Compare commits
240 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71b4f47159 | ||
|
|
347b53659c | ||
|
|
16f32e0df5 | ||
|
|
171287fac6 | ||
|
|
9d05cd6931 | ||
|
|
a9e847372a | ||
|
|
1eba53cc0e | ||
|
|
c5a0077a01 | ||
|
|
2b07dd1db4 | ||
|
|
28b3380a45 | ||
|
|
564338656d | ||
|
|
29b2e4f5ec | ||
|
|
c7ab3aeb32 | ||
|
|
4b771dafe4 | ||
|
|
71393bd35a | ||
|
|
f7e2697e56 | ||
|
|
608644bd83 | ||
|
|
7563e52aba | ||
|
|
039dde0ccb | ||
|
|
abbde79ab0 | ||
|
|
ead958e603 | ||
|
|
6b7f310cd7 | ||
|
|
451186ac4e | ||
|
|
b8b3b7f0af | ||
|
|
5ee71feac4 | ||
|
|
a2e65e2bbd | ||
|
|
e8ad508021 | ||
|
|
aa2a4fac2b | ||
|
|
d5fda558c1 | ||
|
|
171b98717a | ||
|
|
da07ef0e2c | ||
|
|
6c9e226d67 | ||
|
|
d3884358be | ||
|
|
0ebeee3641 | ||
|
|
bd190d5a4e | ||
|
|
b1f09b9ef0 | ||
|
|
ac556aea34 | ||
|
|
87ab3702fe | ||
|
|
83556f9ab2 | ||
|
|
43c18552c1 | ||
|
|
dc54c76435 | ||
|
|
9a16cd026f | ||
|
|
e4710a16b0 | ||
|
|
ae2e99f6d3 | ||
|
|
c182a19fa5 | ||
|
|
2ddeaf4eb8 | ||
|
|
b4fd071efb | ||
|
|
9344280d5b | ||
|
|
ad037536cd | ||
|
|
d8e8af00b6 | ||
|
|
1e651a97b7 | ||
|
|
c2e49e169f | ||
|
|
6662cb0f5e | ||
|
|
c00d85890a | ||
|
|
c42c9ffb3d | ||
|
|
b5661976eb | ||
|
|
c1e66f8fc2 | ||
|
|
c2715040fe | ||
|
|
fc17dac2a5 | ||
|
|
0dfd8e3ba1 | ||
|
|
acbfd6d81d | ||
|
|
0d268a01e1 | ||
|
|
1e9cbb4633 | ||
|
|
7d3683df98 | ||
|
|
3b10bbbcd2 | ||
|
|
3ea40683c9 | ||
|
|
e6b789131a | ||
|
|
613dec0571 | ||
|
|
36b3692e9e | ||
|
|
59cde2fc8c | ||
|
|
e8027b3b95 | ||
|
|
579ab4c831 | ||
|
|
f54322c1f7 | ||
|
|
a5b85c533a | ||
|
|
149340669a | ||
|
|
5165bf5b29 | ||
|
|
fbc04ba199 | ||
|
|
e33f2d40dd | ||
|
|
bad62f0a16 | ||
|
|
b393b58cc1 | ||
|
|
4480825408 | ||
|
|
10fb31f1e5 | ||
|
|
789a2d8a88 | ||
|
|
b9ebd44c30 | ||
|
|
a65edf8fd5 | ||
|
|
89f33160bc | ||
|
|
e96a7657cd | ||
|
|
492270a3bf | ||
|
|
1cd34e3853 | ||
|
|
3ad7b389da | ||
|
|
bc58913272 | ||
|
|
415ba2bd17 | ||
|
|
a338f4c436 | ||
|
|
24507e22bb | ||
|
|
8e208b7dd3 | ||
|
|
d5c585b118 | ||
|
|
56b63b3b4c | ||
|
|
8c64d77276 | ||
|
|
406056bf52 | ||
|
|
f960d65e08 | ||
|
|
a3fc62a7c0 | ||
|
|
5a4e996b37 | ||
|
|
200647f0c5 | ||
|
|
99d6395845 | ||
|
|
fc0d5083e6 | ||
|
|
478a87c8d0 | ||
|
|
d3a8b37cf3 | ||
|
|
0f99cb20b0 | ||
|
|
df54864e43 | ||
|
|
9beae1f9c4 | ||
|
|
0761ee2f4a | ||
|
|
314dc5ba9e | ||
|
|
02a086e083 | ||
|
|
3a616f5e37 | ||
|
|
3f12ce28d8 | ||
|
|
a913c1fa55 | ||
|
|
363803ea9b | ||
|
|
1bbb9f432c | ||
|
|
4854afeb32 | ||
|
|
507832ac2b | ||
|
|
146b36d9ce | ||
|
|
77276d48ae | ||
|
|
c3f253ef64 | ||
|
|
93e51a6d43 | ||
|
|
a26d72f99d | ||
|
|
cd8b714ea6 | ||
|
|
909e9b3ee9 | ||
|
|
d10bcda693 | ||
|
|
7ddb673624 | ||
|
|
bbd11b90eb | ||
|
|
4fee737981 | ||
|
|
14143bf0ce | ||
|
|
0e8a9b078c | ||
|
|
c2ca459882 | ||
|
|
f80a11a982 | ||
|
|
29650cef8c | ||
|
|
4cf8017d7b | ||
|
|
f807b1f48c | ||
|
|
dc7e040087 | ||
|
|
4262716043 | ||
|
|
5f25238ba6 | ||
|
|
cf95129fc6 | ||
|
|
f8b6654cd6 | ||
|
|
cf001082e2 | ||
|
|
c8e2890f60 | ||
|
|
9075736cf1 | ||
|
|
e1cba702f7 | ||
|
|
9ffc4cf9dd | ||
|
|
94647152fc | ||
|
|
e4a69a63c0 | ||
|
|
05e2b483a8 | ||
|
|
f2e8c0c213 | ||
|
|
43c6be0859 | ||
|
|
fb5ef928fd | ||
|
|
3f9be575fd | ||
|
|
9985cfc50a | ||
|
|
be018b39fc | ||
|
|
da15c46429 | ||
|
|
0eb71f44d4 | ||
|
|
aa6618f002 | ||
|
|
e55e28e852 | ||
|
|
0e1c937892 | ||
|
|
65a112a4e9 | ||
|
|
0448ebb0e0 | ||
|
|
fec7d21ca4 | ||
|
|
2d29aa3666 | ||
|
|
23a4f5fa04 | ||
|
|
80bcc21562 | ||
|
|
5dcf0a6622 | ||
|
|
99c1be49a6 | ||
|
|
2a46b4ece7 | ||
|
|
1d77bbdf5a | ||
|
|
943517f07e | ||
|
|
93b664de45 | ||
|
|
695fed709e | ||
|
|
51735ac89d | ||
|
|
5a49699098 | ||
|
|
b2b6e82735 | ||
|
|
fd3ed2b7da | ||
|
|
4da018b8ce | ||
|
|
99ad315832 | ||
|
|
4bd20406a2 | ||
|
|
48b51c549a | ||
|
|
af0a95ddb8 | ||
|
|
5db9b6b9b5 | ||
|
|
e1bee48834 | ||
|
|
704f6fed89 | ||
|
|
c05962c6a6 | ||
|
|
7111494545 | ||
|
|
2833a6cfb1 | ||
|
|
e9dc3ff867 | ||
|
|
ca8856d77c | ||
|
|
17948e06d8 | ||
|
|
51777d47c9 | ||
|
|
1714cf6109 | ||
|
|
2a4cc75f0a | ||
|
|
486cccd1da | ||
|
|
4a93f3e147 | ||
|
|
64871efe6d | ||
|
|
3e382a42e1 | ||
|
|
ff973beb32 | ||
|
|
ced9908da5 | ||
|
|
ea52f821c5 | ||
|
|
cf2b32c66d | ||
|
|
462da5b99b | ||
|
|
9b481ba8ef | ||
|
|
557bb9cc6a | ||
|
|
2cc06be317 | ||
|
|
0afd2b4b8c | ||
|
|
818e5cf255 | ||
|
|
1978274686 | ||
|
|
9c95e154c1 | ||
|
|
4f912a7063 | ||
|
|
45cc57058c | ||
|
|
d222ed2dd1 | ||
|
|
fba53984eb | ||
|
|
b810c4b0bf | ||
|
|
6d5a4ad759 | ||
|
|
802521b364 | ||
|
|
466aecb4b8 | ||
|
|
c34f31c869 | ||
|
|
5a1348868e | ||
|
|
45e244f10c | ||
|
|
9b38dd7d74 | ||
|
|
7d1098740b | ||
|
|
b3ff824806 | ||
|
|
db889f217d | ||
|
|
e60ca05e64 | ||
|
|
1831a9b286 | ||
|
|
f3939938b4 | ||
|
|
2c8b07b1cb | ||
|
|
2ef11d5eea | ||
|
|
5d2c618553 | ||
|
|
917c2d82c7 | ||
|
|
8590d8243c | ||
|
|
bc1ddca4f0 | ||
|
|
d4bda0a45d | ||
|
|
6a49176c0e | ||
|
|
bfd44ada12 | ||
|
|
5172135014 |
230
CHANGELOG.md
230
CHANGELOG.md
@@ -1,5 +1,235 @@
|
||||
# ZeroBrane Studio Changelog
|
||||
|
||||
## v0.37 (May 09 2013)
|
||||
|
||||
### Special thanks
|
||||
- To Samuel Dionne-Riel for wxwidgets 2.8 compatibility updates.
|
||||
- To Mat Hopwood for assistance with Marmalade Quick integration.
|
||||
|
||||
### Highlights
|
||||
- Added Marmalade Quick auto-complete support and API documentation.
|
||||
- Added full Marmalade Quick debugging support (requires Quick 1.1+).
|
||||
- Improved Find/Replace behavior and functionality.
|
||||
- Added Recent File history navigation.
|
||||
- Added Preferences menu to simplify access to system/user settings.
|
||||
|
||||
### Improvements
|
||||
- Added Preferences menu to simplify access to system/user settings.
|
||||
- Added Russian translation for Find/Replace dialog and (ref #70).
|
||||
- Added Russian translation for the Preferences menu (ref #70).
|
||||
- Added 'shaking' Find/Replace window when text is not found (closes #146).
|
||||
- Added 'wlua' to the list of recognized Lua extensions.
|
||||
- Added disabling Recent Files menu if the list is empty.
|
||||
- Added TomorrowContrast color scheme (thanks to Sergey Lerg).
|
||||
- Added detaching a child process to avoid crash when exiting during debugging.
|
||||
- Added Recent File history navigation (closes #66).
|
||||
- Added Marmalade auto-complete support and API documentation.
|
||||
- Added processing of `runonstart` when using remote debugging (closes #138).
|
||||
- Added suggesting proper extension after 'Save/Save As' based on current spec.
|
||||
- Added translation setup for Find/Replace dialog (closes #133).
|
||||
- Added `nomousezoom` option to disable zoom with mouse wheel in the editor.
|
||||
- Added selecting text and Cmd-F shortcut in Find dialog on OSX (ref #127).
|
||||
- Improved file activation when debugging is started (closes #137).
|
||||
- Reduced the minimum size of the Output/Console panel.
|
||||
- Refactored Recent Files history to make it faster and simpler.
|
||||
- Refactored and optimized directory scanning when loading IDE files.
|
||||
- Separated settings for function dropdown and project tree fonts (fixes #148).
|
||||
- Updated documentation about default EOL on OSX (ref #102).
|
||||
- Updated highlighting in Watch windows to not use editor styles.
|
||||
- Updated documentation for user settings (ref #113, #55).
|
||||
- Updated Monokai color scheme to fix current line color.
|
||||
|
||||
### Incompatibilities
|
||||
- (dev) `FileSysGet` has been replaced with `FileSysGetRecursive` with a different signature.
|
||||
|
||||
### Fixes
|
||||
- Fixed hiding all panels when switching to Full Screen mode.
|
||||
- Fixed loading a non-existing file.
|
||||
- Fixed activation of non-existing files/folders in the Project tree.
|
||||
- Fixed search results for lines without newline.
|
||||
- Fixed Find/Replace in folders with Unicode names (fixes #147); improved performance.
|
||||
- Fixed Un/Comment commands executed for empty lines.
|
||||
- Fixed fold/unfold for files starting with block/comment.
|
||||
- Fixed history after activating non-existing file in Recent Files.
|
||||
- Fixed scrolling to restored cursor position on OSX (when `usewrap` = false).
|
||||
- Fixed Find/Replace dialog to take Enter on OSX (fixes #140).
|
||||
- Fixed 'breaking' after executing OUT command that never reaches the target level.
|
||||
- Fixed stopping at a breakpoint at the initial line when `startwith` option is specified.
|
||||
- Fixed activation of a file loaded into active tab.
|
||||
- Fixed incorrect tab activation on OSX after using 'Open File'.
|
||||
- Fixed editor activation when file is loaded into an existing tab.
|
||||
- Fixed an error after opening non-existing file from 'Recent Files'.
|
||||
- Fixed blocking on reading app output without processing other events.
|
||||
- Fixed an issue with duplicate lines shown in the editor.
|
||||
- Fixed 'Replace All' to take 'Wrap Around' into account (fixes #132).
|
||||
- Fixed off-by-one error in searching consecutive matches.
|
||||
- Fixed 'Quick Find' not working without current selection (fixes #131).
|
||||
- Fixed looping in auto-complete on mistyped class (fixes #130).
|
||||
- Fixed compatibility with wx2.8 (thanks to Samuel Dionne-Riel; closes #128).
|
||||
- Fixed replacement logic in Find/Replace that could replace selected fragment (ref #127).
|
||||
- Fixed an error caused by allowing multiple Search/Replace windows (fixes #127).
|
||||
|
||||
## v0.361 (Apr 12 2013)
|
||||
|
||||
### Improvements
|
||||
- Added handling of Ctrl-Home and Ctrl-End on OSX (ref #89).
|
||||
- Added line copy/cut for Ctrl-C/Ctrl-X with no selection.
|
||||
- Updated About screen to be more configurable and flexible.
|
||||
- Updated Russian translation (thanks to toiffel).
|
||||
|
||||
### Fixes
|
||||
- Fixed launch command for Corona debugging on Windows.
|
||||
- Fixed 'control' check on OSX that changed with wx2.9.2+ (ref #89).
|
||||
- Fixed wrong tab activated on OSX after using New file in some cases.
|
||||
- Fixed cursor not being visible in some cases after file is loaded (ref #116).
|
||||
|
||||
## v0.36 (Apr 08 2013)
|
||||
|
||||
### Highlights
|
||||
- Added 32bit and 64bit **Linux binaries**.
|
||||
- Enabled **full debugging for Corona on OSX**.
|
||||
- Improved **debugger performance**.
|
||||
- Improved **performance of tab and project switching**.
|
||||
- Added **multiple selection and multi-cursor editing**.
|
||||
- Made Stack and Watch windows dockable and toggleable.
|
||||
|
||||
### Special thanks
|
||||
- To toiffel for build improvements and continuous work on wxwidgets 2.9 and Linux support.
|
||||
- To Marcel van Herk for testing and feedback on Stack and Watch windows behavior.
|
||||
- To Leo Bartoloni for Italian translation update.
|
||||
- To Fringale for updated French translation.
|
||||
- To neomantra for adding cdata processing in the serializer.
|
||||
|
||||
### Improvements
|
||||
- Added handling of case-insensitive filenames on OSX.
|
||||
- Added cdata processing (thanks to neomantra).
|
||||
- Added universal binaries for luasocket on OSX to allow debugging of 64bit applications (for example, LuaJIT) on OSX.
|
||||
- Added update of Stack and Watch windows after 'Debugging suspended' message.
|
||||
- Added toggling for View menu items.
|
||||
- Added auto-show/hide Stack and Watch windows during debugging (closes #110).
|
||||
- Added ignoring `-psn...` parameter on OSX when reading file names from command line.
|
||||
- Added migration of configuration file on Windows (helps #89).
|
||||
- Added check for different spellings of the same folder in the project tree.
|
||||
- Added scripts to install build prerequisites on Linux (helps #89).
|
||||
- Added linux binaries with support for x86 and x64 (helps #89).
|
||||
- Added window list button to the notepad with editor tabs.
|
||||
- Added centering of current line during debugging.
|
||||
- Added multiple selection and multi-cursor editing (wx2.9.5+).
|
||||
- Added dll proxy to make LfW libraries to work with the IDE.
|
||||
- Disabled showing 'value' in auto-complete after 'a:' (helps #101).
|
||||
- Enabled full debugging for Corona on OSX.
|
||||
- Improved debugging performance.
|
||||
- Improved performance of tab switching and project tree population.
|
||||
- Improved handling of upvalues with __tostring method in the Stack window.
|
||||
- Increased default font size for OSX; set 'Monaco' as default font (helps #89).
|
||||
- Made stack and watch windows dockable (closes #103).
|
||||
- Optimized project switching and added notebook freezing where possible (ref #89).
|
||||
- Reduced flicker in the project tree when a file is opened (ref #89).
|
||||
- Removed binary libraries not currently used.
|
||||
- Set 'Courier New' as the default font on Linux (ref #89).
|
||||
- Switched to 'native' menu on OSX and added 24x24 icons required (helps #89).
|
||||
- Updated Italian translation (thanks to Leo Bartoloni)
|
||||
- Updated 'method' type in auto-complete to only allow a:b syntax (closes #101).
|
||||
- Updated language files (es, it, ru) with new messages (ref #70).
|
||||
- Updated French translation with latest string changes, fixed a few typos (thanks to Fringale).
|
||||
- Updated Stack and Watch window to not refresh when not visible.
|
||||
- Upgraded Mobdebug (0.5222) to add serialization with metamethods and notification on incomplete output (closes #109).
|
||||
- Updated error messages from loading configuration files.
|
||||
- Updated Linux binaries to use libpng 1.6 with wxwidgets (helps #89).
|
||||
- Updated Windows/OSX build files to only build components needed (helps #89).
|
||||
- Updated windows executable to show properly scaled icons in the Explorer.
|
||||
- Updated status bar to use no border around fields.
|
||||
- Updated large icons for "native" toolbar on OSX (helps #89).
|
||||
- Updated function call indicator to use round box with wxwidgets upgrade (helps #89).
|
||||
- Updated handling of markdown styles to make it more robust (fixes #59).
|
||||
- Updated README with Marmalade Quick support and Corona tutorial.
|
||||
|
||||
### Incompatibilities
|
||||
- Configuration file (.ini) location has changed on Windows. The current file will be copied to the new location.
|
||||
- The debugger now stops on the next executable line after `.start()` call.
|
||||
|
||||
### Fixes
|
||||
- Fixed activating files in the project tree on a case insensitive system.
|
||||
- Fixed the Stack view being partially hidden when the root item is too wide (ref #110).
|
||||
- Fixed left side of the project panel being hidden when a file is activated (fixes #122).
|
||||
- Fixed breakpoint not firing on the first executable line in debugging (helps #121).
|
||||
- Fixed terminating debugging of an empty script.
|
||||
- Fixed reporting of initial line during debugging.
|
||||
- Fixed editor tab activation after closing another tab on Linux (ref #89).
|
||||
- Fixed 'Show tooltip' shortcut not working on Linux (fixes #118; ref #89).
|
||||
- Fixed cursor position being incorrectly restored (fixes #116; ref #89).
|
||||
- Fixed a warning about empty project directory in local console.
|
||||
- Fixed an issue with Enter used to select an item in project dropdown (ref #89).
|
||||
- Fixed an issue with the Project tree when project and app directories are the same.
|
||||
- Fixed debugger output not being suppressed on Linux and using wlua.
|
||||
- Fixed a static analyzer issue with anonymous functions defined in expressions (fixes #3).
|
||||
|
||||
## v0.35 (Feb 10 2013)
|
||||
|
||||
### Highlights
|
||||
- Added support for **debugging Lua 5.2 scripts**.
|
||||
- Added support for **cross-platform remote debugging**.
|
||||
- Added support for starting Gideros **on-device debugging**.
|
||||
- Added support for live coding, script reloading, and coroutine debugging under LuaJIT.
|
||||
- Added **Marmalade Quick** support.
|
||||
- Added **live-coding for Corona** interpreter.
|
||||
- Added editor tab popup menu with 'Close All', 'Close Other', and other items.
|
||||
|
||||
### Special thanks
|
||||
- To Roland Yonaba and Fringale for updates to French translation.
|
||||
- To Fringale for enhanced line-endings handling.
|
||||
- To toiffel for build improvements, continuous work on wxwidgets 2.9 support, and several patches.
|
||||
- To Andy Bower for the stream of feedback on live coding and on-device debugging.
|
||||
|
||||
### Improvements
|
||||
- Added `debugger.runonstart` option to configure if debugging should run immediately after starting.
|
||||
- Added `editor.checkeol` option to configure checking for eol encoding in loaded files.
|
||||
- Added Marmalade Quick support.
|
||||
- Added support for starting Gideros on-device debugging.
|
||||
- Added requesting user attention when stopped during debugging.
|
||||
- Added example for `defaulteol` configuration option.
|
||||
- Added configuration option for compact folding (`editor.`).
|
||||
- Added support for cross-platform remote debugging.
|
||||
- Added support for script reloading and coroutine debugging under LuaJIT (MobDebug 0.514).
|
||||
- Added Russian translation for new messages.
|
||||
- Added handling of malformed UTF8 characters in files (fixes #97).
|
||||
- Added support for debugging Lua 5.2 scripts.
|
||||
- Added workaround for Moai require path issue (fixes #96; fixes #87).
|
||||
- Added editor tab popup menu with 'Close All', 'Close Other', and other items.
|
||||
- Added C/CPP specification file and a configuration example.
|
||||
- Added XCode-like key mapping.
|
||||
- Added removing of file: prefix and url decoding of filepaths (helps #89).
|
||||
- Added a workaround for returning incorrect project folder (helps #89).
|
||||
- Adjusted handling of filepath to work with relative and absolute paths (helps #89).
|
||||
- Enabled live-coding for Corona interpreter.
|
||||
- Improved line-endings handling (Fringale).
|
||||
- Improved reporting of stack and serialization run-time errors.
|
||||
- Updated Gideros interpreter to run debugging immediately after starting; Use `debugger.runonstart = false` to disable.
|
||||
- Updated Linux startup script to use online versions of wxlua packages (deb files).
|
||||
- Updated handling of file: prefix as it's different on Windows and OSX (helps #89).
|
||||
- Updated messages in the starter script.
|
||||
- Updated function call parsing to recognize "func{}" and "func''" syntax.
|
||||
- Updated os.exit() call in local console to exit gracefully.
|
||||
- Updated French translation with various fixes and tweaks (Fringale).
|
||||
- Updated French translation with newly added strings (Fringale).
|
||||
- Updated 'Close page' and its translations.
|
||||
- Updated configuration examples and documentation (helps #55).
|
||||
- Updated the size of the function list dropdown on Windows (helps #89).
|
||||
- Typos fixes, small changes in French translation (Roland Yonaba).
|
||||
|
||||
### Incompatibilities
|
||||
- Gideros debugging is changed to start immediately; use `debugger.runonstart = false` to disable.
|
||||
- Removed mosync support from the debugger into a separate module.
|
||||
- Added mixed end-of-line reporting; use `editor.checkeol = false` to disable.
|
||||
- Added reporting of malformed UTF-8.
|
||||
|
||||
### Fixes
|
||||
- Fixed a rare crash on OSX when closing IDE with an application running under debugger.
|
||||
- Fixed path handling for metalua to avoid conflicts with other modules that may include lexer.lua file.
|
||||
- Fixed executing commands in the Remote console immediately after `mobdebug.start()` (closes #100).
|
||||
- Fixed invalid escape sequence that fails under LuaJIT.
|
||||
- Fixed an issue with spec files when a separator (sep) is not specified.
|
||||
|
||||
## v0.34 (Dec 12 2012)
|
||||
|
||||
### Highlights
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[ZeroBrane Studio](http://studio.zerobrane.com/) is a lightweight Lua IDE with code completion, syntax
|
||||
highlighting, remote debugger, code analyzer, live coding, and debugging
|
||||
support for several Lua engines (LuaJIT, Löve 2D, Moai, Gideros, Corona,
|
||||
support for several Lua engines (LuaJIT, Löve 2D, Moai, Gideros, Corona, Marmalade Quick,
|
||||
MobileLua, GSL-shell, and others). It originated from the [Estrela Editor](http://www.luxinia.de/index.php/Estrela/).
|
||||
|
||||
## Features
|
||||
@@ -12,9 +12,8 @@ MobileLua, GSL-shell, and others). It originated from the [Estrela Editor](http:
|
||||
* Auto-completion for functions, keywords, and custom APIs.
|
||||
* Interactive console to directly test code snippets with local and remote execution.
|
||||
* Integrated debugger (with support for local and remote debugging).
|
||||
* Live coding with Lua ([demo](http://notebook.kulchenko.com/zerobrane/live-coding-in-lua-bret-victor-style)), Löve 2D ([demo](http://notebook.kulchenko.com/zerobrane/live-coding-with-love)), and Gideros ([demo](http://notebook.kulchenko.com/zerobrane/gideros-live-coding-with-zerobrane-studio-ide)).
|
||||
* Live coding with Lua ([demo](http://notebook.kulchenko.com/zerobrane/live-coding-in-lua-bret-victor-style)), Löve 2D ([demo](http://notebook.kulchenko.com/zerobrane/live-coding-with-love)), Gideros ([demo](http://notebook.kulchenko.com/zerobrane/gideros-live-coding-with-zerobrane-studio-ide)), Moai ([demo](http://notebook.kulchenko.com/zerobrane/live-coding-with-moai-and-zerobrane-studio)), and Corona SDK ([demo](http://notebook.kulchenko.com/zerobrane/debugging-and-live-coding-with-corona-sdk-applications-and-zerobrane-studio)).
|
||||
* Support for plugin-like components:
|
||||
- applications: overall control of applications settings;
|
||||
- specs (spec/): file syntax, lexer, keywords (e.g. glsl);
|
||||
- apis (api/): for code-completion and tool-tips;
|
||||
- interpreters (interpreters/): how a project is run;
|
||||
@@ -53,7 +52,7 @@ Loading custom configuration:
|
||||
|
||||
## Where is Estrela?
|
||||
|
||||
The projects have been merged again and zbstudio will lead the future.
|
||||
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
|
||||
|
||||
@@ -739,6 +739,7 @@ return {
|
||||
description = "When called with a file name, it opens the named file (in text mode), and sets its handle as the default input file. When called with a file handle, it simply sets this file handle as the default input file. When called without parameters, it returns the current default input file.\n\nIn case of errors this function raises the error, instead of returning an error code.",
|
||||
args = "([file: string|file])",
|
||||
returns = "([file])",
|
||||
valuetype = "f",
|
||||
},
|
||||
lines = {
|
||||
type = "function",
|
||||
@@ -751,18 +752,21 @@ return {
|
||||
description = "This function opens a file, in the mode specified in the string mode.\n\nIt returns a new file handle, or, in case of errors, nil plus an error message.\n\nThe mode string can be any of the following:\n\n* \"r\": read mode (the default);\n\n* \"w\": write mode;\n\n* \"a\": append mode;\n\n* \"r+\": update mode, all previous data is preserved;\n\n* \"w+\": update mode, all previous data is erased;\n\n* \"a+\": append update mode, previous data is preserved, writing is only allowed at the end of file.\n\nThe mode string can also have a 'b' at the end, which is needed in some systems to open the file in binary mode.",
|
||||
args = "(filename: string [, mode: string])",
|
||||
returns = "(file|nil [, string])",
|
||||
valuetype = "f",
|
||||
},
|
||||
output = {
|
||||
type = "function",
|
||||
description = "When called with a file name, it opens the named file (in text mode), and sets its handle as the default output file. When called with a file handle, it simply sets this file handle as the default output file. When called without parameters, it returns the current default output file.\n\nIn case of errors this function raises the error, instead of returning an error code.",
|
||||
args = "([file: string|file])",
|
||||
returns = "([file])",
|
||||
valuetype = "f",
|
||||
},
|
||||
popen = {
|
||||
type = "function",
|
||||
description = "Starts program prog in a separated process and returns a file handle that you can use to read data from this program (if mode is \"r\", the default) or to write data to this program (if mode is \"w\").\n\nThis function is system dependent and is not available on all platforms.",
|
||||
args = "(prog: string [, mode: string])",
|
||||
returns = "(file|nil [, string])",
|
||||
valuetype = "f",
|
||||
},
|
||||
read = {
|
||||
type = "function",
|
||||
@@ -775,6 +779,7 @@ return {
|
||||
description = "Returns a handle for a temporary file.\n\nThis file is opened in update mode and it is automatically removed when the program ends.",
|
||||
args = "()",
|
||||
returns = "(file)",
|
||||
valuetype = "f",
|
||||
},
|
||||
type = {
|
||||
type = "function",
|
||||
@@ -796,43 +801,43 @@ return {
|
||||
description = "Pseudoclass for operations on file handles.",
|
||||
childs = {
|
||||
close = {
|
||||
type = "function",
|
||||
type = "method",
|
||||
description = "Closes file.\n\nNote that files are automatically closed when their handles are garbage collected, but that takes an unpredictable amount of time to happen.\n\nWhen closing a file handle created with io.popen, file:close returns the same values returned by os.execute. RETURN SPECIAL CASE ADDED IN Lua 5.2.",
|
||||
args = "(file: file)",
|
||||
returns = "(boolean|nil [, string, number])",
|
||||
},
|
||||
flush = {
|
||||
type = "function",
|
||||
type = "method",
|
||||
description = "Saves any written data to file.",
|
||||
args = "(file: file)",
|
||||
returns = "(boolean|nil [, string])",
|
||||
},
|
||||
lines = {
|
||||
type = "function",
|
||||
type = "method",
|
||||
description = "Returns an iterator function that, each time it is called, reads the file according to the given formats.\n\nWhen no format is given, uses \"*l\" as a default. ARGUMENT ADDED IN Lua 5.2.\n\nUnlike io.lines, this function does not close the file when the loop ends.\n\nIn case of errors this function raises the error, instead of returning an error code.",
|
||||
args = "(file: file, ...)",
|
||||
returns = "(function)",
|
||||
},
|
||||
read = {
|
||||
type = "function",
|
||||
type = "method",
|
||||
description = "Reads the file file, according to the given formats, which specify what to read.\n\nFor each format, the function returns a string (or a number) with the characters read, or nil if it cannot read data with the specified format. When called without formats, it uses a default format that reads the next line (see below).\n\nThe available formats are\n\n* \"*n\": reads a number; this is the only format that returns a number instead of a string.\n\n* \"*a\": reads the whole file, starting at the current position. On end of file, it returns the empty string.\n\n* \"*l\": reads the next line skipping the end of line, returning nil on end of file. This is the default format.\n\n* \"*L\": reads the next line keeping the end of line (if present), returning nil on end of file. VALUE ADDED IN Lua 5.2.\n\n* number: reads a string with up to this number of bytes, returning nil on end of file. If number is zero, it reads nothing and returns an empty string, or nil on end of file.",
|
||||
args = "(file: file, ...)",
|
||||
returns = "(...)",
|
||||
},
|
||||
seek = {
|
||||
type = "function",
|
||||
description = "Sets and gets the file position, measured from the beginning of the file, to the position given by offset plus a base specified by the string whence.\n\nThe string whence is specified as follows:\n\n* \"set\": base is position 0 (beginning of the file);\n\n* \"cur\": base is current position;\n\n* \"end\": base is end of file.\n\nIn case of success, seek returns the final file position, measured in bytes from the beginning of the file. If seek fails, it returns nil, plus a string describing the error.\n\The default value for whence is \"cur\", and for offset is 0. Therefore, the call file:seek() returns the current file position, without changing it; the call file:seek(\"set\") sets the position to the beginning of the file (and returns 0); and the call file:seek(\"end\") sets the position to the end of the file, and returns its size.",
|
||||
type = "method",
|
||||
description = "Sets and gets the file position, measured from the beginning of the file, to the position given by offset plus a base specified by the string whence.\n\nThe string whence is specified as follows:\n\n* \"set\": base is position 0 (beginning of the file);\n\n* \"cur\": base is current position;\n\n* \"end\": base is end of file.\n\nIn case of success, seek returns the final file position, measured in bytes from the beginning of the file. If seek fails, it returns nil, plus a string describing the error.\n\nThe default value for whence is \"cur\", and for offset is 0. Therefore, the call file:seek() returns the current file position, without changing it; the call file:seek(\"set\") sets the position to the beginning of the file (and returns 0); and the call file:seek(\"end\") sets the position to the end of the file, and returns its size.",
|
||||
args = "(file: file, [whence: string [, offset: number]])",
|
||||
returns = "(number|nil [, string])",
|
||||
},
|
||||
setvbuf = {
|
||||
type = "function",
|
||||
type = "method",
|
||||
description = "Sets the buffering mode for an output file.\n\nThere are three available modes:\n\n* \"no\": no buffering; the result of any output operation appears immediately.\n\n* \"full\": full buffering; output operation is performed only when the buffer is full or when you explicitly flush the file (see io.flush).\n\n* \"line\": line buffering; output is buffered until a newline is output or there is any input from some special files (such as a terminal device).\n\nFor the last two cases, size specifies the size of the buffer, in bytes. The default is an appropriate size.",
|
||||
args = "(file: file, mode: string [, size: number])",
|
||||
returns = "(boolean|nil [, string])",
|
||||
},
|
||||
write = {
|
||||
type = "function",
|
||||
type = "method",
|
||||
description = "Writes the value of each of its arguments to file.\n\nThe arguments must be strings or numbers.\n\nIn case of success, this function returns file (RETURN CHANGED IN Lua 5.2, BOOLEAN IN LUA 5.1). Otherwise it returns nil plus a string describing the error.",
|
||||
args = "(file: file, ...)",
|
||||
returns = "(file|nil [, string])",
|
||||
|
||||
1244
api/lua/corona.lua
1244
api/lua/corona.lua
File diff suppressed because it is too large
Load Diff
2488
api/lua/marmalade.lua
Normal file
2488
api/lua/marmalade.lua
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
BIN
bin/clibs/mime/core.dll
Executable file → Normal file
BIN
bin/clibs/mime/core.dll
Executable file → Normal file
Binary file not shown.
BIN
bin/clibs/mime/core.dylib
Normal file → Executable file
BIN
bin/clibs/mime/core.dylib
Normal file → Executable file
Binary file not shown.
Binary file not shown.
BIN
bin/clibs/socket/core.dll
Executable file → Normal file
BIN
bin/clibs/socket/core.dll
Executable file → Normal file
Binary file not shown.
BIN
bin/clibs/socket/core.dylib
Normal file → Executable file
BIN
bin/clibs/socket/core.dylib
Normal file → Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
bin/liblua.dylib
Executable file
BIN
bin/liblua.dylib
Executable file
Binary file not shown.
BIN
bin/libwx.dylib
Normal file → Executable file
BIN
bin/libwx.dylib
Normal file → Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
bin/libzmq.dll
BIN
bin/libzmq.dll
Binary file not shown.
BIN
bin/linux/x64/clibs/mime/core.so
Normal file
BIN
bin/linux/x64/clibs/mime/core.so
Normal file
Binary file not shown.
BIN
bin/linux/x64/clibs/socket/core.so
Normal file
BIN
bin/linux/x64/clibs/socket/core.so
Normal file
Binary file not shown.
BIN
bin/linux/x64/libwx.so
Normal file
BIN
bin/linux/x64/libwx.so
Normal file
Binary file not shown.
BIN
bin/linux/x64/lua
Executable file
BIN
bin/linux/x64/lua
Executable file
Binary file not shown.
BIN
bin/linux/x86/clibs/mime/core.so
Normal file
BIN
bin/linux/x86/clibs/mime/core.so
Normal file
Binary file not shown.
BIN
bin/linux/x86/clibs/socket/core.so
Normal file
BIN
bin/linux/x86/clibs/socket/core.so
Normal file
Binary file not shown.
BIN
bin/linux/x86/libwx.so
Normal file
BIN
bin/linux/x86/libwx.so
Normal file
Binary file not shown.
BIN
bin/linux/x86/lua
Executable file
BIN
bin/linux/x86/lua
Executable file
Binary file not shown.
Binary file not shown.
BIN
bin/lua.exe
Executable file → Normal file
BIN
bin/lua.exe
Executable file → Normal file
Binary file not shown.
BIN
bin/lua5.1.dll
Executable file → Normal file
BIN
bin/lua5.1.dll
Executable file → Normal file
Binary file not shown.
BIN
bin/lua51.dll
BIN
bin/lua51.dll
Binary file not shown.
BIN
bin/winapi.dll
BIN
bin/winapi.dll
Binary file not shown.
BIN
bin/wx.dll
Executable file → Normal file
BIN
bin/wx.dll
Executable file → Normal file
Binary file not shown.
Binary file not shown.
@@ -1,42 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
|
||||
TEMPLATE_DMG=/tmp/ZeroBraneStudio-template.dmg
|
||||
BUILT_DMG=ZeroBraneStudio.dmg
|
||||
WKDIR=/tmp/zbs-build
|
||||
|
||||
# remove problematic symlink
|
||||
rm ../zbstudio/ZeroBraneStudio.app/Contents/ZeroBraneStudio
|
||||
|
||||
bunzip2 -kf ZeroBraneStudio.dmg.bz2
|
||||
mv ZeroBraneStudio.dmg $TEMPLATE_DMG
|
||||
hdiutil attach "${TEMPLATE_DMG}" -noautoopen -quiet -mountpoint "${WKDIR}"
|
||||
|
||||
rm -rf "${WKDIR}/ZeroBraneStudio.app"
|
||||
|
||||
# copy the app to where it should be
|
||||
cp -pr "../zbstudio/ZeroBraneStudio.app" "${WKDIR}/ZeroBraneStudio.app"
|
||||
|
||||
mkdir "${WKDIR}/ZeroBraneStudio.app/Contents/ZeroBraneStudio"
|
||||
|
||||
# only pick the files listed in manifests and 'myprograms' (if exists)
|
||||
if [[ -d ../myprograms ]]; then MYPROGRAMS=$(cd ..; find myprograms -iname *.lua); fi
|
||||
(cd ".."; tar cf - $MYPROGRAMS $(< zbstudio/MANIFEST) $(< zbstudio/MANIFEST-bin-macos) | (cd "${WKDIR}/ZeroBraneStudio.app/Contents/ZeroBraneStudio/"; tar xf -))
|
||||
|
||||
codesign -s "ZeroBrane LLC" ${WKDIR}/ZeroBraneStudio.app
|
||||
codesign --signature-size 6400 -s "ZeroBrane LLC" ${WKDIR}/ZeroBraneStudio.app/Contents/ZeroBraneStudio/bin/lua.app
|
||||
|
||||
# clean up
|
||||
sudo rm -rf "${WKDIR}/.Trashes"
|
||||
sudo rm -rf "${WKDIR}/.fseventsd"
|
||||
|
||||
hdiutil detach "${WKDIR}" -quiet -force
|
||||
hdiutil convert "${TEMPLATE_DMG}" -quiet -format UDZO -imagekey zlib-level=9 -o "${BUILT_DMG}"
|
||||
|
||||
rm -f "${TEMPLATE_DMG}"
|
||||
|
||||
cd ../zbstudio/ZeroBraneStudio.app/Contents
|
||||
ln -s ../../.. ZeroBraneStudio
|
||||
|
||||
echo Built ${BUILT_DMG}.
|
||||
22
build/build-linux-prep-deb.sh
Executable file
22
build/build-linux-prep-deb.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
# this script installs prerequisites to build binary files on Linux with deb
|
||||
|
||||
sudo apt-get install git-core
|
||||
sudo apt-get install g++
|
||||
sudo apt-get install subversion
|
||||
sudo apt-get install libgtk2.0-dev
|
||||
|
||||
# install cmake as wxwidgets needs 2.8.4+ but "sudo apt-get install cmake"
|
||||
# only installs 2.8.0 on some systems (like Ubuntu 10.4)
|
||||
mkdir build-cmake
|
||||
cd build-cmake
|
||||
wget http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz
|
||||
gunzip cmake-2.8.10.2.tar.gz
|
||||
tar xvf cmake-2.8.10.2.tar
|
||||
cd cmake-2.8.10.2
|
||||
./bootstrap
|
||||
make
|
||||
sudo make install
|
||||
cd ../..
|
||||
rm -rf build-cmake
|
||||
9
build/build-linux-prep-rpm.sh
Normal file
9
build/build-linux-prep-rpm.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# this script installs prerequisites to build binary files on Linux with rpm
|
||||
|
||||
sudo yum install gcc-c++
|
||||
sudo yum install git
|
||||
sudo yum install svn
|
||||
sudo yum install cmake
|
||||
sudo yum install gtk2-devel
|
||||
190
build/build-linux.sh
Executable file
190
build/build-linux.sh
Executable file
@@ -0,0 +1,190 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$(uname -m)" = "x86_64" ]; then
|
||||
FPIC="-fpic"
|
||||
ARCH="x64"
|
||||
else
|
||||
FPIC=""
|
||||
ARCH="x86"
|
||||
fi
|
||||
|
||||
# ZBS binary directory
|
||||
BIN_DIR="$(dirname "$PWD")/bin/linux/$ARCH"
|
||||
|
||||
# temporary installation directory for dependencies
|
||||
INSTALL_DIR="$PWD/deps"
|
||||
|
||||
# number of parallel jobs used for building
|
||||
MAKEFLAGS="-j4"
|
||||
|
||||
# flags for manual building with gcc
|
||||
BUILD_FLAGS="-O2 -shared -s -I $INSTALL_DIR/include -L $INSTALL_DIR/lib $FPIC"
|
||||
|
||||
# paths configuration
|
||||
WXWIDGETS_BASENAME="wxWidgets"
|
||||
WXWIDGETS_URL="http://svn.wxwidgets.org/svn/wx/wxWidgets/trunk"
|
||||
|
||||
LIBPNG_BASENAME="libpng-1.6.0"
|
||||
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"
|
||||
|
||||
LUA_BASENAME="lua-5.1.5"
|
||||
LUA_FILENAME="$LUA_BASENAME.tar.gz"
|
||||
LUA_URL="http://www.lua.org/ftp/$LUA_FILENAME"
|
||||
|
||||
WXLUA_BASENAME="wxlua"
|
||||
WXLUA_URL="https://wxlua.svn.sourceforge.net/svnroot/wxlua/trunk"
|
||||
|
||||
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"
|
||||
|
||||
# exit if the command line is empty
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: $0 LIBRARY..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# iterate through the command line arguments
|
||||
for ARG in "$@"; do
|
||||
case $ARG in
|
||||
wxwidgets)
|
||||
BUILD_WXWIDGETS=true
|
||||
;;
|
||||
lua)
|
||||
BUILD_LUA=true
|
||||
;;
|
||||
wxlua)
|
||||
BUILD_WXLUA=true
|
||||
;;
|
||||
luasocket)
|
||||
BUILD_LUASOCKET=true
|
||||
;;
|
||||
all)
|
||||
BUILD_WXWIDGETS=true
|
||||
BUILD_LUA=true
|
||||
BUILD_WXLUA=true
|
||||
BUILD_LUASOCKET=true
|
||||
;;
|
||||
*)
|
||||
echo "Error: invalid argument $ARG"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# check for g++
|
||||
if [ ! "$(which g++)" ]; then
|
||||
echo "Error: g++ isn't found. Please install GNU C++ compiler."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check for cmake
|
||||
if [ ! "$(which cmake)" ]; then
|
||||
echo "Error: cmake isn't found. Please install CMake and add it to PATH."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check for svn
|
||||
if [ ! "$(which svn)" ]; then
|
||||
echo "Error: svn isn't found. Please install console SVN client."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check for wget
|
||||
if [ ! "$(which wget)" ]; then
|
||||
echo "Error: wget isn't found. Please install GNU Wget."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# create the installation directory
|
||||
mkdir -p "$INSTALL_DIR" || { echo "Error: cannot create directory $INSTALL_DIR"; exit 1; }
|
||||
|
||||
# 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; }
|
||||
tar -xzf "$LIBPNG_FILENAME"
|
||||
(cd "$LIBPNG_BASENAME"; ./configure --with-libpng-prefix=wxpng_; 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"
|
||||
|
||||
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"
|
||||
make $MAKEFLAGS || { echo "Error: failed to build wxWidgets"; exit 1; }
|
||||
make install
|
||||
cd ..
|
||||
rm -rf "$WXWIDGETS_BASENAME" "$LIBPNG_FILENAME"
|
||||
fi
|
||||
|
||||
# build Lua
|
||||
if [ $BUILD_LUA ]; then
|
||||
wget -c "$LUA_URL" -O "$LUA_FILENAME" || { echo "Error: failed to download Lua"; exit 1; }
|
||||
tar -xzf "$LUA_FILENAME"
|
||||
cd "$LUA_BASENAME"
|
||||
# use POSIX as it has minimum dependencies (no readline and no ncurses required)
|
||||
# LUA_USE_DLOPEN is required for loading libraries
|
||||
(cd src; make all MYCFLAGS="$FPIC -DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E -ldl") || { echo "Error: failed to build Lua"; exit 1; }
|
||||
make install INSTALL_TOP="$INSTALL_DIR"
|
||||
cd ..
|
||||
rm -rf "$LUA_FILENAME" "$LUA_BASENAME"
|
||||
fi
|
||||
|
||||
# build wxLua
|
||||
if [ $BUILD_WXLUA ]; then
|
||||
svn co "$WXLUA_URL" "$WXLUA_BASENAME" || { echo "Error: failed to checkout wxLua"; exit 1; }
|
||||
cd "$WXLUA_BASENAME/wxLua"
|
||||
# the following patches wxlua source to fix live coding support in wxlua apps
|
||||
# http://www.mail-archive.com/wxlua-users@lists.sourceforge.net/msg03225.html
|
||||
sed -i 's/\(m_wxlState = wxLuaState(wxlState.GetLuaState(), wxLUASTATE_GETSTATE|wxLUASTATE_ROOTSTATE);\)/\/\/ removed by ZBS build process \/\/ \1/' modules/wxlua/wxlcallb.cpp
|
||||
cmake -G "Unix Makefiles" -DBUILD_INSTALL_PREFIX="$INSTALL_DIR" -DCMAKE_BUILD_TYPE=MinSizeRel -DBUILD_SHARED_LIBS=FALSE \
|
||||
-DwxWidgets_CONFIG_EXECUTABLE="$INSTALL_DIR/bin/wx-config" \
|
||||
-DwxWidgets_COMPONENTS="stc;html;aui;adv;core;net;base" \
|
||||
-DwxLuaBind_COMPONENTS="stc;html;aui;adv;core;net;base" -DwxLua_LUA_LIBRARY_USE_BUILTIN=FALSE \
|
||||
-DwxLua_LUA_INCLUDE_DIR="$INSTALL_DIR/include" -DwxLua_LUA_LIBRARY="$INSTALL_DIR/lib/liblua.a" .
|
||||
(cd modules/luamodule; make $MAKEFLAGS) || { echo "Error: failed to build wxLua"; exit 1; }
|
||||
(cd modules/luamodule; make install/strip)
|
||||
[ -f "$INSTALL_DIR/lib/libwx.so" ] || { echo "Error: libwx.so isn't found"; exit 1; }
|
||||
cd ../..
|
||||
rm -rf "$WXLUA_BASENAME"
|
||||
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"
|
||||
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 \
|
||||
|| { echo "Error: failed to build LuaSocket"; exit 1; }
|
||||
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/5.1/socket/core.so" \
|
||||
src/{auxiliar.c,buffer.c,except.c,inet.c,io.c,luasocket.c,options.c,select.c,tcp.c,timeout.c,udp.c,usocket.c} -llua \
|
||||
|| { echo "Error: failed to build LuaSocket"; exit 1; }
|
||||
mkdir -p "$INSTALL_DIR/share/lua/5.1/socket"
|
||||
cp src/{ftp.lua,http.lua,smtp.lua,tp.lua,url.lua} "$INSTALL_DIR/share/lua/5.1/socket"
|
||||
cp src/{ltn12.lua,mime.lua,socket.lua} "$INSTALL_DIR/share/lua/5.1"
|
||||
[ -f "$INSTALL_DIR/lib/lua/5.1/mime/core.so" ] || { echo "Error: mime/core.so isn't found"; exit 1; }
|
||||
[ -f "$INSTALL_DIR/lib/lua/5.1/socket/core.so" ] || { echo "Error: socket/core.so isn't found"; exit 1; }
|
||||
cd ..
|
||||
rm -rf "$LUASOCKET_FILENAME" "$LUASOCKET_BASENAME"
|
||||
fi
|
||||
|
||||
# now copy the compiled dependencies to ZBS binary directory
|
||||
mkdir -p "$BIN_DIR" || { echo "Error: cannot create directory $BIN_DIR"; exit 1; }
|
||||
[ $BUILD_LUA ] && cp "$INSTALL_DIR/bin/lua" "$BIN_DIR"
|
||||
[ $BUILD_WXLUA ] && cp "$INSTALL_DIR/lib/libwx.so" "$BIN_DIR"
|
||||
if [ $BUILD_LUASOCKET ]; then
|
||||
mkdir -p "$BIN_DIR/clibs/"{mime,socket}
|
||||
cp "$INSTALL_DIR/lib/lua/5.1/mime/core.so" "$BIN_DIR/clibs/mime"
|
||||
cp "$INSTALL_DIR/lib/lua/5.1/socket/core.so" "$BIN_DIR/clibs/socket"
|
||||
fi
|
||||
|
||||
# show a message about successful completion
|
||||
echo "*** Build has been successfully completed ***"
|
||||
exit 0
|
||||
189
build/build-macosx.sh
Executable file
189
build/build-macosx.sh
Executable file
@@ -0,0 +1,189 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ZBS binary directory
|
||||
BIN_DIR="$(dirname "$PWD")/bin"
|
||||
|
||||
# temporary installation directory for dependencies
|
||||
INSTALL_DIR="$PWD/deps"
|
||||
|
||||
# Mac OS X global settings
|
||||
MACOSX_ARCH="i386"
|
||||
MACOSX_VERSION="10.6"
|
||||
MACOSX_SDK_PATH="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.6.sdk"
|
||||
|
||||
# number of parallel jobs used for building
|
||||
MAKEFLAGS="-j4"
|
||||
|
||||
# flags for manual building with gcc; build universal binaries for luasocket
|
||||
MACOSX_FLAGS="-arch $MACOSX_ARCH -mmacosx-version-min=$MACOSX_VERSION -isysroot $MACOSX_SDK_PATH"
|
||||
BUILD_FLAGS="-O2 -arch x86_64 -dynamiclib -undefined dynamic_lookup $MACOSX_FLAGS -I $INSTALL_DIR/include -L $INSTALL_DIR/lib"
|
||||
|
||||
# paths configuration
|
||||
WXWIDGETS_BASENAME="wxWidgets"
|
||||
WXWIDGETS_URL="http://svn.wxwidgets.org/svn/wx/wxWidgets/trunk"
|
||||
|
||||
LUA_BASENAME="lua-5.1.5"
|
||||
LUA_FILENAME="$LUA_BASENAME.tar.gz"
|
||||
LUA_URL="http://www.lua.org/ftp/$LUA_FILENAME"
|
||||
|
||||
WXLUA_BASENAME="wxlua"
|
||||
WXLUA_URL="https://wxlua.svn.sourceforge.net/svnroot/wxlua/trunk"
|
||||
|
||||
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"
|
||||
|
||||
# exit if the command line is empty
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: $0 LIBRARY..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# iterate through the command line arguments
|
||||
for ARG in "$@"; do
|
||||
case $ARG in
|
||||
wxwidgets)
|
||||
BUILD_WXWIDGETS=true
|
||||
;;
|
||||
lua)
|
||||
BUILD_LUA=true
|
||||
;;
|
||||
wxlua)
|
||||
BUILD_WXLUA=true
|
||||
;;
|
||||
luasocket)
|
||||
BUILD_LUASOCKET=true
|
||||
;;
|
||||
all)
|
||||
BUILD_WXWIDGETS=true
|
||||
BUILD_LUA=true
|
||||
BUILD_WXLUA=true
|
||||
BUILD_LUASOCKET=true
|
||||
;;
|
||||
*)
|
||||
echo "Error: invalid argument $ARG"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# check for g++
|
||||
if [ ! "$(which g++)" ]; then
|
||||
echo "Error: g++ isn't found. Please install GNU C++ compiler."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check for cmake
|
||||
if [ ! "$(which cmake)" ]; then
|
||||
echo "Error: cmake isn't found. Please install CMake and add it to PATH."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check for svn
|
||||
if [ ! "$(which svn)" ]; then
|
||||
echo "Error: svn isn't found. Please install console SVN client."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check for wget
|
||||
if [ ! "$(which wget)" ]; then
|
||||
echo "Error: wget isn't found. Please install GNU Wget."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# create the installation directory
|
||||
mkdir -p "$INSTALL_DIR" || { echo "Error: cannot create directory $INSTALL_DIR"; exit 1; }
|
||||
|
||||
# build wxWidgets
|
||||
if [ $BUILD_WXWIDGETS ]; then
|
||||
svn co "$WXWIDGETS_URL" "$WXWIDGETS_BASENAME" || { echo "Error: failed to checkout wxWidgets"; exit 1; }
|
||||
cd "$WXWIDGETS_BASENAME"
|
||||
./configure --prefix="$INSTALL_DIR" --disable-debug --disable-shared --enable-unicode \
|
||||
--with-libjpeg=builtin --with-libpng=builtin --with-libtiff=no --with-expat=no \
|
||||
--with-zlib=builtin --disable-richtext \
|
||||
--enable-macosx_arch=$MACOSX_ARCH --with-macosx-version-min=$MACOSX_VERSION --with-macosx-sdk="$MACOSX_SDK_PATH" \
|
||||
--with-osx_cocoa CFLAGS="-Os" CXXFLAGS="-Os"
|
||||
make $MAKEFLAGS || { echo "Error: failed to build wxWidgets"; exit 1; }
|
||||
make install
|
||||
cd ..
|
||||
rm -rf "$WXWIDGETS_BASENAME"
|
||||
fi
|
||||
|
||||
# build Lua
|
||||
if [ $BUILD_LUA ]; then
|
||||
wget -c "$LUA_URL" -O "$LUA_FILENAME" || { echo "Error: failed to download Lua"; exit 1; }
|
||||
tar -xzf "$LUA_FILENAME"
|
||||
cd "$LUA_BASENAME"
|
||||
sed -i "" 's/PLATS=/& macosx_dylib/' Makefile
|
||||
printf "macosx_dylib:\n" >> src/Makefile
|
||||
printf "\t\$(MAKE) LUA_A=\"liblua.dylib\" AR=\"\$(CC) -dynamiclib $MACOSX_FLAGS -o\" RANLIB=\"strip -u -r\" \\\\\n" >> src/Makefile
|
||||
printf "\tMYCFLAGS=\"-DLUA_USE_LINUX $MACOSX_FLAGS\" MYLDFLAGS=\"$MACOSX_FLAGS\" MYLIBS=\"-lreadline\" lua\n" >> src/Makefile
|
||||
printf "\t\$(MAKE) MYCFLAGS=\"-DLUA_USE_LINUX $MACOSX_FLAGS\" MYLDFLAGS=\"$MACOSX_FLAGS\" luac\n" >> src/Makefile
|
||||
make macosx_dylib || { echo "Error: failed to build Lua"; exit 1; }
|
||||
make install INSTALL_TOP="$INSTALL_DIR"
|
||||
strip -u -r "$INSTALL_DIR/bin/lua"
|
||||
cp src/liblua.dylib "$INSTALL_DIR/lib"
|
||||
[ -f "$INSTALL_DIR/lib/liblua.dylib" ] || { echo "Error: liblua.dylib isn't found"; exit 1; }
|
||||
cd ..
|
||||
rm -rf "$LUA_FILENAME" "$LUA_BASENAME"
|
||||
fi
|
||||
|
||||
# build wxLua
|
||||
if [ $BUILD_WXLUA ]; then
|
||||
svn co "$WXLUA_URL" "$WXLUA_BASENAME" || { echo "Error: failed to checkout wxLua"; exit 1; }
|
||||
cd "$WXLUA_BASENAME/wxLua"
|
||||
# the following patches wxlua source to fix live coding support in wxlua apps
|
||||
# http://www.mail-archive.com/wxlua-users@lists.sourceforge.net/msg03225.html
|
||||
sed -i "" 's/\(m_wxlState = wxLuaState(wxlState.GetLuaState(), wxLUASTATE_GETSTATE|wxLUASTATE_ROOTSTATE);\)/\/\/ removed by ZBS build process \/\/ \1/' modules/wxlua/wxlcallb.cpp
|
||||
cmake -G "Unix Makefiles" -DBUILD_INSTALL_PREFIX="$INSTALL_DIR" -DCMAKE_BUILD_TYPE=MinSizeRel -DBUILD_SHARED_LIBS=FALSE \
|
||||
-DCMAKE_OSX_ARCHITECTURES=$MACOSX_ARCH -DCMAKE_OSX_DEPLOYMENT_TARGET=$MACOSX_VERSION CMAKE_OSX_SYSROOT="$MACOSX_SDK_PATH" \
|
||||
-DCMAKE_C_COMPILER=/usr/bin/gcc -DCMAKE_CXX_COMPILER=/usr/bin/g++ -DwxWidgets_CONFIG_EXECUTABLE="$INSTALL_DIR/bin/wx-config" \
|
||||
-DwxWidgets_COMPONENTS="stc;html;aui;adv;core;net;base" \
|
||||
-DwxLuaBind_COMPONENTS="stc;html;aui;adv;core;net;base" -DwxLua_LUA_LIBRARY_USE_BUILTIN=FALSE \
|
||||
-DwxLua_LUA_INCLUDE_DIR="$INSTALL_DIR/include" -DwxLua_LUA_LIBRARY="$INSTALL_DIR/lib/liblua.dylib" .
|
||||
(cd modules/luamodule; make $MAKEFLAGS) || { echo "Error: failed to build wxLua"; exit 1; }
|
||||
(cd modules/luamodule; make install/strip)
|
||||
strip -u -r "$INSTALL_DIR/lib/libwx.dylib"
|
||||
[ -f "$INSTALL_DIR/lib/libwx.dylib" ] || { echo "Error: libwx.dylib isn't found"; exit 1; }
|
||||
cd ../..
|
||||
rm -rf "$WXLUA_BASENAME"
|
||||
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"
|
||||
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 \
|
||||
|| { echo "Error: failed to build LuaSocket"; exit 1; }
|
||||
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/5.1/socket/core.dylib" \
|
||||
src/{auxiliar.c,buffer.c,except.c,inet.c,io.c,luasocket.c,options.c,select.c,tcp.c,timeout.c,udp.c,usocket.c} \
|
||||
|| { echo "Error: failed to build LuaSocket"; exit 1; }
|
||||
strip -u -r "$INSTALL_DIR/lib/lua/5.1/mime/core.dylib" "$INSTALL_DIR/lib/lua/5.1/socket/core.dylib"
|
||||
mkdir -p "$INSTALL_DIR/share/lua/5.1/socket"
|
||||
cp src/{ftp.lua,http.lua,smtp.lua,tp.lua,url.lua} "$INSTALL_DIR/share/lua/5.1/socket"
|
||||
cp src/{ltn12.lua,mime.lua,socket.lua} "$INSTALL_DIR/share/lua/5.1"
|
||||
[ -f "$INSTALL_DIR/lib/lua/5.1/mime/core.dylib" ] || { echo "Error: mime/core.dylib isn't found"; exit 1; }
|
||||
[ -f "$INSTALL_DIR/lib/lua/5.1/socket/core.dylib" ] || { echo "Error: socket/core.dylib isn't found"; exit 1; }
|
||||
cd ..
|
||||
rm -rf "$LUASOCKET_FILENAME" "$LUASOCKET_BASENAME"
|
||||
fi
|
||||
|
||||
# now copy the compiled dependencies to ZBS binary directory
|
||||
mkdir -p "$BIN_DIR" || { echo "Error: cannot create directory $BIN_DIR"; exit 1; }
|
||||
if [ $BUILD_LUA ]; then
|
||||
mkdir -p "$BIN_DIR/lua.app/Contents/MacOS"
|
||||
cp "$INSTALL_DIR/bin/lua" "$BIN_DIR/lua.app/Contents/MacOS"
|
||||
cp "$INSTALL_DIR/bin/lua" "$INSTALL_DIR/lib/liblua.dylib" "$BIN_DIR"
|
||||
fi
|
||||
[ $BUILD_WXLUA ] && cp "$INSTALL_DIR/lib/libwx.dylib" "$BIN_DIR"
|
||||
if [ $BUILD_LUASOCKET ]; then
|
||||
mkdir -p "$BIN_DIR/clibs/"{mime,socket}
|
||||
cp "$INSTALL_DIR/lib/lua/5.1/mime/core.dylib" "$BIN_DIR/clibs/mime"
|
||||
cp "$INSTALL_DIR/lib/lua/5.1/socket/core.dylib" "$BIN_DIR/clibs/socket"
|
||||
fi
|
||||
|
||||
# show a message about successful completion
|
||||
echo "*** Build has been successfully completed ***"
|
||||
exit 0
|
||||
216
build/build-win32.sh
Normal file
216
build/build-win32.sh
Normal file
@@ -0,0 +1,216 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ZBS binary directory
|
||||
BIN_DIR="$(dirname "$PWD")/bin"
|
||||
|
||||
# temporary installation directory for dependencies
|
||||
INSTALL_DIR="$PWD/deps"
|
||||
|
||||
# number of parallel jobs used for building
|
||||
MAKEFLAGS="-j4"
|
||||
|
||||
# flags for manual building with gcc
|
||||
BUILD_FLAGS="-O2 -shared -s -I $INSTALL_DIR/include -L $INSTALL_DIR/lib"
|
||||
|
||||
# paths configuration
|
||||
WXWIDGETS_BASENAME="wxWidgets"
|
||||
WXWIDGETS_URL="http://svn.wxwidgets.org/svn/wx/wxWidgets/trunk"
|
||||
|
||||
LUA_BASENAME="lua-5.1.5"
|
||||
LUA_FILENAME="$LUA_BASENAME.tar.gz"
|
||||
LUA_URL="http://www.lua.org/ftp/$LUA_FILENAME"
|
||||
|
||||
WXLUA_BASENAME="wxlua"
|
||||
WXLUA_URL="https://wxlua.svn.sourceforge.net/svnroot/wxlua/trunk"
|
||||
|
||||
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"
|
||||
|
||||
WINAPI_BASENAME="winapi"
|
||||
WINAPI_URL="https://github.com/stevedonovan/winapi.git"
|
||||
|
||||
# exit if the command line is empty
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: $0 LIBRARY..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# iterate through the command line arguments
|
||||
for ARG in "$@"; do
|
||||
case $ARG in
|
||||
wxwidgets)
|
||||
BUILD_WXWIDGETS=true
|
||||
;;
|
||||
lua)
|
||||
BUILD_LUA=true
|
||||
;;
|
||||
wxlua)
|
||||
BUILD_WXLUA=true
|
||||
;;
|
||||
luasocket)
|
||||
BUILD_LUASOCKET=true
|
||||
;;
|
||||
winapi)
|
||||
BUILD_WINAPI=true
|
||||
;;
|
||||
zbstudio)
|
||||
BUILD_ZBSTUDIO=true
|
||||
;;
|
||||
all)
|
||||
BUILD_WXWIDGETS=true
|
||||
BUILD_LUA=true
|
||||
BUILD_WXLUA=true
|
||||
BUILD_LUASOCKET=true
|
||||
BUILD_WINAPI=true
|
||||
BUILD_ZBSTUDIO=true
|
||||
;;
|
||||
*)
|
||||
echo "Error: invalid argument $ARG"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# check for g++
|
||||
if [ ! "$(which g++)" ]; then
|
||||
echo "Error: g++ isn't found. Please install MinGW C++ compiler."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check for cmake
|
||||
if [ ! "$(which cmake)" ]; then
|
||||
echo "Error: cmake isn't found. Please install CMake and add it to PATH."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check for svn
|
||||
if [[ ($BUILD_WXWIDGETS || $BUILD_LUA) && ! "$(which svn)" ]]; then
|
||||
echo "Error: svn isn't found. Please install console SVN client."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check for git
|
||||
if [[ $BUILD_WINAPI && ! "$(which git)" ]]; then
|
||||
echo "Error: git isn't found. Please install console GIT client."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# check for wget
|
||||
if [ ! "$(which wget)" ]; then
|
||||
# NOTE: can't check the return status since mingw-get always returns 0 even in the case of errors :(
|
||||
mingw-get install msys-wget
|
||||
fi
|
||||
|
||||
# create the installation directory
|
||||
mkdir -p "$INSTALL_DIR" || { echo "Error: cannot create directory $INSTALL_DIR"; exit 1; }
|
||||
|
||||
# build wxWidgets
|
||||
if [ $BUILD_WXWIDGETS ]; then
|
||||
svn co "$WXWIDGETS_URL" "$WXWIDGETS_BASENAME" || { echo "Error: failed to checkout wxWidgets"; exit 1; }
|
||||
svn revert -R "$WXWIDGETS_BASENAME"
|
||||
cd "$WXWIDGETS_BASENAME"
|
||||
./configure --prefix="$INSTALL_DIR" --disable-debug --disable-shared --enable-unicode \
|
||||
--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"
|
||||
make $MAKEFLAGS || { echo "Error: failed to build wxWidgets"; exit 1; }
|
||||
make install
|
||||
cd ..
|
||||
rm -rf "$WXWIDGETS_BASENAME"
|
||||
fi
|
||||
|
||||
# build Lua
|
||||
if [ $BUILD_LUA ]; then
|
||||
wget -c "$LUA_URL" -O "$LUA_FILENAME" || { echo "Error: failed to download Lua"; exit 1; }
|
||||
tar -xzf "$LUA_FILENAME"
|
||||
cd "$LUA_BASENAME"
|
||||
make mingw || { echo "Error: failed to build Lua"; exit 1; }
|
||||
make install INSTALL_TOP="$INSTALL_DIR"
|
||||
cp src/lua51.dll "$INSTALL_DIR/lib"
|
||||
[ -f "$INSTALL_DIR/lib/lua51.dll" ] || { echo "Error: lua51.dll isn't found"; exit 1; }
|
||||
cd ..
|
||||
rm -rf "$LUA_FILENAME" "$LUA_BASENAME"
|
||||
fi
|
||||
|
||||
# build wxLua
|
||||
if [ $BUILD_WXLUA ]; then
|
||||
svn co "$WXLUA_URL" "$WXLUA_BASENAME" || { echo "Error: failed to checkout wxLua"; exit 1; }
|
||||
svn revert -R "$WXLUA_BASENAME"
|
||||
cd "$WXLUA_BASENAME/wxLua"
|
||||
sed -i 's|:-/\(.\)/|:-\1:/|' "$INSTALL_DIR/bin/wx-config"
|
||||
sed -i 's/execute_process(COMMAND/& sh/' build/CMakewxAppLib.cmake modules/wxstedit/build/CMakewxAppLib.cmake
|
||||
# the following patches wxlua source to fix live coding support in wxlua apps
|
||||
# http://www.mail-archive.com/wxlua-users@lists.sourceforge.net/msg03225.html
|
||||
sed -i 's/\(m_wxlState = wxLuaState(wxlState.GetLuaState(), wxLUASTATE_GETSTATE|wxLUASTATE_ROOTSTATE);\)/\/\/ removed by ZBS build process \/\/ \1/' modules/wxlua/wxlcallb.cpp
|
||||
cp "$INSTALL_DIR/lib/libwxscintilla-2.9.a" "$INSTALL_DIR/lib/libwx_mswu_scintilla-2.9.a"
|
||||
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 \
|
||||
-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)
|
||||
[ -f "$INSTALL_DIR/bin/libwx.dll" ] || { echo "Error: libwx.dll isn't found"; exit 1; }
|
||||
cd ../..
|
||||
rm -rf "$WXLUA_BASENAME"
|
||||
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"
|
||||
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 \
|
||||
|| { echo "Error: failed to build LuaSocket"; exit 1; }
|
||||
gcc $BUILD_FLAGS -o "$INSTALL_DIR/lib/lua/5.1/socket/core.dll" \
|
||||
src/{auxiliar.c,buffer.c,except.c,inet.c,io.c,luasocket.c,options.c,select.c,tcp.c,timeout.c,udp.c,wsocket.c} -lwsock32 -llua51 \
|
||||
|| { echo "Error: failed to build LuaSocket"; exit 1; }
|
||||
mkdir -p "$INSTALL_DIR/share/lua/5.1/socket"
|
||||
cp src/{ftp.lua,http.lua,smtp.lua,tp.lua,url.lua} "$INSTALL_DIR/share/lua/5.1/socket"
|
||||
cp src/{ltn12.lua,mime.lua,socket.lua} "$INSTALL_DIR/share/lua/5.1"
|
||||
[ -f "$INSTALL_DIR/lib/lua/5.1/mime/core.dll" ] || { echo "Error: mime/core.dll isn't found"; exit 1; }
|
||||
[ -f "$INSTALL_DIR/lib/lua/5.1/socket/core.dll" ] || { echo "Error: socket/core.dll isn't found"; exit 1; }
|
||||
cd ..
|
||||
rm -rf "$LUASOCKET_FILENAME" "$LUASOCKET_BASENAME"
|
||||
fi
|
||||
|
||||
# build winapi
|
||||
if [ $BUILD_WINAPI ]; then
|
||||
git clone "$WINAPI_URL" "$WINAPI_BASENAME"
|
||||
cd "$WINAPI_BASENAME"
|
||||
gcc $BUILD_FLAGS -DPSAPI_VERSION=1 -o "$INSTALL_DIR/lib/lua/5.1/winapi.dll" winapi.c wutils.c -lpsapi -lmpr -llua51 \
|
||||
|| { echo "Error: failed to build winapi"; exit 1; }
|
||||
[ -f "$INSTALL_DIR/lib/lua/5.1/winapi.dll" ] || { echo "Error: winapi.dll isn't found"; exit 1; }
|
||||
cd ..
|
||||
rm -rf "$WINAPI_BASENAME"
|
||||
fi
|
||||
|
||||
# build ZBS launcher
|
||||
if [ $BUILD_ZBSTUDIO ]; then
|
||||
windres ../zbstudio/res/zbstudio.rc zbstudio.rc.o
|
||||
gcc -O2 -s -mwindows -o ../zbstudio.exe win32_starter.c zbstudio.rc.o
|
||||
rm zbstudio.rc.o
|
||||
[ -f ../zbstudio.exe ] || { echo "Error: zbstudio.exe isn't found"; exit 1; }
|
||||
fi
|
||||
|
||||
# now copy the compiled dependencies to ZBS binary directory
|
||||
mkdir -p "$BIN_DIR" || { echo "Error: cannot create directory $BIN_DIR"; exit 1; }
|
||||
[ $BUILD_LUA ] && cp "$INSTALL_DIR/bin/lua.exe" "$INSTALL_DIR/lib/lua51.dll" "$BIN_DIR"
|
||||
[ $BUILD_WXLUA ] && cp "$INSTALL_DIR/bin/libwx.dll" "$BIN_DIR/wx.dll"
|
||||
[ $BUILD_WINAPI ] && cp "$INSTALL_DIR/lib/lua/5.1/winapi.dll" "$BIN_DIR"
|
||||
if [ $BUILD_LUASOCKET ]; then
|
||||
mkdir -p "$BIN_DIR/clibs/"{mime,socket}
|
||||
cp "$INSTALL_DIR/lib/lua/5.1/mime/core.dll" "$BIN_DIR/clibs/mime"
|
||||
cp "$INSTALL_DIR/lib/lua/5.1/socket/core.dll" "$BIN_DIR/clibs/socket"
|
||||
fi
|
||||
|
||||
# To build lua5.1.dll proxy:
|
||||
# (1) get mkforwardlib-gcc.lua from http://lua-users.org/wiki/LuaProxyDllThree
|
||||
# (2) run it as "lua mkforwardlib-gcc.lua lua51 lua5.1 X86"
|
||||
|
||||
# show a message about successful completion
|
||||
echo "*** Build has been successfully completed ***"
|
||||
exit 0
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
sudo apt-get install gdebi
|
||||
sudo gdebi wxlua*.deb
|
||||
@@ -19,10 +19,21 @@ require "wx"
|
||||
function FileSysGet(dir,spec)
|
||||
local content = {}
|
||||
local browse = wx.wxFileSystem()
|
||||
local cwd = wx.wxGetCwd()
|
||||
if not wx.wxFileName(dir):DirExists() then return content end
|
||||
local f = browse:FindFirst(dir,spec)
|
||||
while #f>0 do
|
||||
table.insert(content,(f:gsub("^file:",""))) -- drop file: protocol (wx2.9+)
|
||||
if f:match("^file:") then -- remove file: protocol (wx2.9+)
|
||||
f = f:gsub(iswindows and "^file:/?" or "^file:","")
|
||||
:gsub('%%(%x%x)', function(n) return string.char(tonumber(n, 16)) end)
|
||||
end
|
||||
-- wx2.9+ return absolute path here instead of expected relative; fix it
|
||||
if wx.wxIsAbsolutePath(f) then
|
||||
local relative = wx.wxFileName(f)
|
||||
relative:MakeRelativeTo(cwd)
|
||||
f = relative:GetFullPath()
|
||||
end
|
||||
table.insert(content, f)
|
||||
f = browse:FindNext()
|
||||
end
|
||||
return content
|
||||
|
||||
@@ -24,7 +24,6 @@ typedef void varfuncvoid (void *L,...);
|
||||
// from lua.h
|
||||
#define LUA_GLOBALSINDEX (-10002)
|
||||
|
||||
|
||||
static voidfunc *luaL_newstate;
|
||||
static varfunc *luaL_loadbuffer;
|
||||
static varfunc *luaL_openlibs;
|
||||
@@ -146,13 +145,12 @@ int main (int argc, char *argv[])
|
||||
#endif
|
||||
HINSTANCE hinstLib;
|
||||
|
||||
|
||||
char buffer[MAX_PATH],*file;
|
||||
|
||||
if (!GetFullPathName(argv[0],MAX_PATH,buffer,&file)) {
|
||||
MessageBox(NULL,
|
||||
TEXT("Couldn't find the correct working directory"),
|
||||
TEXT("Failed to start estrela"),
|
||||
TEXT("Failed to start editor"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
return 0;
|
||||
}
|
||||
@@ -166,7 +164,7 @@ int main (int argc, char *argv[])
|
||||
|
||||
|
||||
SetDllDirectory(".\\bin\\");
|
||||
hinstLib = LoadLibrary("lua5.1.dll");
|
||||
hinstLib = LoadLibrary("lua51.dll");
|
||||
if (hinstLib != NULL)
|
||||
{
|
||||
luaL_newstate = (voidfunc*) GetProcAddress(hinstLib, "luaL_newstate");
|
||||
@@ -207,18 +205,18 @@ int main (int argc, char *argv[])
|
||||
else
|
||||
MessageBox(NULL,
|
||||
TEXT("An unexpected error occured while loading the lua chunk."),
|
||||
TEXT("Failed to start estrela"),
|
||||
TEXT("Failed to start editor"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
} else
|
||||
MessageBox(NULL,
|
||||
TEXT("Couldn't initialize a luastate"),
|
||||
TEXT("Failed to start estrela"),
|
||||
TEXT("Failed to start editor"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
} else {
|
||||
MessageBox(NULL,
|
||||
TEXT("Could not load all functions that are supposed to be located in the lua5.1.dll\n"
|
||||
TEXT("Could not load all functions that are supposed to be located in the lua51.dll\n"
|
||||
"This is not supposed to be happening..."),
|
||||
TEXT("Failed to start estrela"),
|
||||
TEXT("Failed to start editor"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
}
|
||||
|
||||
@@ -226,11 +224,10 @@ int main (int argc, char *argv[])
|
||||
FreeLibrary(hinstLib);
|
||||
} else {
|
||||
MessageBox(NULL,
|
||||
TEXT("The lua5.1.dll could not be found or loaded, please check the working directory of the application.\n"),
|
||||
TEXT("Failed to initialize estrela"),
|
||||
TEXT("The lua51.dll could not be found or loaded, please check the working directory of the application.\n"),
|
||||
TEXT("Failed to initialize editor"),
|
||||
MB_OK|MB_ICONERROR);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -1,4 +1,5 @@
|
||||
return {
|
||||
[0] = function(c) return c == 1 and 1 or 2 end, -- plural
|
||||
["traced %d instruction"] = {"traced %d instruction", "traced %d instructions"}, -- src\editor\debugger.lua
|
||||
["%d instance"] = {"%d instance", "%d instances"}, -- src\editor\findreplace.lua
|
||||
}
|
||||
|
||||
@@ -6,10 +6,11 @@ return {
|
||||
["&About"] = "&Acerca de...", -- src\editor\menu_help.lua
|
||||
["&Add Watch"] = "Añadir observación", -- src\editor\debugger.lua
|
||||
["&Break"] = "Ruptura", -- src\editor\menu_project.lua
|
||||
["&Close page"] = "Cerrar página", -- src\editor\menu_file.lua
|
||||
["&Close Page"] = "Cerrar página", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["&Compile"] = "Compilar", -- src\editor\menu_project.lua
|
||||
["&Copy"] = "Copiar", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Default Layout"] = "Diseño por defecto", -- src\editor\menu_view.lua
|
||||
["&Delete Watch"] = "Eliminar observación", -- src\editor\debugger.lua
|
||||
["&Edit Watch"] = "Editar observación", -- src\editor\debugger.lua
|
||||
["&Edit"] = "Editar", -- src\editor\menu_edit.lua
|
||||
["&File"] = "Archivo", -- src\editor\menu_file.lua
|
||||
@@ -23,10 +24,9 @@ return {
|
||||
["&Paste"] = "Pegar", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Project"] = "Proyecto", -- src\editor\menu_project.lua, src\editor\inspect.lua
|
||||
["&Redo"] = "Rehacer", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Remove Watch"] = "Eliminar observación", -- src\editor\debugger.lua
|
||||
["&Replace"] = "Remplazar", -- src\editor\menu_search.lua
|
||||
["&Run"] = "Ejecutar", -- src\editor\menu_project.lua
|
||||
["&Save"] = "Guardar", -- src\editor\menu_file.lua
|
||||
["&Save"] = "Guardar", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["&Search"] = "Buscar", -- src\editor\menu_search.lua
|
||||
["&Sort"] = "Clasificar", -- src\editor\menu_search.lua
|
||||
["&Stack Window"] = "Ventana de la pila de ejecución", -- src\editor\menu_view.lua
|
||||
@@ -34,8 +34,7 @@ return {
|
||||
["&Undo"] = "Deshacer", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&View"] = "Ver", -- src\editor\menu_view.lua
|
||||
["&Watch Window"] = "Ventana de observaciones", -- src\editor\menu_view.lua
|
||||
["&Watches"] = "Observaciones", -- src\editor\debugger.lua
|
||||
["About ZeroBrane Studio"] = "Acerca de ZeroBrane Studio", -- src\editor\menu_help.lua
|
||||
["About %s"] = "Acerca de %s", -- src\editor\menu_help.lua
|
||||
["Add Watch Expression"] = "Añadir expresión de observación", -- src\editor\editor.lua
|
||||
["Add to Scratchpad"] = "Añadir al borrador", -- src\editor\editor.lua
|
||||
["All files"] = "Todos los archivos", -- src\editor\commands.lua
|
||||
@@ -53,9 +52,12 @@ return {
|
||||
["Can't run the entry point script ('%s')."] = "No se pude ejecutar el punto de entrada del script (%s).", -- src\editor\debugger.lua
|
||||
["Can't start debugging session due to internal error '%s'."] = "No se puede iniciar la sesión de depuración debido a un error interno '%s'.'", -- src\editor\debugger.lua
|
||||
["Can't start debugging without an opened file or with the current file not being saved ('%s')."] = "No se puede iniciar la depuración sin abrir un archivo o si no ha sido guardado ('%s').", -- src\editor\debugger.lua
|
||||
["Choose ..."] = nil, -- src\editor\menu_project.lua
|
||||
["Choose a project directory"] = "Elegir el directorio del proyecto", -- src\editor\menu_project.lua
|
||||
["Clear &Dynamic Words"] = "Limpiar las palabras dinámicas", -- src\editor\menu_edit.lua
|
||||
["Clear the output window before compiling or debugging"] = "Limpiar la ventana de salida antes de compilar o depurar", -- src\editor\menu_project.lua
|
||||
["Close &Other Pages"] = nil, -- src\editor\gui.lua
|
||||
["Close A&ll Pages"] = nil, -- src\editor\gui.lua
|
||||
["Close the current editor window"] = "Cerrar la ventana actual del editor", -- src\editor\menu_file.lua
|
||||
["Co&ntinue"] = "Continuar", -- src\editor\menu_project.lua
|
||||
["Col: %d"] = "Col: %d", -- src\editor\editor.lua
|
||||
@@ -65,23 +67,25 @@ return {
|
||||
["Compile the current file"] = "Compilar el archivo actual", -- src\editor\menu_project.lua
|
||||
["Complete &Identifier"] = "Completar identificador", -- src\editor\menu_edit.lua
|
||||
["Complete the current identifier"] = "Completar el actual identificador", -- src\editor\menu_edit.lua
|
||||
["Copy selected text to clipboard"] = "Copiar el texto seleccionado al portapapeles", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Copy selected text to clipboard"] = "Copiar el texto seleccionado al portapapeles", -- src\editor\menu_edit.lua
|
||||
["Couldn't activate file '%s' for debugging; continuing without it."] = "No se pudo activar el archivo '%s' para la depuración; continuar sin él.", -- src\editor\debugger.lua
|
||||
["Create an empty document"] = "Crear un documento en blanco", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Cu&t"] = "Cortar", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["Cut selected text to clipboard"] = "Cortar el texto selecionado al portapapeles", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Cut selected text to clipboard"] = "Cortar el texto selecionado al portapapeles", -- src\editor\menu_edit.lua
|
||||
["Debugger server started at %s:%d."] = "Servidor de depuración inciado en %s:%s", -- src\editor\debugger.lua
|
||||
["Debugging session completed (%s)."] = "Sesión de depuración completada (%s).", -- src\editor\debugger.lua
|
||||
["Debugging session started in '%s'."] = "Sesión de depuración iniciada en '%s'.", -- src\editor\debugger.lua
|
||||
["Debugging suspended at %s:%s (couldn't activate the file)."] = nil, -- src\editor\debugger.lua
|
||||
["Do you want to reload it?"] = "¿Quieres recargarlo?", -- src\editor\editor.lua
|
||||
["Do you want to save the changes to '%s'?"] = "¿Quieres guardar los cambios en '%s'?", -- src\editor\commands.lua
|
||||
["E&xit"] = "Salir", -- src\editor\menu_file.lua
|
||||
["Enter Lua code and press Enter to run it."] = "Introduce código Lua y pulsa <Entrer> para ejecutarlo.", -- src\editor\shellbox.lua
|
||||
["Enter line number"] = "Introduce número de línea", -- src\editor\menu_search.lua
|
||||
["Error while loading API file: %s"] = "Error mientras se cargaba el archivo de API: %s", -- src\editor\autocomplete.lua
|
||||
["Error while loading configuration file: %s"] = nil, -- src\editor\style.lua
|
||||
["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 &Watches"] = "Evaluar las observaciones", -- src\editor\debugger.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
|
||||
@@ -113,12 +117,14 @@ return {
|
||||
["Ln: %d"] = "Ln: %d", -- src\editor\editor.lua
|
||||
["Local console"] = "Consola local", -- src\editor\shellbox.lua, src\editor\gui.lua
|
||||
["Lua &Interpreter"] = "Intérprete Lua", -- src\editor\menu_project.lua
|
||||
["Mapped remote request for '%s' to '%s'."] = nil, -- src\editor\debugger.lua
|
||||
["Mixed end-of-line encodings detected."] = nil, -- src\editor\commands.lua
|
||||
["OVR"] = "OVR", -- src\editor\editor.lua
|
||||
["Open an existing document"] = "Abrir un documento existente", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Open file"] = "Abrir archivo", -- src\editor\commands.lua
|
||||
["Output (running)"] = "Salida (en ejecución)", -- src\editor\output.lua
|
||||
["Output"] = "Salida", -- src\editor\output.lua, src\editor\settings.lua, src\editor\gui.lua
|
||||
["Paste text from the clipboard"] = "Pegar texto desde el portapapeles", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Paste text from the clipboard"] = "Pegar texto desde el portapapeles", -- src\editor\menu_edit.lua
|
||||
["Prepend '=' to show complex values on multiple lines."] = "Antepón '=' para ver valores complejos en líneas múltiples", -- src\editor\shellbox.lua
|
||||
["Press cancel to abort."] = "Presiona cancelar para abortar.", -- src\editor\commands.lua
|
||||
["Program '%s' started in '%s' (pid: %d)."] = "Programa '%s' iniciado en '%s' (pid: %d).", -- src\editor\output.lua
|
||||
@@ -127,21 +133,23 @@ return {
|
||||
["Program starting as '%s'."] = "Programa iniciado como '%s'.", -- src\editor\output.lua
|
||||
["Program stopped (pid: %d)."] = "Programa parado (pid: %d).", -- src\editor\debugger.lua
|
||||
["Program unable to run as '%s'."] = "No se puede ejecutar el programa como '%s'.", -- src\editor\output.lua
|
||||
["Project Directory"] = nil, -- src\editor\menu_project.lua
|
||||
["Project"] = "Proyecto", -- src\editor\settings.lua, src\editor\gui.lua
|
||||
["Project/&FileTree Window"] = "Ventana de proyecto/árbol de archivos", -- 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"] = "Remplazar en archivos", -- src\editor\menu_search.lua
|
||||
["Recent Files"] = "Archivos recientes", -- src\editor\menu_file.lua
|
||||
["Redo last edit undone"] = "Rehacer la última edición deshecha", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Redo last edit undone"] = "Rehacer la última edición deshecha", -- src\editor\menu_edit.lua
|
||||
["Refused a request to start a new debugging session as there is one in progress already."] = "No se pudo lanzar una nueva sesión de depuración porque ya hay una en curso.", -- src\editor\debugger.lua
|
||||
["Remote console"] = "Consola remota", -- src\editor\shellbox.lua
|
||||
["Replaced an invalid UTF8 character with %s."] = nil, -- src\editor\commands.lua
|
||||
["Reset to default layout"] = "Restablecer el diseño por defecto", -- src\editor\menu_view.lua
|
||||
["Resets the dynamic word list for autocompletion"] = "Restablecer la lista dinámica de palabras para autocompletado", -- src\editor\menu_edit.lua
|
||||
["Run as Scratchpad"] = "Ejecutar como borrador", -- src\editor\menu_project.lua
|
||||
["S&top Debugging"] = "Parar depuración", -- src\editor\menu_project.lua
|
||||
["S&top Process"] = "Parar proceso", -- src\editor\menu_project.lua
|
||||
["Save &As..."] = "Guardar como...", -- src\editor\menu_file.lua
|
||||
["Save &As..."] = "Guardar como...", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Save A&ll"] = "Guardar todo", -- src\editor\menu_file.lua
|
||||
["Save Changes?"] = "¿Guardar cambios?", -- src\editor\commands.lua
|
||||
["Save all open documents"] = "Guardar todos los documentos abiertos", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
@@ -153,12 +161,14 @@ return {
|
||||
["Scratchpad error"] = "Error en el borrador", -- src\editor\debugger.lua
|
||||
["Select &All"] = "Seleccionar todo", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["Select all text in the editor"] = "Seleccionar todo el texto en el editor", -- src\editor\menu_edit.lua
|
||||
["Set project directory from current file"] = "Establecer el directorio del proyecto del archivo actual", -- src\editor\gui.lua
|
||||
["Set From Current File"] = nil, -- src\editor\menu_project.lua
|
||||
["Set project directory from current file"] = "Establecer el directorio del proyecto del archivo actual", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Set the interpreter to be used"] = "Establecer el intérprete a ser usado", -- src\editor\menu_project.lua
|
||||
["Set the project directory to be used"] = nil, -- src\editor\menu_project.lua
|
||||
["Show &Tooltip"] = "Ver tooltip", -- src\editor\menu_edit.lua
|
||||
["Show tooltip for current position; place cursor after opening bracket of function"] = "Ver tooltip para la posición actual; posicionar el cursor después de abrir el paréntisis de los argumentos de la función", -- src\editor\menu_edit.lua
|
||||
["Sort selected lines"] = "Clasificar las líneas seleccionadas", -- src\editor\menu_search.lua
|
||||
["Stack Window"] = "Ventana de la pila de ejecución", -- src\editor\debugger.lua
|
||||
["Stack"] = nil, -- src\editor\debugger.lua
|
||||
["Start &Debugging"] = "Comenzar depuración", -- src\editor\menu_project.lua
|
||||
["Start debugging"] = "Comenzar depuración", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Step &Into"] = "Paso dentro", -- src\editor\menu_project.lua
|
||||
@@ -177,7 +187,9 @@ return {
|
||||
["Unable to load file '%s'."] = "No se pudo cargar el archivo '%s'.", -- src\editor\commands.lua
|
||||
["Unable to save file '%s': %s"] = "No se pudo guardar el archivo '%s': %s", -- src\editor\commands.lua
|
||||
["Unable to stop program (pid: %d), code %d."] = "No se puedo parar el programa (pid: %d), código %d.", -- src\editor\debugger.lua
|
||||
["Undo last edit"] = "Deshacer la última edición", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Undo last edit"] = "Deshacer la última edición", -- src\editor\menu_edit.lua
|
||||
["Use '%s' to see full description."] = nil, -- src\editor\editor.lua
|
||||
["Use '%s' to show line endings and '%s' to convert them."] = nil, -- src\editor\commands.lua
|
||||
["Use 'clear' to clear the shell output and the history."] = "Usa 'clear' para limpiar la consola de salida y el historial.", -- src\editor\shellbox.lua
|
||||
["Use Shift-Enter for multiline code."] = "Usa <Shift-Enter> para código multilínea.", -- src\editor\shellbox.lua
|
||||
["Value"] = "Valor", -- src\editor\debugger.lua
|
||||
@@ -185,7 +197,7 @@ return {
|
||||
["View the project/filetree window"] = "Ver la ventana de proyecto/árbol de archivos", -- src\editor\menu_view.lua
|
||||
["View the stack window"] = "Ver la ventana de la pila de ejecución", -- src\editor\menu_view.lua, src\editor\gui.lua
|
||||
["View the watch window"] = "Ver la ventana de observación", -- src\editor\menu_view.lua, src\editor\gui.lua
|
||||
["Watch Window"] = "Ventana de observación", -- src\editor\debugger.lua
|
||||
["Watch"] = nil, -- src\editor\debugger.lua
|
||||
["Welcome to the interactive Lua interpreter."] = "Bienvenido al intérprete interactico de Lua.", -- src\editor\shellbox.lua
|
||||
["You must save the program first."] = "Debes guardar el programa primero", -- src\editor\commands.lua
|
||||
["on line %d"] = "en la línea %d", -- src\editor\debugger.lua, src\editor\commands.lua
|
||||
|
||||
286
cfg/i18n/fr.lua
286
cfg/i18n/fr.lua
@@ -1,190 +1,202 @@
|
||||
return {
|
||||
[0] = function(c) return c == 1 and 1 or 2 end, -- plural
|
||||
["&About"] = "&A propos", -- src\editor\menu_help.lua
|
||||
["&Add Watch"] = "Ajouter un point d'observation", -- src\editor\debugger.lua
|
||||
["&Break"] = "Interrompre", -- src\editor\menu_project.lua
|
||||
["&Close page"] = "Fermer la page", -- src\editor\menu_file.lua
|
||||
["&Compile"] = "Compiler", -- src\editor\menu_project.lua
|
||||
["&Copy"] = "Copier", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Default Layout"] = "Affichage par défaut", -- src\editor\menu_view.lua
|
||||
["&Edit Watch"] = "Editer le point d'observation", -- src\editor\debugger.lua
|
||||
["&Edit"] = "Editer", -- src\editor\menu_edit.lua
|
||||
["&File"] = "Fichier", -- src\editor\menu_file.lua
|
||||
["&Find"] = "Trouver", -- src\editor\menu_search.lua
|
||||
["&Fold/Unfold All"] = "Replier/Déplier tout", -- src\editor\menu_edit.lua
|
||||
["&Goto Line"] = "Aller à la ligne", -- src\editor\menu_search.lua
|
||||
["&Help"] = "Aide", -- src\editor\menu_help.lua
|
||||
["&About"] = "À &propos", -- src\editor\menu_help.lua
|
||||
["&Add Watch"] = "&Ajouter une expression", -- src\editor\debugger.lua
|
||||
["&Break"] = "&Interrompre", -- src\editor\menu_project.lua
|
||||
["&Close Page"] = "&Fermer la page", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["&Compile"] = "&Compiler", -- src\editor\menu_project.lua
|
||||
["&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
|
||||
["&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
|
||||
["&Fold/Unfold All"] = "Re&plier/Déplier tout", -- src\editor\menu_edit.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
|
||||
["&Output/Console Window"] = "Sortie/Console", -- src\editor\menu_view.lua
|
||||
["&Paste"] = "Coller", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Project"] = "Projet", -- src\editor\menu_project.lua, src\editor\inspect.lua
|
||||
["&Redo"] = "Répéter", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Remove Watch"] = "Supprimer le point d'observation", -- src\editor\debugger.lua
|
||||
["&Replace"] = "Remplacer", -- src\editor\menu_search.lua
|
||||
["&Run"] = "Exécuter", -- src\editor\menu_project.lua
|
||||
["&Save"] = "Enregister", -- src\editor\menu_file.lua
|
||||
["&Search"] = "Rechercher", -- 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 débogueur", -- src\editor\menu_project.lua
|
||||
["&Undo"] = "Défaire", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&View"] = "Vue", -- src\editor\menu_view.lua
|
||||
["&Watch Window"] = "Fenêtre d'observation", -- src\editor\menu_view.lua
|
||||
["&Watches"] = "Points d'observation", -- src\editor\debugger.lua
|
||||
["About ZeroBrane Studio"] = "A propos de ZeroBrane Studio", -- src\editor\menu_help.lua
|
||||
["&Open..."] = "&Ouvrir...", -- src\editor\menu_file.lua
|
||||
["&Output/Console Window"] = "&Sortie/Console", -- src\editor\menu_view.lua
|
||||
["&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
|
||||
["&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
|
||||
["&Undo"] = "&Annuler", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&View"] = "&Affichage", -- src\editor\menu_view.lua
|
||||
["&Watch Window"] = "&Expressions espionnes", -- src\editor\menu_view.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
|
||||
["All files"] = "Tous les fichiers", -- src\editor\commands.lua
|
||||
["Allow external process to start debugging"] = "Autoriser aux processus externes le démarrage du débogueur", -- src\editor\menu_project.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
|
||||
["Analyze"] = "Analyser", -- src\editor\inspect.lua
|
||||
["Auto Complete Identifiers"] = "Identificateur d'auto-complétion", -- src\editor\menu_edit.lua
|
||||
["Auto complete while typing"] = "Auto-complémention en mode saisie", -- src\editor\menu_edit.lua
|
||||
["Auto Complete Identifiers"] = "Auto-compléter les identifiants", -- src\editor\menu_edit.lua
|
||||
["Auto complete while typing"] = "Auto-compléter lors de la saisie", -- src\editor\menu_edit.lua
|
||||
["Break execution at the next executed line of code"] = "Interrompre l'exécution à la ligne suivante", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["C&lear Output Window"] = "Effacer la sortie console", -- src\editor\menu_project.lua
|
||||
["C&omment/Uncomment"] = "Commenter/Décommenter", -- src\editor\menu_edit.lua
|
||||
["Can't debug the script in the active editor window."] = "Impossible de déboguer le script dans la fenêtre d'édition active", -- 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."] = "Fichier '%s' non trouvé dans le projet en cours pour le débogage. Mettez le projet à jour ou ouvrez le fichier dans l'éditeur avant débogage.", -- src\editor\debugger.lua
|
||||
["Can't process auto-recovery record; invalid format: %s."] = "Impossible de restaurer automatiquement l'enregistrement; Format invalide: %s.", -- src\editor\commands.lua
|
||||
["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 démarrer 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 déboguer sans fichier ouvert ou si le fichier en cours d'édition n'a pas été enregistré ('%s').", -- src\editor\debugger.lua
|
||||
["C&lear Output Window"] = "E&ffacer la fenêtre de sortie", -- src\editor\menu_project.lua
|
||||
["C&omment/Uncomment"] = "Co&mmenter/Décommenter", -- src\editor\menu_edit.lua
|
||||
["Can't debug the script in the active editor window."] = "Impossible de déboguer le script dans la fenêtre d'édition active.", -- 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."] = "Impossible de trouver le fichier '%s' dans le projet courant pour permettre le débogage. Mettez le projet à jour ou ouvrez le fichier dans l'éditeur avant débogage.", -- src\editor\debugger.lua
|
||||
["Can't process auto-recovery record; invalid format: %s."] = "Impossible de lire la récupération automatique ; format invalide : %s.", -- src\editor\commands.lua
|
||||
["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
|
||||
["Choose ..."] = "Choisir...", -- src\editor\menu_project.lua
|
||||
["Choose a project directory"] = "Choisissez un répertoire de projet", -- 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"] = "Nettoyer la fenêtre de sortie avant compilation ou débogage", -- 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
|
||||
["Close A&ll Pages"] = "Fermer &toutes les pages", -- src\editor\gui.lua
|
||||
["Close the current editor window"] = "Fermer la fenêtre d'édition active", -- src\editor\menu_file.lua
|
||||
["Co&ntinue"] = "Continuer", -- src\editor\menu_project.lua
|
||||
["Col: %d"] = "Col: %d", -- src\editor\editor.lua
|
||||
["Comment or uncomment current or selected lines"] = "Commenter/Décommenter les lignes actives (sélectionnées)", -- src\editor\menu_edit.lua
|
||||
["Compilation error"] = "Erreur de commpilation", -- src\editor\debugger.lua, src\editor\commands.lua
|
||||
["Compilation successful; %.0f%% success rate (%d/%d)."] = "Compilation réussie; taux de succès : %.0f%% (%d/%d).", -- src\editor\commands.lua
|
||||
["Co&ntinue"] = "Co&ntinuer", -- src\editor\menu_project.lua
|
||||
["Col: %d"] = "Col : %d", -- src\editor\editor.lua
|
||||
["Comment or uncomment current or selected lines"] = "Commenter ou décommenter les lignes courantes ou sélectionnées", -- src\editor\menu_edit.lua
|
||||
["Compilation error"] = "Erreur de compilation", -- src\editor\debugger.lua, src\editor\commands.lua
|
||||
["Compilation successful; %.0f%% success rate (%d/%d)."] = "Compilation réussie ; taux de succès : %.0f%% (%d/%d).", -- src\editor\commands.lua
|
||||
["Compile the current file"] = "Сompiler le fichier courant", -- src\editor\menu_project.lua
|
||||
["Complete &Identifier"] = "Complétion d'identificateur", -- src\editor\menu_edit.lua
|
||||
["Complete the current identifier"] = "Complétion de l'identificateur courant", -- src\editor\menu_edit.lua
|
||||
["Copy selected text to clipboard"] = "Copier le texte sélectionné dans le presse-papiers", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Couldn't activate file '%s' for debugging; continuing without it."] = "Echec d'activation du fichier '%s' pour débogage; Poursuite du processus en ignorant le fichier.", -- src\editor\debugger.lua
|
||||
["Complete &Identifier"] = "Compléter l'&identifiant", -- src\editor\menu_edit.lua
|
||||
["Complete the current identifier"] = "Compléter l'identifiant courant", -- src\editor\menu_edit.lua
|
||||
["Copy selected text to clipboard"] = "Copier le texte sélectionné dans le presse-papiers", -- src\editor\menu_edit.lua
|
||||
["Couldn't activate file '%s' for debugging; continuing without it."] = "Impossible d'activer le fichier '%s' pour débogage ; poursuite du processus en ignorant le fichier.", -- src\editor\debugger.lua
|
||||
["Create an empty document"] = "Créer un document vierge", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Cu&t"] = "Couper", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["Cut selected text to clipboard"] = "Couper le texte selectionné et copier dans le presse-papiers", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Debugger server started at %s:%d."] = "Débogueur démarré à %s:%s", -- src\editor\debugger.lua
|
||||
["Cu&t"] = "&Couper", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["Cut selected text to clipboard"] = "Couper le texte sélectionné et copier dans le presse-papiers", -- src\editor\menu_edit.lua
|
||||
["Debugger server started at %s:%d."] = "Serveur de débogage démarré à %s:%d.", -- src\editor\debugger.lua
|
||||
["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
|
||||
["Do you want to reload it?"] = "Voulez -vous le charger à nouveau?", -- src\editor\editor.lua
|
||||
["Do you want to save the changes to '%s'?"] = "Voulez-vous sauvegarder les changements dans '%s'?", -- src\editor\commands.lua
|
||||
["E&xit"] = "Sortie", -- src\editor\menu_file.lua
|
||||
["Enter Lua code and press Enter to run it."] = "Entrer du code Lua et pressez <Entrée> pour l`exécuter.", -- src\editor\shellbox.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
|
||||
["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
|
||||
["Enter Lua code and press Enter to run it."] = "Saisissez du code Lua et appuyez sur <Entrée> pour l´exécuter.", -- src\editor\shellbox.lua
|
||||
["Enter line number"] = "Entrez le numéro de ligne", -- src\editor\menu_search.lua
|
||||
["Error while loading API file: %s"] = "Erreur lors du chargement du fichier d'API: %s", -- src\editor\autocomplete.lua
|
||||
["Error while processing API file: %s"] = "Erreur lors de la lecture du fichier d'API: %s", -- src\editor\autocomplete.lua
|
||||
["Error while loading API file: %s"] = "Erreur lors du chargement du fichier d'API : %s", -- src\editor\autocomplete.lua
|
||||
["Error while loading configuration file: %s"] = "Erreur lors du chargement du fichier de configuration : %s", -- src\editor\style.lua
|
||||
["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 &Watches"] = "Evaluer les points d'observation", -- src\editor\debugger.lua
|
||||
["Evaluate in Console"] = "Evaluer en 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
|
||||
["Exit program"] = "Sortie du programme", -- src\editor\menu_file.lua
|
||||
["Exit program"] = "Quitter le programme", -- src\editor\menu_file.lua
|
||||
["Expr"] = "Expr.", -- src\editor\debugger.lua
|
||||
["Expression"] = "Expresseion", -- src\editor\debugger.lua
|
||||
["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 enregistrement.", -- src\editor\commands.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 history"] = "Historique de fichier", -- src\editor\menu_file.lua
|
||||
["Find &In Files"] = "Rechercher dans les fichiers", -- src\editor\menu_search.lua
|
||||
["Find &Next"] = "Rechercher l'occurence suivante", -- src\editor\menu_search.lua
|
||||
["Find &Previous"] = "Rechercher l'occurence précédente", -- 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 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'occurence précédente du texte", -- src\editor\menu_search.lua
|
||||
["Find the next text occurrence"] = "Recherche l'occurence suivante du texte", -- src\editor\menu_search.lua
|
||||
["Fold or unfold all code folds"] = "Replier/Déplier tous les blocs de code repliés", -- src\editor\menu_edit.lua
|
||||
["Found auto-recovery record and restored saved session."] = "Enregistrement automatique trouvé et session restaurée", -- src\editor\commands.lua
|
||||
["Full &Screen"] = "Plein écran", -- src\editor\menu_view.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
|
||||
["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
|
||||
["Full &Screen"] = "&Plein écran", -- src\editor\menu_view.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
|
||||
["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"] = "Ln: %d", -- src\editor\editor.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 Lua", -- src\editor\menu_project.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
|
||||
["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
|
||||
["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, src\editor\gui.lua
|
||||
["Prepend '=' to show complex values on multiple lines."] = "Préfixer '=' afin de mettre en évidence les valeurs complexes sur les lignes multiples", -- src\editor\shellbox.lua
|
||||
["Press cancel to abort."] = "Appuyer annuler pour arrêter.", -- src\editor\commands.lua
|
||||
["Program '%s' started in '%s' (pid: %d)."] = "Programme '%s' démarré dans '%s' (pid: %d).", -- src\editor\output.lua
|
||||
["Program can't start because conflicting process is running as '%s'."] = "Le programme ne peut démarrer à cause d'un processus conflictuel '%s' en cours d'exécution.", -- src\editor\output.lua
|
||||
["Program completed in %.2f seconds (pid: %d)."] = "Programme terminé en %.2f secondes (pid: %d).", -- src\editor\output.lua
|
||||
["Paste text from the clipboard"] = "Coller le texte depuis le presse-papiers", -- 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
|
||||
["Program can't start because conflicting process is running as '%s'."] = "Le programme ne peut démarrer à cause d'un conflit de processus avec '%s' (en cours d'exécution).", -- src\editor\output.lua
|
||||
["Program completed in %.2f seconds (pid: %d)."] = "Programme terminé en %.2f secondes (pid : %d).", -- src\editor\output.lua
|
||||
["Program starting as '%s'."] = "Programme démarré en tant que '%s'.", -- src\editor\output.lua
|
||||
["Program stopped (pid: %d)."] = "Programme stoppé (pid: %d).", -- src\editor\debugger.lua
|
||||
["Program unable to run as '%s'."] = "Impossible d'écuter le programme en tant que '%s'.", -- src\editor\output.lua
|
||||
["Program stopped (pid: %d)."] = "Programme stoppé (pid : %d).", -- src\editor\debugger.lua
|
||||
["Program unable to run as '%s'."] = "Impossible d'exécuter le programme en tant que '%s'.", -- src\editor\output.lua
|
||||
["Project Directory"] = "Répertoire de projet", -- src\editor\menu_project.lua
|
||||
["Project"] = "Projet", -- src\editor\settings.lua, src\editor\gui.lua
|
||||
["Project/&FileTree Window"] = "Projet/Arborescence de fichiers", -- src\editor\menu_view.lua
|
||||
["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"] = "Remplacer 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"] = "Refaire la dernière édition annulée", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Refused a request to start a new debugging session as there is one in progress already."] = "Impossible de lancer une nouvelle session de débogage en plus de celle en cours.", -- src\editor\debugger.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
|
||||
["Remote console"] = "Console à distance", -- src\editor\shellbox.lua
|
||||
["Reset to default layout"] = "Retourner à l'affiche par défaut", -- src\editor\menu_view.lua
|
||||
["Resets the dynamic word list for autocompletion"] = "Redéfinir la liste des mots dynamiques pour auto-complétion", -- src\editor\menu_edit.lua
|
||||
["Run as Scratchpad"] = "Exécuter en Brouillon", -- src\editor\menu_project.lua
|
||||
["S&top Debugging"] = "Arrêter le débogueur", -- src\editor\menu_project.lua
|
||||
["S&top Process"] = "Arrêter le processus", -- src\editor\menu_project.lua
|
||||
["Save &As..."] = "Enregitrer sous...", -- src\editor\menu_file.lua
|
||||
["Save A&ll"] = "Enregister tout", -- src\editor\menu_file.lua
|
||||
["Save Changes?"] = "Enregister les modifications?", -- src\editor\commands.lua
|
||||
["Save all open documents"] = "Enregister tous les documents ouverts", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Save file as"] = "Enregsitrer le fichier sous", -- src\editor\commands.lua
|
||||
["Save file?"] = "Enregister le fichier?", -- src\editor\commands.lua
|
||||
["Save the current document to a file with a new name"] = "Enregister une copie du document en cours sous", -- src\editor\menu_file.lua
|
||||
["Save the current document"] = "Enregister le document en cours", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Saved auto-recover at %s."] = "Auto-enregistré à %s.", -- src\editor\commands.lua
|
||||
["Scratchpad error"] = "Erreur dans le Brouillon", -- src\editor\debugger.lua
|
||||
["Select &All"] = "Sélectionner tout", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["Replaced an invalid UTF8 character with %s."] = "Un caractère UTF8 invalide a été remplacé par %s.", -- src\editor\commands.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
|
||||
["S&top Debugging"] = "&Arrêter le débogage", -- src\editor\menu_project.lua
|
||||
["S&top Process"] = "&Arrêter le processus", -- src\editor\menu_project.lua
|
||||
["Save &As..."] = "Enregistrer &sous...", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Save A&ll"] = "Enregistrer &tout", -- src\editor\menu_file.lua
|
||||
["Save Changes?"] = "Enregistrer les modifications ?", -- src\editor\commands.lua
|
||||
["Save all open documents"] = "Enregistrer tous les documents ouverts", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Save file as"] = "Enregistrer le fichier sous", -- src\editor\commands.lua
|
||||
["Save file?"] = "Enregistrer le fichier ?", -- src\editor\commands.lua
|
||||
["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
|
||||
["Scratchpad error"] = "Erreur dans le brouillon", -- src\editor\debugger.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 project directory from current file"] = "Définir le répertoire de projet depuis le fichier courant", -- src\editor\gui.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
|
||||
["Show &Tooltip"] = "Affichier l'info-bulle", -- src\editor\menu_edit.lua
|
||||
["Show tooltip for current position; place cursor after opening bracket of function"] = "Afficher l'info-bulle pour la position actuelle; placer le curseur après avoir ouvert les parenthèses d'arguments de fontion", -- src\editor\menu_edit.lua
|
||||
["Sort selected lines"] = "trier les fichiers sélectionnés", -- src\editor\menu_search.lua
|
||||
["Stack Window"] = "Fenêtre de pile d'éxécution", -- src\editor\debugger.lua
|
||||
["Start &Debugging"] = "Démarrer le débogage", -- src\editor\menu_project.lua
|
||||
["Start debugging"] = "Démarrer le débogage", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Step &Into"] = "Pas dans", -- src\editor\menu_project.lua
|
||||
["Step &Over"] = "Pas sur", -- src\editor\menu_project.lua
|
||||
["Step O&ut"] = "Pas en dehors de", -- src\editor\menu_project.lua
|
||||
["Step into"] = "Pas dans", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Step out of the current function"] = "Pas en dehors de la fonction courante", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Step over"] = "Pas par-dessus la fonction courante", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Stop the currently running process"] = "Arrêter le processus en cours", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Switch to or from full screen mode"] = "Passer au/Quitter le mode Plein Ecran", -- src\editor\menu_view.lua
|
||||
["Set the project directory to be used"] = "Définir le répertoire de projet à utiliser", -- src\editor\menu_project.lua
|
||||
["Show &Tooltip"] = "Afficher l'info-&bulle", -- src\editor\menu_edit.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
|
||||
["Start &Debugging"] = "Lancer le &débogage", -- src\editor\menu_project.lua
|
||||
["Start debugging"] = "Lancer le débogage", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Step &Into"] = "Pas à pas détai&llé", -- src\editor\menu_project.lua
|
||||
["Step &Over"] = "Pas à pas so&mmaire", -- src\editor\menu_project.lua
|
||||
["Step O&ut"] = "Pas à pas so&rtant", -- src\editor\menu_project.lua
|
||||
["Step into"] = "Rentrer dans l'instruction suivante", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Step out of the current function"] = "Sortir de la fonction courante", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["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
|
||||
["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"] = "Basculer en Point d'Interruption", -- src\editor\menu_project.lua
|
||||
["Toggle breakpoint"] = "Basculer en point d'interruption", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Tr&ace"] = "Tracer", -- src\editor\menu_project.lua
|
||||
["Trace execution showing each executed line"] = "Traçage d'exécution du code", -- src\editor\menu_project.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
|
||||
["Tr&ace"] = "&Tracer", -- src\editor\menu_project.lua
|
||||
["Trace execution showing each executed line"] = "Tracer l'exécution en montrant chaque ligne de code exécutée", -- src\editor\menu_project.lua
|
||||
["Unable to load file '%s'."] = "Impossible de charger le le fichier '%s'.", -- src\editor\commands.lua
|
||||
["Unable to save file '%s': %s"] = "Impossible d'enregistrer le fichier '%s': %s", -- src\editor\commands.lua
|
||||
["Unable to stop program (pid: %d), code %d."] = "Impossible d'arrêter le programme (pid: %d), code %d.", -- src\editor\debugger.lua
|
||||
["Undo last edit"] = "Défaire la dernière édition", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Use 'clear' to clear the shell output and the history."] = "Utiliser 'clear' pour effacer la sortie console et l`historique.", -- src\editor\shellbox.lua
|
||||
["Use Shift-Enter for multiline code."] = "Pressez <Shift-Entrée> pour du code multiligne.", -- src\editor\shellbox.lua
|
||||
["Unable to save file '%s': %s"] = "Impossible d'enregistrer le fichier '%s' : %s", -- src\editor\commands.lua
|
||||
["Unable to stop program (pid: %d), code %d."] = "Impossible d'arrêter le programme (pid : %d), code %d.", -- src\editor\debugger.lua
|
||||
["Undo last edit"] = "Annuler la dernière modification", -- src\editor\menu_edit.lua
|
||||
["Use '%s' to see full description."] = "Utilisez '%s' pour voir la description complète.", -- src\editor\editor.lua
|
||||
["Use '%s' to show line endings and '%s' to convert them."] = "Utilisez '%s' pour afficher les fins de ligne et '%s' pour les convertir.", -- src\editor\commands.lua
|
||||
["Use 'clear' to clear the shell output and the history."] = "Utilisez 'clear' pour effacer la sortie console et l´historique.", -- src\editor\shellbox.lua
|
||||
["Use Shift-Enter for multiline code."] = "Appuyez sur <Shift-Entrée> pour du code multiligne.", -- src\editor\shellbox.lua
|
||||
["Value"] = "Valeur", -- src\editor\debugger.lua
|
||||
["View the output/console window"] = "Voir la sortie en console", -- src\editor\menu_view.lua
|
||||
["View the project/filetree window"] = "Voir l'arborescence des fichiers de projet", -- src\editor\menu_view.lua
|
||||
["View the stack window"] = "Voir la pile d'éxécution", -- src\editor\menu_view.lua, src\editor\gui.lua
|
||||
["View the watch window"] = "Voir la fenêtre d'observation", -- src\editor\menu_view.lua, src\editor\gui.lua
|
||||
["Watch Window"] = "Fenêtre d'observation", -- src\editor\debugger.lua
|
||||
["Welcome to the interactive Lua interpreter."] = "Bienvenue dans l`interpréteur interactif Lua.", -- src\editor\shellbox.lua
|
||||
["You must save the program first."] = "Enregistrez d'abord le programme", -- src\editor\commands.lua
|
||||
["View the output/console window"] = "Afficher la fenêtre de sortie/console", -- src\editor\menu_view.lua
|
||||
["View the project/filetree window"] = "Afficher la fenêtre d'explorateur de projet", -- src\editor\menu_view.lua
|
||||
["View the stack window"] = "Afficher la fenêtre de pile d'exécution", -- src\editor\menu_view.lua, src\editor\gui.lua
|
||||
["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
|
||||
["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
|
||||
["traced %d instruction"] = {"%d instruction tracée", "%d instructions tracées"} -- src\editor\debugger.lua
|
||||
}
|
||||
|
||||
@@ -3,10 +3,11 @@ return {
|
||||
["&About"] = "Informazioni", -- src\editor\menu_help.lua
|
||||
["&Add Watch"] = "&Aggiungi Espressione di Controllo", -- src\editor\debugger.lua
|
||||
["&Break"] = "Interrompi", -- src\editor\menu_project.lua
|
||||
["&Close page"] = "&Chiudi pagina", -- src\editor\menu_file.lua
|
||||
["&Close Page"] = "&Chiudi pagina", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["&Compile"] = "&Compila", -- src\editor\menu_project.lua
|
||||
["&Copy"] = "&Copia", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Default Layout"] = "Visualizzazione di &Default", -- src\editor\menu_view.lua
|
||||
["&Delete Watch"] = "Elimina Espressione di Controllo", -- src\editor\debugger.lua
|
||||
["&Edit Watch"] = "Modifica Espressione di Controllo", -- src\editor\debugger.lua
|
||||
["&Edit"] = "Modifica", -- src\editor\menu_edit.lua
|
||||
["&File"] = "File", -- src\editor\menu_file.lua
|
||||
@@ -20,10 +21,9 @@ return {
|
||||
["&Paste"] = "Incolla", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Project"] = "&Progetto", -- src\editor\menu_project.lua, src\editor\inspect.lua
|
||||
["&Redo"] = "&Ripeti", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Remove Watch"] = "Elimina Espressione di Controllo", -- src\editor\debugger.lua
|
||||
["&Replace"] = "Sostituisci", -- src\editor\menu_search.lua
|
||||
["&Run"] = "Lancia", -- src\editor\menu_project.lua
|
||||
["&Save"] = "&Salva", -- src\editor\menu_file.lua
|
||||
["&Save"] = "&Salva", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["&Search"] = "Ricerca", -- src\editor\menu_search.lua
|
||||
["&Sort"] = "Ordina", -- src\editor\menu_search.lua
|
||||
["&Stack Window"] = "Stack di chiamate", -- src\editor\menu_view.lua
|
||||
@@ -31,8 +31,7 @@ return {
|
||||
["&Undo"] = "Annulla", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&View"] = "Visualizza", -- src\editor\menu_view.lua
|
||||
["&Watch Window"] = "Finestra Espressioni di Controllo", -- src\editor\menu_view.lua
|
||||
["&Watches"] = "Espressioni di Controllo", -- src\editor\debugger.lua
|
||||
["About ZeroBrane Studio"] = "Informazioni su ZeroBrane Studio", -- src\editor\menu_help.lua
|
||||
["About %s"] = "Informazioni su %s", -- src\editor\menu_help.lua
|
||||
["Add Watch Expression"] = "Aggiungi Espressione di Controllo", -- src\editor\editor.lua
|
||||
["Add to Scratchpad"] = "Aggiungi a Scratchpad ", -- src\editor\editor.lua
|
||||
["All files"] = "Tutti i files", -- src\editor\commands.lua
|
||||
@@ -50,9 +49,12 @@ return {
|
||||
["Can't run the entry point script ('%s')."] = "Impossibile eseguire il punto di ingresos dello script (%s).", -- src\editor\debugger.lua
|
||||
["Can't start debugging session due to internal error '%s'."] = "Impossibile lanciare la sessione di debug: errore interno '%s'.'", -- src\editor\debugger.lua
|
||||
["Can't start debugging without an opened file or with the current file not being saved ('%s')."] = "Impossibile lanciare il debug senza aver aperto un file o se il file corrente non è stato salvato ('%s').", -- src\editor\debugger.lua
|
||||
["Choose ..."] = "Scegli...", -- src\editor\menu_project.lua
|
||||
["Choose a project directory"] = "Scegli la directory di un progetto", -- src\editor\menu_project.lua
|
||||
["Clear &Dynamic Words"] = "Elimna le &Dynamic Words", -- src\editor\menu_edit.lua
|
||||
["Clear the output window before compiling or debugging"] = "Pulisci la finestra di output prima di compilare o lanciare debug", -- src\editor\menu_project.lua
|
||||
["Close &Other Pages"] = "Chidi le Altre Pagine", -- src\editor\gui.lua
|
||||
["Close A&ll Pages"] = "Chiudi Tutte le Pagine", -- src\editor\gui.lua
|
||||
["Close the current editor window"] = "Chiude la finestra dell'edit corrente", -- src\editor\menu_file.lua
|
||||
["Co&ntinue"] = "Co&ntinua", -- src\editor\menu_project.lua
|
||||
["Col: %d"] = "Col: %d", -- src\editor\editor.lua
|
||||
@@ -62,23 +64,25 @@ return {
|
||||
["Compile the current file"] = "Compila il file corrente", -- src\editor\menu_project.lua
|
||||
["Complete &Identifier"] = "Completa l'&Identificatore", -- src\editor\menu_edit.lua
|
||||
["Complete the current identifier"] = "Completa l'identificatore corrente", -- src\editor\menu_edit.lua
|
||||
["Copy selected text to clipboard"] = "Copia il testo selezionato negli appunti", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Copy selected text to clipboard"] = "Copia il testo selezionato negli appunti", -- src\editor\menu_edit.lua
|
||||
["Couldn't activate file '%s' for debugging; continuing without it."] = "Impossibile attivare il file '%s' per debug; si prosegue senza.", -- src\editor\debugger.lua
|
||||
["Create an empty document"] = "Crea un documento vuoto", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Cu&t"] = "&Taglia", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["Cut selected text to clipboard"] = "Taglia il testo selezionato e mette negli appunti", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Cut selected text to clipboard"] = "Taglia il testo selezionato e mette negli appunti", -- src\editor\menu_edit.lua
|
||||
["Debugger server started at %s:%d."] = "Server Debugger iniziato %s:%s", -- src\editor\debugger.lua
|
||||
["Debugging session completed (%s)."] = "Sessione di debug completata (%s).", -- src\editor\debugger.lua
|
||||
["Debugging session started in '%s'."] = "Sessione di debug iniziata da '%s'.", -- src\editor\debugger.lua
|
||||
["Debugging suspended at %s:%s (couldn't activate the file)."] = "Debug sospeso a %s:%s (impossibile attivare il file).", -- src\editor\debugger.lua
|
||||
["Do you want to reload it?"] = "Vuoi ricaricarlo?", -- src\editor\editor.lua
|
||||
["Do you want to save the changes to '%s'?"] = "Vuoi salvare le modifiche a '%s'?", -- src\editor\commands.lua
|
||||
["E&xit"] = "Uscita", -- src\editor\menu_file.lua
|
||||
["Enter Lua code and press Enter to run it."] = "Inserisci codice Lua e premi <Enter> per eseguirlo.", -- src\editor\shellbox.lua
|
||||
["Enter line number"] = "Inserisci il numero di linea", -- src\editor\menu_search.lua
|
||||
["Error while loading API file: %s"] = "Errore durante il caricamento del file API: %s", -- src\editor\autocomplete.lua
|
||||
["Error while loading configuration file: %s"] = "Errore nel caricamento del file di configurazione: %s", -- src\editor\style.lua
|
||||
["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 &Watches"] = "Elabora Espressioni di Controllo", -- src\editor\debugger.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
|
||||
@@ -110,12 +114,14 @@ return {
|
||||
["Ln: %d"] = "Ln: %d", -- src\editor\editor.lua
|
||||
["Local console"] = "Console locale", -- src\editor\shellbox.lua, src\editor\gui.lua
|
||||
["Lua &Interpreter"] = "&Interprete Lua", -- src\editor\menu_project.lua
|
||||
["Mapped remote request for '%s' to '%s'."] = "Richiesta remota '%s' mappata su '%s'.", -- src\editor\debugger.lua
|
||||
["Mixed end-of-line encodings detected."] = "Trovata codifica Fine-Riga mista.", -- src\editor\commands.lua
|
||||
["OVR"] = "OVR", -- src\editor\editor.lua
|
||||
["Open an existing document"] = "Apri un documento esistente", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Open file"] = "Apri un file", -- src\editor\commands.lua
|
||||
["Output (running)"] = "Output (in corso d'esecuzione)", -- src\editor\output.lua
|
||||
["Output"] = "Output", -- src\editor\output.lua, src\editor\settings.lua, src\editor\gui.lua
|
||||
["Paste text from the clipboard"] = "Incolla testo dagli appunti", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Paste text from the clipboard"] = "Incolla testo dagli appunti", -- src\editor\menu_edit.lua
|
||||
["Prepend '=' to show complex values on multiple lines."] = "Prefissa '=' per visualizzare valori complessi su piu` righe", -- src\editor\shellbox.lua
|
||||
["Press cancel to abort."] = "Premi cancel per bloccare.", -- src\editor\commands.lua
|
||||
["Program '%s' started in '%s' (pid: %d)."] = "Programma '%s' partito da '%s' (pid: %d).", -- src\editor\output.lua
|
||||
@@ -124,21 +130,23 @@ return {
|
||||
["Program starting as '%s'."] = "Programma partito da '%s'.", -- src\editor\output.lua
|
||||
["Program stopped (pid: %d)."] = "Programma fermato (pid: %d).", -- src\editor\debugger.lua
|
||||
["Program unable to run as '%s'."] = "Il programma non puo' partire '%s'.", -- src\editor\output.lua
|
||||
["Project Directory"] = "Directory del Progetto", -- src\editor\menu_project.lua
|
||||
["Project"] = "Progetto", -- src\editor\settings.lua, src\editor\gui.lua
|
||||
["Project/&FileTree Window"] = "Progetto/Explorer", -- 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"] = "Sostituisci nei files", -- src\editor\menu_search.lua
|
||||
["Recent Files"] = "Files recenti", -- src\editor\menu_file.lua
|
||||
["Redo last edit undone"] = "Ripeti l'ultima azione annullata", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Redo last edit undone"] = "Ripeti l'ultima azione annullata", -- src\editor\menu_edit.lua
|
||||
["Refused a request to start a new debugging session as there is one in progress already."] = "Impossibile aprire una nuova sessione di debug in quanto ne esiste una in corso", -- src\editor\debugger.lua
|
||||
["Remote console"] = "Console remota", -- src\editor\shellbox.lua
|
||||
["Replaced an invalid UTF8 character with %s."] = "Sostituito un carattere UTF8 invalido con %s.", -- src\editor\commands.lua
|
||||
["Reset to default layout"] = "Ritorna al default layout", -- src\editor\menu_view.lua
|
||||
["Resets the dynamic word list for autocompletion"] = "Azzera la lista di dynamic words per l'autocompletamento", -- src\editor\menu_edit.lua
|
||||
["Run as Scratchpad"] = "Esegui in Scratchpad (Live coding)", -- src\editor\menu_project.lua
|
||||
["S&top Debugging"] = "Ferma il debugger", -- src\editor\menu_project.lua
|
||||
["S&top Process"] = "Ferma il processo", -- src\editor\menu_project.lua
|
||||
["Save &As..."] = "S&alva con nome...", -- src\editor\menu_file.lua
|
||||
["Save &As..."] = "S&alva con nome...", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Save A&ll"] = "Sa&lva tutto", -- src\editor\menu_file.lua
|
||||
["Save Changes?"] = "Vuoi salvare le modifiche?", -- src\editor\commands.lua
|
||||
["Save all open documents"] = "Salva tutti i documenti aperti", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
@@ -150,12 +158,14 @@ return {
|
||||
["Scratchpad error"] = "Errore durente Scratchpad", -- src\editor\debugger.lua
|
||||
["Select &All"] = "Selezion&a Tutto", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["Select all text in the editor"] = "Seleziona tutto il testo nell'editor", -- src\editor\menu_edit.lua
|
||||
["Set project directory from current file"] = "Definisci la directory del progeetto dal file corrente", -- src\editor\gui.lua
|
||||
["Set From Current File"] = "Impostato da file corrente", -- src\editor\menu_project.lua
|
||||
["Set project directory from current file"] = "Definisci la directory del progeetto dal file corrente", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Set the interpreter to be used"] = "Definisci l'interprete da utilizzare", -- src\editor\menu_project.lua
|
||||
["Set the project directory to be used"] = "Imposta la directory di progetto da usare", -- src\editor\menu_project.lua
|
||||
["Show &Tooltip"] = "Mos&tra i consgli", -- src\editor\menu_edit.lua
|
||||
["Show tooltip for current position; place cursor after opening bracket of function"] = "Mostra i consigli per la posizione corrente; muovi il cursore dopo la parentesi o la funzione", -- src\editor\menu_edit.lua
|
||||
["Sort selected lines"] = "Ordina le righe selezionate", -- src\editor\menu_search.lua
|
||||
["Stack Window"] = "Finestra Stack", -- src\editor\debugger.lua
|
||||
["Stack"] = "Stack", -- src\editor\debugger.lua
|
||||
["Start &Debugging"] = "Inizia il &Debug", -- src\editor\menu_project.lua
|
||||
["Start debugging"] = "Inizia il Debug", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Step &Into"] = "Step &Into", -- src\editor\menu_project.lua
|
||||
@@ -174,7 +184,9 @@ return {
|
||||
["Unable to load file '%s'."] = "Impossibile aprire il file '%s'.", -- src\editor\commands.lua
|
||||
["Unable to save file '%s': %s"] = "Impossibile salvare il file '%s': %s", -- src\editor\commands.lua
|
||||
["Unable to stop program (pid: %d), code %d."] = "Impossibile fermare il programma (pid: %d), code %d.", -- src\editor\debugger.lua
|
||||
["Undo last edit"] = "Annulla l'ultima azione di edit", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Undo last edit"] = "Annulla l'ultima azione di edit", -- src\editor\menu_edit.lua
|
||||
["Use '%s' to see full description."] = "Utilizza '%s' per vedere la descrizione completa.", -- src\editor\editor.lua
|
||||
["Use '%s' to show line endings and '%s' to convert them."] = "Utilizza '%s' per vedere la fine della riga e '%s' per convertirli.", -- src\editor\commands.lua
|
||||
["Use 'clear' to clear the shell output and the history."] = "Utilizza 'clear' per pulire l`output e lo storico.", -- src\editor\shellbox.lua
|
||||
["Use Shift-Enter for multiline code."] = "Premi <Shift-Invio> per inserire piu` righe di codice.", -- src\editor\shellbox.lua
|
||||
["Value"] = "Valore", -- src\editor\debugger.lua
|
||||
@@ -182,9 +194,9 @@ return {
|
||||
["View the project/filetree window"] = "Mostra la finestra di progetto/explorer", -- src\editor\menu_view.lua
|
||||
["View the stack window"] = "Mostra la finestra dello Stack", -- src\editor\menu_view.lua, src\editor\gui.lua
|
||||
["View the watch window"] = "Mostra la finestra delle Espressioni di Controllo", -- src\editor\menu_view.lua, src\editor\gui.lua
|
||||
["Watch Window"] = "Finestra Espressioni di Controllo", -- src\editor\debugger.lua
|
||||
["Watch"] = "Watch", -- src\editor\debugger.lua
|
||||
["Welcome to the interactive Lua interpreter."] = "Benvenuti nell`interprete interattivo Lua.", -- src\editor\shellbox.lua
|
||||
["You must save the program first."] = "Devi prima salvare il programma", -- src\editor\commands.lua
|
||||
["on line %d"] = "alla linea %d", -- src\editor\debugger.lua, src\editor\commands.lua
|
||||
["traced %d instruction"] = {"tracciata %d istruzione", "%d istruzioni tracciate"} -- src\editor\debugger.lua
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
return {
|
||||
[0] = function(c) return (c%10 == 1 and c%100 ~= 11) and 1 or (c%10 >= 2 and c%10 <= 4 and (c%100 < 10 or c%100 >= 20) and 2) or 3 end, -- plural
|
||||
[0] = function(c) c = (c-9)%100 < 9 and 9 or (c-1)%10 return c == 0 and 1 or c < 4 and 2 or 3 end, -- plural
|
||||
["%d instance"] = {"%d совпадение", "%d совпадения", "%d совпадений"}, -- src\editor\findreplace.lua
|
||||
["&About"] = "&О программе", -- src\editor\menu_help.lua
|
||||
["&Add Watch"] = "&Добавить выражение", -- src\editor\debugger.lua
|
||||
["&Break"] = "Пр&ервать", -- src\editor\menu_project.lua
|
||||
["&Close page"] = "&Закрыть", -- src\editor\menu_file.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
|
||||
@@ -20,20 +25,22 @@ return {
|
||||
["&Paste"] = "В&ставить", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Project"] = "Пр&оект", -- src\editor\menu_project.lua, src\editor\inspect.lua
|
||||
["&Redo"] = "Верну&ть", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Remove Watch"] = "&Удалить выражение", -- src\editor\debugger.lua
|
||||
["&Replace"] = "За&менить", -- src\editor\menu_search.lua
|
||||
["&Replace All"] = "Заменить всe", -- src\editor\findreplace.lua
|
||||
["&Replace"] = "За&менить", -- src\editor\findreplace.lua, src\editor\menu_search.lua
|
||||
["&Run"] = "За&пустить", -- src\editor\menu_project.lua
|
||||
["&Save"] = "&Сохранить", -- src\editor\menu_file.lua
|
||||
["&Save"] = "&Сохранить", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["&Search"] = "По&иск", -- src\editor\menu_search.lua
|
||||
["&Sort"] = "&Cортировать", -- src\editor\menu_search.lua
|
||||
["&Stack Window"] = "Окно &стека", -- src\editor\menu_view.lua
|
||||
["&Start Debugger Server"] = "Запустить сервер отла&дки", -- src\editor\menu_project.lua
|
||||
["&Subdirectories"] = "В папках", -- src\editor\findreplace.lua
|
||||
["&Undo"] = "&Отменить", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["&Up"] = "Вверх", -- src\editor\findreplace.lua
|
||||
["&View"] = "&Вид", -- src\editor\menu_view.lua
|
||||
["&Watch Window"] = "Окно &наблюдения", -- src\editor\menu_view.lua
|
||||
["&Watches"] = "&Выражения", -- src\editor\debugger.lua
|
||||
["About ZeroBrane Studio"] = "О ZeroBrane Studio", -- src\editor\menu_help.lua
|
||||
["Add Watch Expression"] = "Добавить в окно наблюдения", -- src\editor\editor.lua
|
||||
["&Watch Window"] = "Окно &выражений", -- src\editor\menu_view.lua
|
||||
[".&bak on Replace"] = ".&bak после замены", -- src\editor\findreplace.lua
|
||||
["About %s"] = "О %s", -- src\editor\menu_help.lua
|
||||
["Add Watch Expression"] = "Добавить выражение", -- src\editor\editor.lua
|
||||
["Add to Scratchpad"] = "Добавить в черновик", -- src\editor\editor.lua
|
||||
["All files"] = "Все файлы", -- src\editor\commands.lua
|
||||
["Allow external process to start debugging"] = "Разрешить внешнему процессу начать отладку", -- src\editor\menu_project.lua
|
||||
@@ -50,9 +57,13 @@ return {
|
||||
["Can't run the entry point script ('%s')."] = "Ошибка выполнения стартового скрипта ('%s').", -- src\editor\debugger.lua
|
||||
["Can't start debugging session due to internal error '%s'."] = "Невозможно начать отладочную сессию из-за внутренней ошибки '%s'.", -- src\editor\debugger.lua
|
||||
["Can't start debugging without an opened file or with the current file not being saved ('%s')."] = "Невозможно начать отладку без открытого файла или с несохраненным текущим файлом ('%s').", -- src\editor\debugger.lua
|
||||
["Choose a project directory"] = "Выберите каталог проекта", -- src\editor\menu_project.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
|
||||
@@ -62,23 +73,26 @@ return {
|
||||
["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"] = "Скопировать выделенный текст в буфер обмена", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Copy selected text to 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"] = "Вырезать выделенный текст в буфер обмена", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Cut selected text to 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"] = "Ошибка загрузки файла конфигурации: %s", -- src\editor\style.lua
|
||||
["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 &Watches"] = "&Вычислить выражения", -- src\editor\debugger.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
|
||||
@@ -88,34 +102,45 @@ return {
|
||||
["Expression"] = "Выражение", -- src\editor\debugger.lua
|
||||
["File '%s' has been modified on disk."] = "Файл '%s' был изменен на диске.", -- src\editor\editor.lua
|
||||
["File '%s' has more recent timestamp than restored '%s'; please review before saving."] = "Файл '%s' имеет более позднее время модификации, чем восстановленный '%s'; пожалуйста просмотрите его перед сохранением.", -- src\editor\commands.lua
|
||||
["File '%s' no longer exists."] = "Файл '%s' больше не существует.", -- src\editor\editor.lua
|
||||
["File '%s' no longer exists."] = "Файл '%s' больше не существует.", -- src\editor\editor.lua, src\editor\menu_file.lua
|
||||
["File Type"] = "Тип файла", -- src\editor\findreplace.lua
|
||||
["File history"] = "История файлов", -- src\editor\menu_file.lua
|
||||
["Find &In Files"] = "Н&айти в файлах", -- src\editor\menu_search.lua
|
||||
["Find &Next"] = "Найти &далее", -- src\editor\menu_search.lua
|
||||
["Find &Previous"] = "Найти &ранее", -- src\editor\menu_search.lua
|
||||
["Find In Files"] = "Найти в файлах", -- src\editor\findreplace.lua
|
||||
["Find and replace text in files"] = "Найти и заменить текст в файлах", -- src\editor\menu_search.lua
|
||||
["Find and replace text"] = "Найти и заменить текст", -- src\editor\menu_search.lua, src\editor\gui.lua
|
||||
["Find text in files"] = "Найти текст в файлах", -- src\editor\menu_search.lua
|
||||
["Find text"] = "Найти текст", -- src\editor\menu_search.lua, src\editor\gui.lua
|
||||
["Find the earlier text occurence"] = "Найти предыдущее вхождение текста", -- src\editor\menu_search.lua
|
||||
["Find the next text occurrence"] = "Найти следующее вхождение текста", -- src\editor\menu_search.lua
|
||||
["Find"] = "Найти", -- src\editor\findreplace.lua
|
||||
["Fold or unfold all code folds"] = "Свернуть или развернуть все блоки кода", -- src\editor\menu_edit.lua
|
||||
["Found auto-recovery record and restored saved session."] = "Найдена запись авто-восстановления и восстановлена сохраненная сессия.", -- src\editor\commands.lua
|
||||
["Found"] = "Найдено", -- src\editor\findreplace.lua
|
||||
["Full &Screen"] = "Во весь экр&ан", -- src\editor\menu_view.lua
|
||||
["Go to a selected line"] = "Перейти к заданной строке", -- src\editor\menu_search.lua
|
||||
["Goto Line"] = "Перейти к строке", -- src\editor\menu_search.lua
|
||||
["INS"] = "ВСТ", -- src\editor\editor.lua
|
||||
["In Files"] = "Установки файлов", -- src\editor\findreplace.lua
|
||||
["Jump to a function definition..."] = "Перейти к определению функции...", -- src\editor\editor.lua
|
||||
["Known Files"] = "Файлы Lua", -- src\editor\commands.lua
|
||||
["Ln: %d"] = "Стр: %d", -- src\editor\editor.lua
|
||||
["Local console"] = "Локальная консоль", -- src\editor\shellbox.lua, src\editor\gui.lua
|
||||
["Lua &Interpreter"] = "&Интерпретатор Lua", -- src\editor\menu_project.lua
|
||||
["Mapped remote request for '%s' to '%s'."] = "Удаленный запрос для '%s' отображен на '%s'.", -- src\editor\debugger.lua
|
||||
["Match &case"] = "Совпадение регистра", -- src\editor\findreplace.lua
|
||||
["Match &whole word"] = "Совпадение целого слова", -- src\editor\findreplace.lua
|
||||
["Mixed end-of-line encodings detected."] = "Обнаружены смешанные символы конца строки.", -- src\editor\commands.lua
|
||||
["OVR"] = "ЗАМ", -- src\editor\editor.lua
|
||||
["Open an existing document"] = "Открыть существующий документ", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Open file"] = "Открыть файл", -- src\editor\commands.lua
|
||||
["Options"] = "Установки", -- src\editor\findreplace.lua
|
||||
["Output (running)"] = "Вывод (запущен)", -- src\editor\output.lua
|
||||
["Output"] = "Вывод", -- src\editor\output.lua, src\editor\settings.lua, src\editor\gui.lua
|
||||
["Paste text from the clipboard"] = "Вставить текст из буфера обмена", -- src\editor\menu_edit.lua, src\editor\gui.lua
|
||||
["Paste text from the clipboard"] = "Вставить текст из буфера обмена", -- src\editor\menu_edit.lua
|
||||
["Preferences"] = "Настройки", -- src\editor\menu_edit.lua
|
||||
["Prepend '=' to show complex values on multiple lines."] = "Укажите '=' в начале выражения для отображения сложных значений на нескольких строках.", -- src\editor\shellbox.lua
|
||||
["Press cancel to abort."] = "Нажмите Отмена для завершения.", -- src\editor\commands.lua
|
||||
["Program '%s' started in '%s' (pid: %d)."] = "Программа '%s' запущена в '%s' (pid: %d).", -- src\editor\output.lua
|
||||
@@ -124,21 +149,28 @@ return {
|
||||
["Program starting as '%s'."] = "Программа запускается как '%s'.", -- src\editor\output.lua
|
||||
["Program stopped (pid: %d)."] = "Программа завершена (pid: %d).", -- src\editor\debugger.lua
|
||||
["Program unable to run as '%s'."] = "Программа не может быть запущена как '%s'.", -- src\editor\output.lua
|
||||
["Project Directory"] = "Папка проекта", -- src\editor\menu_project.lua
|
||||
["Project"] = "Проект", -- src\editor\settings.lua, src\editor\gui.lua
|
||||
["Project/&FileTree Window"] = "Окно &проекта/списка файлов", -- 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"] = "Замени&ть в файлах", -- src\editor\menu_search.lua
|
||||
["Recent Files"] = "Недавние файлы", -- src\editor\menu_file.lua
|
||||
["Redo last edit undone"] = "Вернуть последнее отмененное изменение", -- src\editor\menu_edit.lua, src\editor\gui.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."] = "Некорректный символ UTF8 заменен на %s.", -- src\editor\commands.lua
|
||||
["Replaced"] = "Заменено", -- src\editor\findreplace.lua
|
||||
["Replacing"] = "Замена", -- src\editor\findreplace.lua
|
||||
["Reset to default layout"] = "Установить расположение окон по умолчанию", -- src\editor\menu_view.lua
|
||||
["Resets the dynamic word list for autocompletion"] = "Очистить список динамических слов для автодополнения", -- src\editor\menu_edit.lua
|
||||
["Run as Scratchpad"] = "Запустить как черновик", -- src\editor\menu_project.lua
|
||||
["S&top Debugging"] = "&Завершить отладку", -- src\editor\menu_project.lua
|
||||
["S&top Process"] = "&Завершить процесс", -- src\editor\menu_project.lua
|
||||
["Save &As..."] = "Сохранить &как...", -- src\editor\menu_file.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
|
||||
@@ -147,15 +179,21 @@ return {
|
||||
["Save the current document to a file with a new name"] = "Сохранить текущий документ в файл под новым именем", -- src\editor\menu_file.lua
|
||||
["Save the current document"] = "Сохранить текущий документ", -- src\editor\menu_file.lua, src\editor\gui.lua
|
||||
["Saved auto-recover at %s."] = "Сохранено авто-восст в %s.", -- src\editor\commands.lua
|
||||
["Scope"] = "Направление", -- src\editor\findreplace.lua
|
||||
["Scratchpad error"] = "Ошибка в черновике", -- src\editor\debugger.lua
|
||||
["Searching for"] = "Поиск", -- src\editor\findreplace.lua
|
||||
["Select &All"] = "Выделить &все", -- src\editor\editor.lua, src\editor\menu_edit.lua
|
||||
["Select all text in the editor"] = "Выделить весь текст в редакторе", -- src\editor\menu_edit.lua
|
||||
["Set project directory from current file"] = "Установить каталог проекта по текущему файлу", -- src\editor\gui.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"] = "Показать &подсказку", -- src\editor\menu_edit.lua
|
||||
["Show tooltip for current position; place cursor after opening bracket of function"] = "Показать подсказку в текущей позиции; переместите курсор в позицию после открывающей скобки функции", -- src\editor\menu_edit.lua
|
||||
["Sort selected lines"] = "Отсортировать выделенные строки", -- src\editor\menu_search.lua
|
||||
["Stack Window"] = "Окно стека", -- src\editor\debugger.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
|
||||
@@ -166,7 +204,8 @@ return {
|
||||
["Step over"] = "Перейти на следующую строку", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Stop the currently running process"] = "Завершить текущий процесс", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Switch to or from full screen mode"] = "Переключить полноэкранный режим", -- src\editor\menu_view.lua
|
||||
["The API file must be located in a subdirectory of the API directory."] = "Файл определений API должен быть расположен в подкаталоге каталога API.", -- src\editor\autocomplete.lua
|
||||
["Text not found."] = "Текст не найден.", -- src\editor\findreplace.lua
|
||||
["The API file must be located in a subdirectory of the API directory."] = "Файл определений API должен быть расположен внутри папки API.", -- src\editor\autocomplete.lua
|
||||
["Toggle Break&point"] = "&Точка останова", -- src\editor\menu_project.lua
|
||||
["Toggle breakpoint"] = "Переключить точку останова", -- src\editor\menu_project.lua, src\editor\gui.lua
|
||||
["Tr&ace"] = "Т&рассировка", -- src\editor\menu_project.lua
|
||||
@@ -174,16 +213,19 @@ return {
|
||||
["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, src\editor\gui.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' для очистки содержимого окна и истории.", -- 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 Window"] = "Окно наблюдения", -- src\editor\debugger.lua
|
||||
["View the watch window"] = "Показать окно выражений", -- src\editor\menu_view.lua, src\editor\gui.lua
|
||||
["Watch"] = "Выражение", -- src\editor\debugger.lua
|
||||
["Welcome to the interactive Lua interpreter."] = "Добро пожаловать в интерактивный интерпретатор Lua.", -- src\editor\shellbox.lua
|
||||
["Wrap ar&ound"] = "Продолжить сначала", -- src\editor\findreplace.lua
|
||||
["You must save the program first."] = "Вы должны сначала сохранить программу.", -- src\editor\commands.lua
|
||||
["on line %d"] = "в строке %d", -- src\editor\debugger.lua, src\editor\commands.lua
|
||||
["traced %d instruction"] = {"выполнена %d инструкция", "выполнено %d инструкции", "выполнено %d инструкций"}, -- src\editor\debugger.lua
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
--[[
|
||||
1. Pick a color scheme by clicking on a link:
|
||||
- [Tomorrow](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','Tomorrow')))
|
||||
- [TomorrowContrast](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','TomorrowContrast')))
|
||||
- [TomorrowNight](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','TomorrowNight')))
|
||||
- [TomorrowNightBlue](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','TomorrowNightBlue')))
|
||||
- [TomorrowNightBright](macro:shell(ApplyStyleConfig('cfg/tomorrow.lua','TomorrowNightBright')))
|
||||
|
||||
@@ -37,6 +37,20 @@ local colors = {
|
||||
Blue = H'4271ae',
|
||||
Purple = H'8959a8',
|
||||
},
|
||||
TomorrowContrast = { -- contributed by Sergey Lerg
|
||||
Background = H'f7f7f7',
|
||||
CurrentLine = H'efefef',
|
||||
Selection = H'd6d6d6',
|
||||
Foreground = H'202020',
|
||||
Comment = H'8e908c',
|
||||
Red = H'4669ff', --numbers
|
||||
Orange = H'f5871f',
|
||||
Yellow = H'eab700',
|
||||
Green = H'108010', --strings
|
||||
Aqua = H'4060b0', --built in functions
|
||||
Blue = H'101080', --keywords
|
||||
Purple = H'a01090',
|
||||
},
|
||||
TomorrowNight = {
|
||||
Background = H'1d1f21',
|
||||
CurrentLine = H'282a2e',
|
||||
@@ -109,7 +123,7 @@ local colors = {
|
||||
},
|
||||
Monokai = {
|
||||
Background = H'272822',
|
||||
CurrentLine = H'49483E',
|
||||
CurrentLine = H'2D2F29',
|
||||
Selection = H'49483E',
|
||||
Foreground = H'F8F8F2',
|
||||
Comment = H'75715E',
|
||||
@@ -182,15 +196,15 @@ return {
|
||||
-- wxstc.wxSTC_LUA_NUMBER
|
||||
number = {fg = C.Red},
|
||||
|
||||
-- wxstc.wxSTC_LUA_WORD, wxstc.wxSTC_LUA_WORD#
|
||||
-- wxstc.wxSTC_LUA_WORD, wxstc.wxSTC_LUA_WORD2-8
|
||||
keywords0 = {fg = C.Blue, b = true},
|
||||
keywords1 = {fg = C.Aqua, b = false},
|
||||
keywords2 = {fg = C.Aqua, b = true},
|
||||
keywords3 = {fg = C.Purple, b = true},
|
||||
keywords4 = {fg = C.Purple, b = true},
|
||||
keywords5 = {fg = C.Purple, b = true},
|
||||
keywords6 = {fg = C.Purple, b = true},
|
||||
keywords7 = {fg = C.Purple, b = true},
|
||||
keywords3 = {fg = C.Purple, b = false},
|
||||
keywords4 = {fg = C.Purple, b = false},
|
||||
keywords5 = {fg = C.Purple, b = false},
|
||||
keywords6 = {fg = C.Purple, b = false},
|
||||
keywords7 = {fg = C.Purple, b = false},
|
||||
|
||||
-- common (inherit fg/bg from text)
|
||||
-- wxstc.wxSTC_LUA_IDENTIFIER
|
||||
@@ -218,7 +232,7 @@ return {
|
||||
wxSTC_INDIC_DIAGONAL Diagonal hatching
|
||||
wxSTC_INDIC_STRIKE Strike-out
|
||||
wxSTC_INDIC_BOX Box
|
||||
wxSTC_INDIC_ROUNDBOX Rounded Box (not suppored in the current version?)
|
||||
wxSTC_INDIC_ROUNDBOX Rounded Box
|
||||
--]]
|
||||
|
||||
-- markup
|
||||
@@ -244,8 +258,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---- Zenburn license ----
|
||||
|
||||
GNU GPL, http://www.gnu.org/licenses/gpl.html
|
||||
|
||||
--]]
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
--[[-- Copy required content from this file to `user.lua`
|
||||
--[[-- This file shows examples of settings you can adjust.
|
||||
|
||||
Configuration files are loaded in the following order
|
||||
Configuration files with preferences are loaded in the following order:
|
||||
1. cfg/user.lua (system-wide configuration)
|
||||
2. HOME/.zbstudio/user.lua (per-user configuration)
|
||||
3. -cfg <lua code fragment|filename> (command line configuration)
|
||||
|
||||
1. <application>\config.lua
|
||||
2. cfg\user.lua
|
||||
3. ~\.zbstudio\user.lua
|
||||
4. -cfg commandline strings
|
||||
See [configuration](http://studio.zerobrane.com/doc-configuration.html) page for information about location of configuration files.
|
||||
|
||||
--]]--
|
||||
|
||||
@@ -47,7 +47,7 @@ path.lua = 'd:/lua/lua'
|
||||
path.gslshell = [[D:\Lua\gsl-shell\gsl-shell.exe]]
|
||||
|
||||
-- to provide output filter for those engines that support redirecting
|
||||
-- of "print" output to the IDE (like Corona SDK and Gideros)
|
||||
-- of "print" output to the IDE (like Corona SDK or Gideros)
|
||||
debugger.outputfilter = function(m) return #m < 124 and m or m:sub(1,120).."...\n" end
|
||||
|
||||
-- to fix an issue with 0d0d0a line endings in MOAI examples,
|
||||
@@ -96,3 +96,42 @@ stylesoutshell = styles
|
||||
|
||||
-- to disable indicators (underlining) on function calls
|
||||
editor.showfncall = false
|
||||
|
||||
-- to change the color of the indicator used for function calls
|
||||
styles.fncall.fg = {240,0,0}
|
||||
|
||||
-- to change the type of the indicator used for function calls
|
||||
styles.fncall.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
|
||||
--]]
|
||||
|
||||
-- to enable additional spec files (like spec/cpp.lua)
|
||||
load.specs(function(file) return file:find('spec[/\\]cpp%.lua$') end)
|
||||
|
||||
-- to specify a default EOL encoding to be used for new files:
|
||||
-- `wxstc.wxSTC_EOL_CRLF` or `wxstc.wxSTC_EOL_LF`;
|
||||
-- `nil` means OS default: CRLF on Windows and LF on Linux/Unix and OSX.
|
||||
-- (OSX had CRLF as a default until v0.36, which fixed it).
|
||||
editor.defaulteol = wxstc.wxSTC_EOL_LF
|
||||
|
||||
-- to turn off checking for mixed end-of-line encodings in loaded files
|
||||
editor.checkeol = false
|
||||
|
||||
-- to force execution to continue immediately after starting debugging;
|
||||
-- set to `false` to disable (the interpreter will stop on the first line or
|
||||
-- when debugging starts); some interpreters may use `true` or `false`
|
||||
-- by default, but can be still reconfigured with this setting.
|
||||
debugger.runonstart = true
|
||||
|
||||
-- to set compact fold that doesn't include empty lines after a block
|
||||
editor.foldcompact = true
|
||||
|
||||
-- to disable zoom with mouse wheel as it may be too sensitive on OSX
|
||||
editor.nomousezoom = true
|
||||
|
||||
59
cfg/user-snippet.lua
Normal file
59
cfg/user-snippet.lua
Normal file
@@ -0,0 +1,59 @@
|
||||
--[[-- Copy snippets from this file to `user.lua` --]]--
|
||||
|
||||
--[[ Add a shortcut to generate `~` if your keyboard doesn't have one
|
||||
local G = ... -- this now points to the global environment in the script
|
||||
local ide, wx, TR, ID = G.ide, G.wx, G.TR, G.ID
|
||||
local postinit = ide.app.postinit
|
||||
ide.app.postinit = function()
|
||||
if postinit then postinit() end
|
||||
local menu = ide.frame.menuBar:GetMenu(ide.frame.menuBar:FindMenu(TR("&Edit")))
|
||||
menu:Append(ID "tilde", "Tilde\tAlt-'")
|
||||
ide.frame:Connect(ID "tilde", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () GetEditor():AddText("~") end)
|
||||
end
|
||||
--]]
|
||||
|
||||
--[[ Add `Evaluate in Console` option to the Edit menu
|
||||
local G = ... -- this now points to the global environment in the script
|
||||
local ide, wx, TR, ID = G.ide, G.wx, G.TR, G.ID
|
||||
local postinit = ide.app.postinit
|
||||
ide.app.postinit = function()
|
||||
if postinit then postinit() end
|
||||
local menu = ide.frame.menuBar:GetMenu(ide.frame.menuBar:FindMenu(TR("&Edit")))
|
||||
menu:Append(ID "eval", "Evaluate in Console\tCtrl-E")
|
||||
ide.frame:Connect(ID "eval", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () ShellExecuteCode(GetEditor():GetSelectedText()) end)
|
||||
ide.frame:Connect(ID "eval", wx.wxEVT_UPDATE_UI,
|
||||
function (event) event:Enable(GetEditor() and #GetEditor():GetSelectedText() > 0) end)
|
||||
end
|
||||
--]]
|
||||
|
||||
--[[ Add `Zoom` menu to increase/decrease/reset font in the editor
|
||||
local G = ... -- this now points to the global environment in the script
|
||||
local ide, wx, TR, ID = G.ide, G.wx, G.TR, G.ID
|
||||
local postinit = ide.app.postinit
|
||||
ide.app.postinit = function()
|
||||
if postinit then postinit() end
|
||||
|
||||
local zoomMenu = wx.wxMenu{
|
||||
{ID "zoomreset", "Zoom to 100%\tCtrl-0"},
|
||||
{ID "zoomin", "Zoom In\tCtrl-+"},
|
||||
{ID "zoomout", "Zoom Out\tCtrl--"},
|
||||
}
|
||||
local menu = ide.frame.menuBar:GetMenu(ide.frame.menuBar:FindMenu(TR("&View")))
|
||||
menu:Append(ID "zoom", "Zoom", zoomMenu)
|
||||
|
||||
ide.frame:Connect(ID "zoomreset", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () GetEditor():SetZoom(1) end)
|
||||
ide.frame:Connect(ID "zoomin", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () GetEditor():SetZoom(GetEditor():GetZoom()+1) end)
|
||||
ide.frame:Connect(ID "zoomout", wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () GetEditor():SetZoom(GetEditor():GetZoom()-1) end)
|
||||
|
||||
-- only enable if there is an editor
|
||||
for _, m in G.ipairs({"zoomreset", "zoomin", "zoomout"}) do
|
||||
ide.frame:Connect(ID(m), wx.wxEVT_UPDATE_UI,
|
||||
function (event) event:Enable(GetEditor() ~= nil) end)
|
||||
end
|
||||
end
|
||||
--]]
|
||||
74
cfg/xcode-keys.lua
Normal file
74
cfg/xcode-keys.lua
Normal file
@@ -0,0 +1,74 @@
|
||||
-- Copy the content of this file to user.lua;
|
||||
-- see the [configuration](http://studio.zerobrane.com/doc-configuration.html) page for details.
|
||||
|
||||
local G = ...
|
||||
-- Alt-Shift-Cmd-X (Alt maps to Option, Ctrl maps to Command)
|
||||
-- The mapping is largely based on [Xcode Keyboard Shortcuts](http://developer.apple.com/library/mac/#documentation/IDEs/Conceptual/xcode_help-command_shortcuts/MenuCommands/MenuCommands014.html).
|
||||
local xcode = {
|
||||
-- File menu
|
||||
[G.ID_NEW] = "Ctrl-N",
|
||||
[G.ID_OPEN] = "Ctrl-O",
|
||||
[G.ID_CLOSE] = "Ctrl-W",
|
||||
[G.ID_SAVE] = "Ctrl-S",
|
||||
[G.ID_SAVEAS] = "Shift-Ctrl-S",
|
||||
[G.ID_SAVEALL] = "Alt-Ctrl-S",
|
||||
[G.ID_RECENTFILES] = "",
|
||||
[G.ID_EXIT] = "Ctrl-Q",
|
||||
-- Edit menu
|
||||
[G.ID_CUT] = "Ctrl-X",
|
||||
[G.ID_COPY] = "Ctrl-C",
|
||||
[G.ID_PASTE] = "Ctrl-V",
|
||||
[G.ID_SELECTALL] = "Ctrl-A",
|
||||
[G.ID_UNDO] = "Ctrl-Z",
|
||||
[G.ID_REDO] = "Shift-Ctrl-Z",
|
||||
[G.ID_SHOWTOOLTIP] = "Ctrl-T",
|
||||
[G.ID_AUTOCOMPLETE] = "Ctrl-K",
|
||||
[G.ID_AUTOCOMPLETEENABLE] = "",
|
||||
[G.ID_COMMENT] = "Ctrl-U",
|
||||
[G.ID_FOLD] = "F12",
|
||||
[G.ID_CLEARDYNAMICWORDS] = "",
|
||||
-- Search menu
|
||||
[G.ID_FIND] = "Ctrl-F",
|
||||
[G.ID_FINDNEXT] = "Ctrl-G",
|
||||
[G.ID_FINDPREV] = "Shift-Ctrl-G",
|
||||
[G.ID_REPLACE] = "Alt-Ctrl-F",
|
||||
[G.ID_FINDINFILES] = "Shift-Ctrl-F",
|
||||
[G.ID_REPLACEINFILES] = "Alt-Shift-Ctrl-F",
|
||||
[G.ID_GOTOLINE] = "",
|
||||
[G.ID_SORT] = "",
|
||||
-- View menu
|
||||
[G.ID_VIEWFILETREE] = "Shift-Ctrl-P",
|
||||
[G.ID_VIEWOUTPUT] = "Shift-Ctrl-O",
|
||||
[G.ID_VIEWWATCHWINDOW] = "Shift-Ctrl-W",
|
||||
[G.ID_VIEWCALLSTACK] = "Shift-Ctrl-S",
|
||||
[G.ID_VIEWDEFAULTLAYOUT] = "",
|
||||
[G.ID_VIEWFULLSCREEN] = "Shift-Ctrl-A",
|
||||
-- Project menu
|
||||
[G.ID_RUN] = "Ctrl-R",
|
||||
[G.ID_RUNNOW] = "Shift-Ctrl-R",
|
||||
[G.ID_COMPILE] = "Ctrl-B",
|
||||
[G.ID_ANALYZE] = "Shift-Ctrl-B",
|
||||
[G.ID_STARTDEBUG] = "F5",
|
||||
[G.ID_ATTACHDEBUG] = "",
|
||||
[G.ID_STOPDEBUG] = "Ctrl-.",
|
||||
[G.ID_STEP] = "F7",
|
||||
[G.ID_STEPOVER] = "F6",
|
||||
[G.ID_STEPOUT] = "F8",
|
||||
[G.ID_TRACE] = "",
|
||||
[G.ID_BREAK] = "Ctrl-Y",
|
||||
[G.ID_TOGGLEBREAKPOINT] = "Ctrl-\\",
|
||||
[G.ID_CLEAROUTPUT] = "",
|
||||
[G.ID_INTERPRETER] = "",
|
||||
[G.ID_PROJECTDIR] = "",
|
||||
-- Help menu
|
||||
[G.ID_ABOUT] = "F1",
|
||||
-- Watch window menu items
|
||||
[G.ID_ADDWATCH] = "Ins",
|
||||
[G.ID_EDITWATCH] = "F2",
|
||||
[G.ID_DELETEWATCH] = "Del",
|
||||
-- Editor popup menu items
|
||||
[G.ID_QUICKADDWATCH] = "",
|
||||
[G.ID_QUICKEVAL] = "",
|
||||
}
|
||||
|
||||
for id, key in G.pairs(xcode) do keymap[id] = key end
|
||||
@@ -40,12 +40,10 @@ return {
|
||||
return
|
||||
end
|
||||
|
||||
-- can we really do debugging? do if asked and if not on mac OSX where it's not supported
|
||||
local debug = rundebug and not mac
|
||||
if rundebug then
|
||||
-- start running the application right away
|
||||
DebuggerAttachDefault({runstart=true, startwith = file,
|
||||
redirect = debug and "c", noshell = mac or nil, noeval = mac or nil})
|
||||
DebuggerAttachDefault({startwith = file, redirect = mac and "r" or "c",
|
||||
runstart = ide.config.debugger.runonstart ~= false})
|
||||
|
||||
-- copy mobdebug.lua to Resources/ folder on Win and to the project folder on OSX
|
||||
-- as copying it to Resources/ folder seems to break the signature of the app.
|
||||
@@ -59,7 +57,8 @@ return {
|
||||
end
|
||||
end
|
||||
|
||||
local cmd = ('"%s" %s"%s"'):format(corona, debug and "-debug " or "", file)
|
||||
local debugopt = mac and "-debug 1 -project " or "-debug "
|
||||
local cmd = ('"%s" %s"%s"'):format(corona, rundebug and debugopt or "", file)
|
||||
-- CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
|
||||
return CommandLineRun(cmd,self:fworkdir(wfilename),true,false,nil,nil,
|
||||
function() ide.debugger.pid = nil end)
|
||||
@@ -72,4 +71,5 @@ return {
|
||||
end,
|
||||
hasdebugger = true,
|
||||
fattachdebug = function(self) DebuggerAttachDefault() end,
|
||||
scratchextloop = true,
|
||||
}
|
||||
|
||||
@@ -4,6 +4,22 @@ local gideros
|
||||
local win = ide.osname == "Windows"
|
||||
local mac = ide.osname == "Macintosh"
|
||||
|
||||
local function isValidPid(bid, cmd)
|
||||
if not bid or bid == -1 or bid == 0 then
|
||||
DisplayOutputLn(("Program unable to run as '%s'."):format(cmd))
|
||||
return
|
||||
end
|
||||
return bid
|
||||
end
|
||||
|
||||
local function waitToComplete(bid)
|
||||
while wx.wxProcess.Exists(bid) do
|
||||
wx.wxSafeYield()
|
||||
wx.wxWakeUpIdle()
|
||||
wx.wxMilliSleep(100)
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
name = "Gideros",
|
||||
description = "Gideros mobile platform",
|
||||
@@ -26,13 +42,13 @@ return {
|
||||
table.insert(paths, p)
|
||||
end
|
||||
if not gideros then
|
||||
DisplayOutput("Can't find gideros executable in any of the folders in PATH: "
|
||||
..table.concat(paths, ", ").."\n")
|
||||
DisplayOutputLn("Can't find gideros executable in any of the folders in PATH: "
|
||||
..table.concat(paths, ", "))
|
||||
return
|
||||
end
|
||||
end
|
||||
if gideros and not wx.wxFileName(gideros):FileExists() then
|
||||
DisplayOutput("Can't find the specified gideros executable '"..gideros.."'.\n")
|
||||
DisplayOutputLn("Can't find the specified gideros executable '"..gideros.."'.")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -43,32 +59,44 @@ return {
|
||||
local giderospath = giderostools:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
local gdrbridge = GetFullPathIfExists(giderospath, win and 'gdrbridge.exe' or 'gdrbridge')
|
||||
if not gdrbridge then
|
||||
DisplayOutput("Can't find gideros bridge executable in '"..giderospath.."'.\n")
|
||||
DisplayOutputLn("Can't find gideros bridge executable in '"..giderospath.."'.")
|
||||
return
|
||||
end
|
||||
|
||||
-- find *.gproj file in the project directory
|
||||
local file
|
||||
for _, proj in ipairs(FileSysGet(self:fworkdir(wfilename).."/*.gproj", wx.wxFILE)) do
|
||||
for _, proj in ipairs(FileSysGetRecursive(self:fworkdir(wfilename), false, "*.gproj")) do
|
||||
if file then
|
||||
DisplayOutput("Found multiple .gproj files in the project directory; ignored '"..proj.."'\n")
|
||||
DisplayOutputLn("Found multiple .gproj files in the project directory; ignored '"..proj.."'.")
|
||||
end
|
||||
file = proj
|
||||
file = file or proj
|
||||
end
|
||||
if not file then
|
||||
DisplayOutput("Can't find gideros project file in the project directory.\n")
|
||||
DisplayOutputLn("Can't find gideros project file in the project directory.")
|
||||
return
|
||||
end
|
||||
|
||||
if rundebug then DebuggerAttachDefault({redirect = "c"}) end
|
||||
if rundebug then DebuggerAttachDefault(
|
||||
{redirect = "c", runstart = ide.config.debugger.runonstart ~= false}) end
|
||||
|
||||
local cmd = ('"%s"'):format(gideros)
|
||||
-- CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
|
||||
local pid = CommandLineRun(cmd,self:fworkdir(wfilename),not mac,true,nil,nil,
|
||||
function() ide.debugger.pid = nil end)
|
||||
local pid
|
||||
local remote = ide.config.gideros and ide.config.gideros.remote
|
||||
if remote then
|
||||
local cmd = ('"%s" %s "%s"'):format(gdrbridge, 'setip', remote)
|
||||
DisplayOutputLn(("Configuring remote player at %s."):format(remote))
|
||||
local bid = wx.wxExecute(cmd, wx.wxEXEC_ASYNC)
|
||||
if not isValidPid(bid, cmd) then return end
|
||||
waitToComplete(bid) -- wait for a bit to give Gideros chance to connect
|
||||
else
|
||||
local cmd = ('"%s"'):format(gideros)
|
||||
-- CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
|
||||
pid = CommandLineRun(cmd,self:fworkdir(wfilename),not mac,true,nil,nil,
|
||||
function() ide.debugger.pid = nil end)
|
||||
if not pid then return end
|
||||
end
|
||||
|
||||
do
|
||||
DisplayOutput("Starting the player and waiting for the bridge to connect at '"..gdrbridge.."'.\n")
|
||||
DisplayOutputLn("Starting the player and waiting for the bridge to connect at '"..gdrbridge.."'.")
|
||||
local cmd = ('"%s" %s'):format(gdrbridge, 'isconnected')
|
||||
local attempts, connected = 12
|
||||
for _ = 1, attempts do
|
||||
@@ -76,10 +104,7 @@ return {
|
||||
proc:Redirect()
|
||||
proc:Connect(wx.wxEVT_END_PROCESS, function(event) proc = nil end)
|
||||
local bid = wx.wxExecute(cmd, wx.wxEXEC_ASYNC + wx.wxEXEC_MAKE_GROUP_LEADER, proc)
|
||||
if not bid or bid == -1 or bid == 0 then
|
||||
DisplayOutput(("Program unable to run as '%s'\n"):format(cmd))
|
||||
return
|
||||
end
|
||||
if not isValidPid(bid, cmd) then return end
|
||||
|
||||
local streamin = proc:GetInputStream()
|
||||
for _ = 1, 20 do
|
||||
@@ -94,21 +119,21 @@ return {
|
||||
if connected then break end
|
||||
if connected == nil and proc then
|
||||
wx.wxProcess.Kill(bid, wx.wxSIGKILL, wx.wxKILL_CHILDREN)
|
||||
wx.wxProcess.Kill(pid, wx.wxSIGKILL, wx.wxKILL_CHILDREN)
|
||||
DisplayOutput("Couldn't connect to the player. Try again or check starting the player and the bridge manually.\n")
|
||||
if not remote then wx.wxProcess.Kill(pid, wx.wxSIGKILL, wx.wxKILL_CHILDREN) end
|
||||
DisplayOutputLn("Couldn't connect to the player. Try again or check starting the player and the bridge manually.")
|
||||
return
|
||||
end
|
||||
end
|
||||
if not connected then
|
||||
wx.wxProcess.Kill(pid, wx.wxSIGKILL, wx.wxKILL_CHILDREN)
|
||||
DisplayOutput("Couldn't connect after "..attempts.." attempts. Try again or check starting the player manually.\n")
|
||||
if not remote then wx.wxProcess.Kill(pid, wx.wxSIGKILL, wx.wxKILL_CHILDREN) end
|
||||
DisplayOutputLn("Couldn't connect after "..attempts.." attempts. Try again or check starting the player manually.")
|
||||
return
|
||||
end
|
||||
|
||||
DisplayOutput("Starting project file '"..file.."'.\n")
|
||||
|
||||
cmd = ('"%s" %s "%s"'):format(gdrbridge, 'play', file)
|
||||
wx.wxExecute(cmd, wx.wxEXEC_ASYNC)
|
||||
local cmd = ('"%s" %s "%s"'):format(gdrbridge, 'play', file)
|
||||
DisplayOutputLn(("Starting project file '%s'."):format(file))
|
||||
local bid = wx.wxExecute(cmd, wx.wxEXEC_ASYNC)
|
||||
if not isValidPid(bid, cmd) then return end
|
||||
end
|
||||
return pid
|
||||
end,
|
||||
|
||||
@@ -51,7 +51,9 @@ return {
|
||||
end
|
||||
end
|
||||
|
||||
if rundebug then DebuggerAttachDefault() end
|
||||
if rundebug then
|
||||
DebuggerAttachDefault({runstart = ide.config.debugger.runonstart == true})
|
||||
end
|
||||
|
||||
local cmd = ('"%s" "%s"'):format(gslshell, wfilename:GetFullPath())
|
||||
-- CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
|
||||
|
||||
@@ -38,7 +38,9 @@ return {
|
||||
return
|
||||
end
|
||||
|
||||
if rundebug then DebuggerAttachDefault() end
|
||||
if rundebug then
|
||||
DebuggerAttachDefault({runstart = ide.config.debugger.runonstart == true})
|
||||
end
|
||||
|
||||
local cmd = ('"%s" "%s"%s'):format(love2d,
|
||||
self:fworkdir(wfilename), rundebug and ' -debug' or '')
|
||||
|
||||
@@ -5,7 +5,7 @@ local function exePath()
|
||||
local macExe = mainpath..'bin/lua.app/Contents/MacOS/lua'
|
||||
return ide.config.path.lua or
|
||||
(ide.osname == "Windows" and mainpath..[[bin\lua.exe]]
|
||||
or (ide.osname == "Unix" and [[lua]]) -- using installed lua
|
||||
or (ide.osname == "Unix" and mainpath..([[bin/linux/%s/lua]]):format(ide.osarch))
|
||||
or (wx.wxFileExists(macExe) and macExe or mainpath..[[bin/lua]]))
|
||||
end
|
||||
|
||||
@@ -16,10 +16,8 @@ return {
|
||||
frun = function(self,wfilename,rundebug)
|
||||
exe = exe or exePath()
|
||||
local filepath = wfilename:GetFullPath()
|
||||
local script
|
||||
if rundebug then
|
||||
DebuggerAttachDefault()
|
||||
script = rundebug
|
||||
DebuggerAttachDefault({runstart = ide.config.debugger.runonstart == true})
|
||||
else
|
||||
-- if running on Windows and can't open the file, this may mean that
|
||||
-- the file path includes unicode characters that need special handling
|
||||
@@ -30,11 +28,11 @@ return {
|
||||
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..'"'
|
||||
local code = rundebug
|
||||
and ([[-e "io.stdout:setvbuf('no'); %s"]]):format(rundebug)
|
||||
or ([[-e "io.stdout:setvbuf('no')" "%s"]]):format(filepath)
|
||||
local cmd = '"'..exe..'" '..code
|
||||
-- CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
|
||||
return CommandLineRun(cmd,self:fworkdir(wfilename),true,false,nil,nil,
|
||||
function() ide.debugger.pid = nil end)
|
||||
|
||||
117
interpreters/marmalade.lua
Normal file
117
interpreters/marmalade.lua
Normal file
@@ -0,0 +1,117 @@
|
||||
-- Copyright 2011-12 Paul Kulchenko, ZeroBrane LLC
|
||||
|
||||
local quick
|
||||
local win = ide.osname == "Windows"
|
||||
local mac = ide.osname == "Macintosh"
|
||||
local exe = win and [[win32\s3e_simulator_debug.exe]] or [[loader/osx/s3e_simulator_debug]]
|
||||
local s3e = os.getenv("S3E_DIR")
|
||||
|
||||
return {
|
||||
name = "Marmalade Quick",
|
||||
description = "Marmalade Quick mobile framework",
|
||||
api = {"baselib", "marmalade"},
|
||||
frun = function(self,wfilename,rundebug)
|
||||
quick = quick or ide.config.path.quick or (s3e and GetFullPathIfExists(s3e, exe))
|
||||
if not quick then
|
||||
local sep = win and ';' or ':'
|
||||
local path =
|
||||
win and ([[C:\Marmalade]]..sep..[[D:\Marmalade]]..sep..
|
||||
[[C:\Program Files\Marmalade]]..sep..[[D:\Program Files\Marmalade]]..sep..
|
||||
[[C:\Program Files (x86)\Marmalade]]..sep..[[D:\Program Files (x86)\Marmalade]]..sep)
|
||||
or mac and ([[/Developer/Marmalade]]..sep)
|
||||
or ''
|
||||
-- Marmalade can be installed in a folder with version number or without
|
||||
-- so it may be c:\Marmalade\s3e\... or c:\Marmalade\6.2\s3e\...
|
||||
local candidates, paths = {}, {}
|
||||
for p in path:gmatch("[^"..sep.."]+") do
|
||||
table.insert(paths, p)
|
||||
for _, candidate in ipairs(FileSysGetRecursive(p, false, "*")) do
|
||||
if GetFullPathIfExists(candidate, exe) then table.insert(candidates, candidate) end
|
||||
if GetFullPathIfExists(candidate.."/s3e", exe) then table.insert(candidates, candidate.."/s3e") end
|
||||
end
|
||||
end
|
||||
-- multiple candidates may be present, so sort and use the latest.
|
||||
-- only happens if multiple versions are installed and S3E_DIR is not set.
|
||||
table.sort(candidates)
|
||||
if #candidates > 0 then
|
||||
s3e = candidates[#candidates]
|
||||
quick = GetFullPathIfExists(s3e, exe) -- guaranteed to exist
|
||||
else
|
||||
DisplayOutputLn("Can't find Marmalade installation in any of these folders (and S3E_DIR environmental variable is not set): "
|
||||
..table.concat(paths, ", "))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local projdir = self:fworkdir(wfilename)
|
||||
local file = GetFullPathIfExists(projdir, 'main.lua')
|
||||
if not file then
|
||||
DisplayOutputLn("Can't find 'main.lua' file in the current project folder.")
|
||||
return
|
||||
end
|
||||
|
||||
-- check for *.mkb file; it can be in the same or in the parent folder
|
||||
local mproj, mfile = MergeFullPath(projdir, "./")
|
||||
for _, file in ipairs(FileSysGetRecursive(mproj, false, "*.mkb")) do mfile = file end
|
||||
if not mfile then
|
||||
mproj, mfile = MergeFullPath(projdir, "../")
|
||||
for _, file in ipairs(FileSysGetRecursive(mproj, false, "*.mkb")) do mfile = file end
|
||||
end
|
||||
if not mfile then
|
||||
DisplayOutputLn(("Can't find '%s' project file."):format(mproj))
|
||||
return
|
||||
end
|
||||
|
||||
local mkb = FileRead(mfile)
|
||||
local datadir = mkb:match("options%s*%{[^%}]*s3e%-data%-dir%s*=%s*(.-)%s*[\r\n%}]")
|
||||
datadir = datadir and datadir:gsub("^['\"]", ""):gsub("['\"][\r\n]*$", "")
|
||||
local icf1, icf2 = mkb:match("options%s*%{[^%}]*app%-icf%s*=%s*(.-)%s*[\r\n%}]")
|
||||
icf1 = icf1 and icf1:gsub("^['\"]", ""):gsub("['\"][\r\n]*$", "")
|
||||
if icf1 and icf1:find(",") then
|
||||
icf1, icf2 = icf1:match("(.+),(.*)")
|
||||
end
|
||||
|
||||
datadir = datadir and (wx.wxIsAbsolutePath(datadir) and datadir or MergeFullPath(mproj, datadir))
|
||||
icf1 = icf1 and (wx.wxIsAbsolutePath(icf1) and icf1 or MergeFullPath(mproj, icf1))
|
||||
icf2 = icf2 and (wx.wxIsAbsolutePath(icf2) and icf2 or MergeFullPath(mproj, icf2))
|
||||
|
||||
if rundebug then
|
||||
-- start running the application right away
|
||||
DebuggerAttachDefault({redirect = mac and "r" or "c", basedir = datadir,
|
||||
runstart = ide.config.debugger.runonstart ~= false})
|
||||
|
||||
-- copy mobdebug.lua to the configured datadir or project folder
|
||||
local mdbc = MergeFullPath(datadir or projdir, "mobdebug.lua")
|
||||
local mdbl = MergeFullPath(GetPathWithSep(ide.editorFilename), "lualibs/mobdebug/mobdebug.lua")
|
||||
if not wx.wxFileExists(mdbc)
|
||||
or GetFileModTime(mdbc):GetTicks() < GetFileModTime(mdbl):GetTicks() then
|
||||
FileCopy(mdbl, mdbc)
|
||||
DisplayOutputLn("Copied ZeroBrane Studio debugger ('mobdebug.lua') to the project folder.")
|
||||
end
|
||||
end
|
||||
|
||||
local dll = GetFullPathIfExists(s3e, "../quick/target/quick_prebuilt_d.s86")
|
||||
or MergeFullPath(s3e, ("../quick/target/%s/quick_prebuilt_d.s86"):format(mac and 'osx' or 'win'))
|
||||
local options = table.concat({
|
||||
([[--dll="%s"]]):format(dll),
|
||||
(datadir and ([[--data="%s"]]):format(datadir) or ''),
|
||||
-- Quick doesn't handle correctly spaces in quoted parameters on OSX,
|
||||
-- so replace those with escaped spaces; still quote on Windows
|
||||
(icf1 and ([[--app-icf1=%s]]):format(mac and icf1:gsub(" ", "\\ ") or '"'..icf1..'"') or ''),
|
||||
(icf2 and ([[--app-icf2=%s]]):format(mac and icf2:gsub(" ", "\\ ") or '"'..icf2..'"') or nil),
|
||||
}, " ")
|
||||
|
||||
local cmd = ('"%s" %s'):format(quick, options)
|
||||
-- CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
|
||||
return CommandLineRun(cmd,GetPathWithSep(projdir),true,true,nil,nil,
|
||||
function() ide.debugger.pid = nil end)
|
||||
end,
|
||||
fprojdir = function(self,wfilename)
|
||||
return wfilename:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end,
|
||||
fworkdir = function(self,wfilename)
|
||||
return ide.config.path.projectdir or wfilename:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end,
|
||||
hasdebugger = true,
|
||||
fattachdebug = function(self) DebuggerAttachDefault() end,
|
||||
}
|
||||
@@ -46,7 +46,8 @@ return {
|
||||
|
||||
if rundebug then
|
||||
-- start running the application right away
|
||||
DebuggerAttachDefault({runstart=true, startwith = file})
|
||||
DebuggerAttachDefault({startwith = file,
|
||||
runstart = ide.config.debugger.runonstart ~= false})
|
||||
local code = (
|
||||
[[xpcall(function()
|
||||
io.stdout:setvbuf('no')
|
||||
@@ -63,6 +64,14 @@ return {
|
||||
end
|
||||
f:write(code)
|
||||
f:close()
|
||||
|
||||
-- add mobdebug as the first path to LUA_PATH to provide a workaround
|
||||
-- for a MOAI issue: https://github.com/pkulchenko/ZeroBraneStudio/issues/96
|
||||
local mdb = MergeFullPath(GetPathWithSep(ide.editorFilename), "lualibs/mobdebug/?.lua")
|
||||
local _, path = wx.wxGetEnv("LUA_PATH")
|
||||
if path and path:find(mdb, 1, true) ~= 1 then
|
||||
wx.wxSetEnv("LUA_PATH", mdb..";"..path)
|
||||
end
|
||||
end
|
||||
|
||||
file = file or wfilename:GetFullPath()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
-- an abstract syntax tree (AST)
|
||||
local file = debug.getinfo(1, "S").source
|
||||
if string.find(file, "@") == 1 then file = string.sub(file, 2) end
|
||||
package.path = package.path .. ';' .. string.gsub(file, "metalua%.lua$", "?.lua")
|
||||
package.path = string.gsub(file, "metalua%.lua$", "?.lua") .. ';' .. package.path
|
||||
|
||||
-- these modules are sufficient to build an AST from a source file/string
|
||||
require "lexer"
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
--
|
||||
-- MobDebug 0.5084
|
||||
-- Copyright 2011-12 Paul Kulchenko
|
||||
-- MobDebug 0.526
|
||||
-- Copyright 2011-13 Paul Kulchenko
|
||||
-- Based on RemDebug 1.0 Copyright Kepler Project 2005
|
||||
--
|
||||
|
||||
local mobdebug = {
|
||||
_NAME = "mobdebug",
|
||||
_VERSION = 0.5084,
|
||||
_VERSION = 0.526,
|
||||
_COPYRIGHT = "Paul Kulchenko",
|
||||
_DESCRIPTION = "Mobile Remote Debugger for the Lua programming language",
|
||||
port = os and os.getenv and os.getenv("MOBDEBUG_PORT") or 8172,
|
||||
checkcount = 200,
|
||||
yieldtimeout = 0.02,
|
||||
}
|
||||
|
||||
local coroutine = coroutine
|
||||
local error = error
|
||||
local getfenv = getfenv
|
||||
local loadstring = loadstring
|
||||
local setfenv = setfenv
|
||||
local loadstring = loadstring or load -- "load" replaced "loadstring" in Lua 5.2
|
||||
local io = io
|
||||
local os = os
|
||||
local pairs = pairs
|
||||
@@ -34,151 +36,34 @@ local tonumber = tonumber
|
||||
-- the debug loop as 'wx' can be loaded at any time during debugging.
|
||||
local genv = _G or _ENV
|
||||
local jit = rawget(genv, "jit")
|
||||
local mosync = rawget(genv, "mosync")
|
||||
local MOAICoroutine = rawget(genv, "MOAICoroutine")
|
||||
|
||||
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
|
||||
|
||||
-- check for OS and convert file names to lower case on windows
|
||||
-- (its file system is case insensitive, but case preserving), as setting a
|
||||
-- breakpoint on x:\Foo.lua will not work if the file was loaded as X:\foo.lua.
|
||||
local iswindows = os.getenv('WINDIR')
|
||||
-- OSX and Windows behave the same way (case insensitive, but case preserving)
|
||||
local iscasepreserving = os and os.getenv and (os.getenv('WINDIR')
|
||||
or (os.getenv('OS') or ''):match('[Ww]indows')
|
||||
or pcall(require, "winapi")
|
||||
|
||||
-- this is a socket class that implements maConnect interface
|
||||
local function socketMobileLua()
|
||||
local self = {}
|
||||
self.select = function(readfrom) -- writeto and timeout parameters are ignored
|
||||
local canread = {}
|
||||
for _,s in ipairs(readfrom) do
|
||||
if s:receive(0) then canread[s] = true end
|
||||
end
|
||||
return canread
|
||||
end
|
||||
self.connect = coroutine.wrap(function(host, port)
|
||||
while true do
|
||||
local connection = mosync.maConnect("socket://" .. host .. ":" .. port)
|
||||
|
||||
if connection > 0 then
|
||||
local event = mosync.SysEventCreate()
|
||||
while true do
|
||||
mosync.maWait(0)
|
||||
mosync.maGetEvent(event)
|
||||
local eventType = mosync.SysEventGetType(event)
|
||||
if (mosync.EVENT_TYPE_CONN == eventType and
|
||||
mosync.SysEventGetConnHandle(event) == connection and
|
||||
mosync.SysEventGetConnOpType(event) == mosync.CONNOP_CONNECT) then
|
||||
-- result > 0 ? success : error
|
||||
if not (mosync.SysEventGetConnResult(event) > 0) then connection = nil end
|
||||
break
|
||||
elseif mosync.EventMonitor and mosync.EventMonitor.HandleEvent then
|
||||
mosync.EventMonitor:HandleEvent(event)
|
||||
end
|
||||
end
|
||||
mosync.SysFree(event)
|
||||
end
|
||||
|
||||
host, port = coroutine.yield(connection and (function ()
|
||||
local self = {}
|
||||
local outBuffer = mosync.SysAlloc(1000)
|
||||
local inBuffer = mosync.SysAlloc(1000)
|
||||
local event = mosync.SysEventCreate()
|
||||
local recvBuffer = ""
|
||||
function stringToBuffer(s, buffer)
|
||||
local i = 0
|
||||
for c in s:gmatch(".") do
|
||||
i = i + 1
|
||||
local b = s:byte(i)
|
||||
mosync.SysBufferSetByte(buffer, i - 1, b)
|
||||
end
|
||||
return i
|
||||
end
|
||||
function bufferToString(buffer, len)
|
||||
local s = ""
|
||||
for i = 0, len - 1 do
|
||||
local c = mosync.SysBufferGetByte(buffer, i)
|
||||
s = s .. string.char(c)
|
||||
end
|
||||
return s
|
||||
end
|
||||
self.send = coroutine.wrap(function(self, msg)
|
||||
while true do
|
||||
local numberOfBytes = stringToBuffer(msg, outBuffer)
|
||||
mosync.maConnWrite(connection, outBuffer, numberOfBytes)
|
||||
while true do
|
||||
mosync.maWait(0)
|
||||
mosync.maGetEvent(event)
|
||||
local eventType = mosync.SysEventGetType(event)
|
||||
if (mosync.EVENT_TYPE_CONN == eventType and
|
||||
mosync.SysEventGetConnHandle(event) == connection and
|
||||
mosync.SysEventGetConnOpType(event) == mosync.CONNOP_WRITE) then
|
||||
break
|
||||
elseif mosync.EventMonitor and mosync.EventMonitor.HandleEvent then
|
||||
mosync.EventMonitor:HandleEvent(event)
|
||||
end
|
||||
end
|
||||
self, msg = coroutine.yield()
|
||||
end
|
||||
end)
|
||||
self.receive = coroutine.wrap(function(self, len)
|
||||
while true do
|
||||
local line = recvBuffer
|
||||
while (len and string.len(line) < len) -- either we need len bytes
|
||||
or (not len and not line:find("\n")) -- or one line (if no len specified)
|
||||
or (len == 0) do -- only check for new data (select-like)
|
||||
mosync.maConnRead(connection, inBuffer, 1000)
|
||||
while true do
|
||||
if len ~= 0 then mosync.maWait(0) end
|
||||
mosync.maGetEvent(event)
|
||||
local eventType = mosync.SysEventGetType(event)
|
||||
if (mosync.EVENT_TYPE_CONN == eventType and
|
||||
mosync.SysEventGetConnHandle(event) == connection and
|
||||
mosync.SysEventGetConnOpType(event) == mosync.CONNOP_READ) then
|
||||
local result = mosync.SysEventGetConnResult(event)
|
||||
if result > 0 then line = line .. bufferToString(inBuffer, result) end
|
||||
if len == 0 then self, len = coroutine.yield("") end
|
||||
break -- got the event we wanted; now check if we have all we need
|
||||
elseif len == 0 then
|
||||
self, len = coroutine.yield(nil)
|
||||
elseif mosync.EventMonitor and mosync.EventMonitor.HandleEvent then
|
||||
mosync.EventMonitor:HandleEvent(event)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not len then
|
||||
len = string.find(line, "\n") or string.len(line)
|
||||
end
|
||||
|
||||
recvBuffer = string.sub(line, len+1)
|
||||
line = string.sub(line, 1, len)
|
||||
|
||||
self, len = coroutine.yield(line)
|
||||
end
|
||||
end)
|
||||
self.close = coroutine.wrap(function(self)
|
||||
while true do
|
||||
mosync.SysFree(inBuffer)
|
||||
mosync.SysFree(outBuffer)
|
||||
mosync.SysFree(event)
|
||||
mosync.maConnClose(connection)
|
||||
coroutine.yield(self)
|
||||
end
|
||||
end)
|
||||
return self
|
||||
end)())
|
||||
end
|
||||
end)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-- overwrite RunEventLoop in MobileLua as it conflicts with the event
|
||||
-- loop that needs to run to process debugger events (socket read/write).
|
||||
-- event loop functionality is implemented by calling HandleEvent
|
||||
-- while waiting for debugger events.
|
||||
if mosync and mosync.EventMonitor then
|
||||
mosync.EventMonitor.RunEventLoop = function(self) end
|
||||
end
|
||||
or os.getenv('DYLD_LIBRARY_PATH'))
|
||||
or not io.open("/proc")
|
||||
|
||||
-- turn jit off based on Mike Pall's comment in this discussion:
|
||||
-- http://www.freelists.org/post/luajit/Debug-hooks-and-JIT,2
|
||||
@@ -186,10 +71,11 @@ end
|
||||
-- reliable hook calls at any later point in time."
|
||||
if jit and jit.off then jit.off() end
|
||||
|
||||
local socket = mosync and socketMobileLua() or (require "socket")
|
||||
|
||||
local socket = require "socket"
|
||||
local debug = require "debug"
|
||||
local coro_debugger
|
||||
local coro_debugee
|
||||
local coroutines = {}; setmetatable(coroutines, {__mode = "k"}) -- "weak" keys
|
||||
local events = { BREAK = 1, WATCH = 2, RESTART = 3, STACK = 4 }
|
||||
local breakpoints = {}
|
||||
local watches = {}
|
||||
@@ -198,14 +84,13 @@ local lastfile
|
||||
local watchescnt = 0
|
||||
local abort -- default value is nil; this is used in start/loop distinction
|
||||
local seen_hook = false
|
||||
local skip
|
||||
local skipcount = 0
|
||||
local checkcount = 0
|
||||
local step_into = false
|
||||
local step_over = false
|
||||
local step_level = 0
|
||||
local stack_level = 0
|
||||
local server
|
||||
local rset
|
||||
local buf
|
||||
local outputs = {}
|
||||
local iobase = {print = print}
|
||||
local basedir = ""
|
||||
@@ -218,10 +103,10 @@ end
|
||||
local function q(s) return s:gsub('([%(%)%.%%%+%-%*%?%[%^%$%]])','%%%1') end
|
||||
|
||||
local serpent = (function() ---- include Serpent module for serialization
|
||||
local n, v = "serpent", 0.20 -- (C) 2012 Paul Kulchenko; MIT License
|
||||
local c, d = "Paul Kulchenko", "Serializer and pretty printer of Lua data types"
|
||||
local n, v = "serpent", 0.23 -- (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}
|
||||
local badtype = {thread = true, userdata = true, cdata = true}
|
||||
local keyword, globals, G = {}, {}, (_G or _ENV)
|
||||
for _,k in ipairs({'and', 'break', 'do', 'else', 'elseif', 'end', 'false',
|
||||
'for', 'function', 'goto', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',
|
||||
@@ -234,9 +119,10 @@ local function s(t, opts)
|
||||
local name, indent, fatal = opts.name, opts.indent, opts.fatal
|
||||
local sparse, custom, huge = opts.sparse, opts.custom, not opts.nohuge
|
||||
local space, maxl = (opts.compact and '' or ' '), (opts.maxlevel or math.huge)
|
||||
local comm = opts.comment and (tonumber(opts.comment) or math.huge)
|
||||
local seen, sref, syms, symn = {}, {}, {}, 0
|
||||
local function gensym(val) return (tostring(val):gsub("[^%w]",""):gsub("(%d%w+)",
|
||||
local iname, comm = '_'..(name or ''), opts.comment and (tonumber(opts.comment) or math.huge)
|
||||
local seen, sref, syms, symn = {}, {'local '..iname..'={}'}, {}, 0
|
||||
local function gensym(val) return '_'..(tostring(tostring(val)):gsub("[^%w]",""):gsub("(%d%w+)",
|
||||
-- tostring(val) is needed because __tostring may return a non-string value
|
||||
function(s) if not syms[s] then symn = symn+1; syms[s] = symn end return syms[s] end)) end
|
||||
local function safestr(s) return type(s) == "number" and (huge and snum[tostring(s)] or s)
|
||||
or type(s) ~= "string" and tostring(s) -- escape NEWLINE/010 and EOF/026
|
||||
@@ -249,49 +135,45 @@ local function s(t, opts)
|
||||
local plain = type(n) == "string" and n:match("^[%l%u_][%w_]*$") and not keyword[n]
|
||||
local safe = plain and n or '['..safestr(n)..']'
|
||||
return (path or '')..(plain and path and '.' or '')..safe, safe end
|
||||
local alphanumsort = type(opts.sortkeys) == 'function' and opts.sortkeys or function(o, n)
|
||||
local alphanumsort = type(opts.sortkeys) == 'function' and opts.sortkeys or function(k, o, n) -- k=keys, o=originaltable, n=padding
|
||||
local maxn, to = tonumber(n) or 12, {number = 'a', string = 'b'}
|
||||
local function padnum(d) return ("%0"..maxn.."d"):format(d) end
|
||||
table.sort(o, function(a,b)
|
||||
return (o[a] and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))
|
||||
< (o[b] and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end
|
||||
table.sort(k, function(a,b)
|
||||
-- sort numeric keys first: k[key] is non-nil for numeric keys
|
||||
return (k[a] and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))
|
||||
< (k[b] and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end
|
||||
local function val2str(t, name, indent, insref, path, plainindex, level)
|
||||
local ttype, level = type(t), (level or 0)
|
||||
local ttype, level, mt = type(t), (level or 0), getmetatable(t)
|
||||
local spath, sname = safename(path, name)
|
||||
local tag = plainindex and
|
||||
((type(name) == "number") and '' or name..space..'='..space) or
|
||||
(name ~= nil and sname..space..'='..space or '')
|
||||
if seen[t] then -- if already seen and in sref processing,
|
||||
if insref then return tag..seen[t] end -- then emit right away
|
||||
if seen[t] then -- already seen this element
|
||||
table.insert(sref, spath..space..'='..space..seen[t])
|
||||
return tag..'nil'..comment('ref', level)
|
||||
elseif badtype[ttype] then
|
||||
seen[t] = spath
|
||||
return tag..globerr(t, level)
|
||||
elseif ttype == 'function' then
|
||||
return tag..'nil'..comment('ref', level) end
|
||||
if mt and (mt.__serialize or mt.__tostring) then -- knows how to serialize itself
|
||||
seen[t] = insref or spath
|
||||
local ok, res = pcall(string.dump, t)
|
||||
local func = ok and ((opts.nocode and "function() --[[..skipped..]] end" or
|
||||
"loadstring("..safestr(res)..",'@serialized')")..comment(t, level))
|
||||
return tag..(func or globerr(t, level))
|
||||
elseif ttype == "table" then
|
||||
if mt.__serialize then t = mt.__serialize(t) else t = tostring(t) end
|
||||
ttype = type(t) end -- new value falls through to be serialized
|
||||
if ttype == "table" then
|
||||
if level >= maxl then return tag..'{}'..comment('max', level) end
|
||||
seen[t] = insref or spath -- set path to use as reference
|
||||
if getmetatable(t) and getmetatable(t).__tostring
|
||||
then return tag..safestr(tostring(t))..comment("meta", level) end
|
||||
seen[t] = insref or spath
|
||||
if next(t) == nil then return tag..'{}'..comment(t, level) end -- table empty
|
||||
local maxn, o, out = #t, {}, {}
|
||||
for key = 1, maxn do table.insert(o, key) end
|
||||
for key in pairs(t) do if not o[key] then table.insert(o, key) end end
|
||||
if opts.sortkeys then alphanumsort(o, opts.sortkeys) 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
|
||||
if opts.ignore and opts.ignore[value] -- skip ignored values; do nothing
|
||||
if opts.valignore and opts.valignore[value] -- skip ignored values; do nothing
|
||||
or opts.keyallow and not opts.keyallow[key]
|
||||
or opts.valtypeignore and opts.valtypeignore[type(value)] -- skipping ignored value types
|
||||
or sparse and value == nil then -- skipping nils; do nothing
|
||||
elseif ktype == 'table' or ktype == 'function' or badtype[ktype] then
|
||||
if not seen[key] and not globals[key] then
|
||||
table.insert(sref, 'placeholder')
|
||||
sref[#sref] = 'local '..val2str(key,gensym(key),indent,gensym(key)) end
|
||||
local sname = safename(iname, gensym(key)) -- iname is table for local variables
|
||||
sref[#sref] = val2str(key,sname,indent,sname,iname,true) end
|
||||
table.insert(sref, 'placeholder')
|
||||
local path = seen[t]..'['..(seen[key] or globals[key] or gensym(key))..']'
|
||||
sref[#sref] = path..space..'='..space..(seen[value] or val2str(value,nil,indent,path))
|
||||
@@ -304,12 +186,22 @@ local function s(t, opts)
|
||||
local body = table.concat(out, ','..(indent and '\n'..prefix..indent or space))
|
||||
local tail = indent and "\n"..prefix..'}' or '}'
|
||||
return (custom and custom(tag,head,body,tail) or tag..head..body..tail)..comment(t, level)
|
||||
elseif badtype[ttype] then
|
||||
seen[t] = insref or spath
|
||||
return tag..globerr(t, level)
|
||||
elseif ttype == 'function' then
|
||||
seen[t] = insref or spath
|
||||
local ok, res = pcall(string.dump, t)
|
||||
local func = ok and ((opts.nocode and "function() --[[..skipped..]] end" or
|
||||
"loadstring("..safestr(res)..",'@serialized')")..comment(t, level))
|
||||
return tag..(func or globerr(t, level))
|
||||
else return tag..safestr(t) end -- handle all other types
|
||||
end
|
||||
local sepr = indent and "\n" or ";"..space
|
||||
local body = val2str(t, name, indent) -- this call also populates sref
|
||||
local tail = #sref>0 and table.concat(sref, sepr)..sepr or ''
|
||||
return not name and body or "do local "..body..sepr..tail.."return "..name..sepr.."end"
|
||||
local tail = #sref>1 and table.concat(sref, sepr)..sepr or ''
|
||||
local warn = opts.comment and #sref>1 and space.."--[[incomplete output with shared/self-references skipped]]" or ''
|
||||
return not name and body..warn or "do local "..body..sepr..tail.."return "..name..sepr.."end"
|
||||
end
|
||||
|
||||
local function merge(a, b) if b then for k,v in pairs(b) do a[k] = v end end; return a; end
|
||||
@@ -319,6 +211,17 @@ return { _NAME = n, _COPYRIGHT = c, _DESCRIPTION = d, _VERSION = v, serialize =
|
||||
block = function(a, opts) return s(a, merge({indent = ' ', sortkeys = true, comment = true}, opts)) end }
|
||||
end)() ---- end of Serpent module
|
||||
|
||||
local function removebasedir(path, basedir)
|
||||
if iscasepreserving then
|
||||
-- check if the lowercased path matches the basedir
|
||||
-- if so, return substring of the original path (to not lowercase it)
|
||||
return path:lower():find('^'..q(basedir:lower()))
|
||||
and path:sub(#basedir+1) or path
|
||||
else
|
||||
return string.gsub(path, '^'..q(basedir), '')
|
||||
end
|
||||
end
|
||||
|
||||
local function stack(start)
|
||||
local function vars(f)
|
||||
local func = debug.getinfo(f, "f").func
|
||||
@@ -345,8 +248,15 @@ local function stack(start)
|
||||
for i = (start or 0), 100 do
|
||||
local source = debug.getinfo(i, "Snl")
|
||||
if not source then break end
|
||||
table.insert(stack, {
|
||||
{source.name, source.source, source.linedefined,
|
||||
|
||||
local src = source.source
|
||||
if src:find("@") == 1 then
|
||||
src = src:sub(2):gsub("\\", "/")
|
||||
if src:find("%./") == 1 then src = src:sub(3) end
|
||||
end
|
||||
|
||||
table.insert(stack, { -- remove basedir from source
|
||||
{source.name, removebasedir(src, basedir), source.linedefined,
|
||||
source.currentline, source.what, source.namewhat, source.short_src},
|
||||
vars(i+1)})
|
||||
if source.what == 'main' then break end
|
||||
@@ -355,19 +265,21 @@ local function stack(start)
|
||||
end
|
||||
|
||||
local function set_breakpoint(file, line)
|
||||
if file == '-' and lastfile then file = lastfile end
|
||||
if not breakpoints[file] then breakpoints[file] = {} end
|
||||
breakpoints[file][line] = true
|
||||
if file == '-' and lastfile then file = lastfile
|
||||
elseif iscasepreserving then file = string.lower(file) end
|
||||
if not breakpoints[line] then breakpoints[line] = {} end
|
||||
breakpoints[line][file] = true
|
||||
end
|
||||
|
||||
local function remove_breakpoint(file, line)
|
||||
if file == '-' and lastfile then file = lastfile end
|
||||
if breakpoints[file] then breakpoints[file][line] = nil end
|
||||
if file == '-' and lastfile then file = lastfile
|
||||
elseif iscasepreserving then file = string.lower(file) end
|
||||
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[file] and breakpoints[file][line]
|
||||
return breakpoints[line] and breakpoints[line][file]
|
||||
end
|
||||
|
||||
local function restore_vars(vars)
|
||||
@@ -437,16 +349,14 @@ local function stack_depth(start_depth)
|
||||
return start_depth
|
||||
end
|
||||
|
||||
local function is_safe(stack_level, conservative)
|
||||
local function is_safe(stack_level)
|
||||
-- the stack grows up: 0 is getinfo, 1 is is_safe, 2 is debug_hook, 3 is user function
|
||||
if stack_level == 3 then return true end
|
||||
local main = debug.getinfo(3, "S").source
|
||||
|
||||
for i = 3, stack_level do
|
||||
-- return if it is not safe to abort
|
||||
local info = debug.getinfo(i, "S")
|
||||
if not info then return true end
|
||||
if conservative and info.source ~= main or info.what == "C" then return false end
|
||||
if info.what == "C" then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
@@ -462,9 +372,18 @@ local function in_debugger()
|
||||
return false
|
||||
end
|
||||
|
||||
local function debug_hook(event, line)
|
||||
if abort and is_safe(stack_level) then error(abort) end
|
||||
local function is_pending(peer)
|
||||
-- if there is something already in the buffer, skip check
|
||||
if not buf and checkcount >= mobdebug.checkcount then
|
||||
peer:settimeout(0) -- non-blocking
|
||||
buf = peer:receive(1)
|
||||
peer:settimeout() -- back to blocking
|
||||
checkcount = 0
|
||||
end
|
||||
return buf
|
||||
end
|
||||
|
||||
local function debug_hook(event, line)
|
||||
-- (1) LuaJIT needs special treatment. Because debug_hook is set for
|
||||
-- *all* coroutines, and not just the one being debugged as in regular Lua
|
||||
-- (http://lua-users.org/lists/lua-l/2011-06/msg00513.html),
|
||||
@@ -475,23 +394,38 @@ local function debug_hook(event, line)
|
||||
-- 'tail return' events are not generated by LuaJIT).
|
||||
-- the next line checks if the debugger is run under LuaJIT and if
|
||||
-- one of debugger methods is present in the stack, it simply returns.
|
||||
-- (2) also check if this debug hook has not been visited for any reason.
|
||||
if jit then
|
||||
local coro = coroutine.running()
|
||||
if coro_debugee and coro ~= coro_debugee and not coroutines[coro]
|
||||
or not coro_debugee and (in_debugger() or coro and not coroutines[coro])
|
||||
then return end
|
||||
end
|
||||
|
||||
-- (2) check if abort has been requested and it's safe to abort
|
||||
if abort and is_safe(stack_level) then error(abort) end
|
||||
|
||||
-- (3) also check if this debug hook has not been visited for any reason.
|
||||
-- this check is needed to avoid stepping in too early
|
||||
-- (for example, when coroutine.resume() is executed inside start()).
|
||||
if (jit or not seen_hook) and in_debugger() then return end
|
||||
if not seen_hook and in_debugger() then return end
|
||||
|
||||
if event == "call" then
|
||||
stack_level = stack_level + 1
|
||||
elseif event == "return" or event == "tail return" then
|
||||
stack_level = stack_level - 1
|
||||
elseif event == "line" then
|
||||
-- may need to fall through because of the following:
|
||||
-- (1) step_into
|
||||
-- (2) step_over and stack_level <= step_level (need stack_level)
|
||||
-- (3) breakpoint; check for line first as it's known; then for file
|
||||
-- (4) socket call (only do every Xth check)
|
||||
-- (5) at least one watch is registered
|
||||
if not (
|
||||
step_into or step_over or breakpoints[line] or watchescnt > 0
|
||||
or is_pending(server)
|
||||
) then checkcount = checkcount + 1; return end
|
||||
|
||||
-- check if we need to skip some callbacks (to save time)
|
||||
if skip then
|
||||
skipcount = skipcount + 1
|
||||
if skipcount < skip or not is_safe(stack_level) then return end
|
||||
skipcount = 0
|
||||
end
|
||||
checkcount = mobdebug.checkcount -- force check on the next command
|
||||
|
||||
-- this is needed to check if the stack got shorter or longer.
|
||||
-- unfortunately counting call/return calls is not reliable.
|
||||
@@ -505,22 +439,30 @@ local function debug_hook(event, line)
|
||||
-- have any other instructions to execute. it triggers three returns:
|
||||
-- "return, tail return, return", which needs to be accounted for.
|
||||
stack_level = stack_depth(stack_level+1)
|
||||
|
||||
local caller = debug.getinfo(2, "S")
|
||||
|
||||
-- grab the filename and fix it if needed
|
||||
local file = lastfile
|
||||
if (lastsource ~= caller.source) then
|
||||
lastsource = caller.source
|
||||
file = lastsource
|
||||
if string.find(file, "@") == 1 then file = string.sub(file, 2) end
|
||||
if iswindows then file = string.lower(file) end
|
||||
file = string.gsub(file, "\\", "/") -- convert slash
|
||||
-- remove references to the current folder (./)
|
||||
if string.find(file, "%./") == 1 then file = string.sub(file, 3)
|
||||
else file = string.gsub(file, '^'..q(basedir), '') end
|
||||
-- fix filenames for loaded strings that may contain scripts with newlines
|
||||
if string.find(file, "\n") then
|
||||
file = string.sub(string.gsub(file, "\n", ' '), 1, 32) -- limit to 32 chars
|
||||
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 '@',
|
||||
-- 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
|
||||
end
|
||||
|
||||
-- set to true if we got here; this only needs to be done once per
|
||||
@@ -548,7 +490,7 @@ local function debug_hook(event, line)
|
||||
(step_into
|
||||
or (step_over and stack_level <= step_level)
|
||||
or has_breakpoint(file, line)
|
||||
or (socket.select(rset, nil, 0))[server])
|
||||
or is_pending(server))
|
||||
|
||||
if getin then
|
||||
vars = vars or capture_vars()
|
||||
@@ -562,7 +504,9 @@ local function debug_hook(event, line)
|
||||
while status and res == 'stack' do
|
||||
-- resume with the stack trace and variables
|
||||
if vars then restore_vars(vars) end -- restore vars so they are reflected in stack values
|
||||
status, res = coroutine.resume(coro_debugger, events.STACK, stack(3), file, line)
|
||||
-- this may fail if __tostring method fails at run-time
|
||||
local ok, snapshot = pcall(stack, 4)
|
||||
status, res = coroutine.resume(coro_debugger, ok and events.STACK or events.BREAK, snapshot, file, line)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -574,6 +518,8 @@ local function debug_hook(event, line)
|
||||
-- only abort if safe; if not, there is another (earlier) check inside
|
||||
-- debug_hook, which will abort execution at the first safe opportunity
|
||||
if is_safe(stack_level) then error(abort) end
|
||||
elseif not status and res then
|
||||
error(res, 2) -- report any other (internal) errors back to the application
|
||||
end
|
||||
|
||||
if vars then restore_vars(vars) end
|
||||
@@ -585,18 +531,19 @@ local function stringify_results(status, ...)
|
||||
|
||||
local t = {...}
|
||||
for i,v in pairs(t) do -- stringify each of the returned values
|
||||
t[i] = serpent.line(v, {nocode = true, comment = 1})
|
||||
local ok, res = pcall(serpent.line, v, {nocode = true, comment = 1})
|
||||
t[i] = ok and res or ("%q"):format(res):gsub("\010","n"):gsub("\026","\\026")
|
||||
end
|
||||
-- stringify table with all returned values
|
||||
-- this is done to allow each returned value to be used (serialized or not)
|
||||
-- intependently and to preserve "original" comments
|
||||
return status, serpent.dump(t, {sparse = false})
|
||||
return pcall(serpent.dump, t, {sparse = false})
|
||||
end
|
||||
|
||||
local function debugger_loop(sfile, sline)
|
||||
local function debugger_loop(sev, svars, sfile, sline)
|
||||
local command
|
||||
local app, osname
|
||||
local eval_env = {}
|
||||
local eval_env = svars or {}
|
||||
local function emptyWatch () return false end
|
||||
local loaded = {}
|
||||
for k in pairs(package.loaded) do loaded[k] = true end
|
||||
@@ -630,8 +577,10 @@ local function debugger_loop(sfile, sline)
|
||||
elseif mobdebug.yield then mobdebug.yield()
|
||||
end
|
||||
elseif not line and err == "closed" then
|
||||
error("Debugger connection unexpectedly closed")
|
||||
error("Debugger connection unexpectedly closed", 0)
|
||||
else
|
||||
-- if there is something in the pending buffer, prepend it to the line
|
||||
if buf then line = buf .. line; buf = nil end
|
||||
break
|
||||
end
|
||||
end
|
||||
@@ -690,13 +639,13 @@ local function debugger_loop(sfile, sline)
|
||||
if not loaded[k] then package.loaded[k] = nil end
|
||||
end
|
||||
|
||||
if size == 0 then -- RELOAD the current script being debugged
|
||||
if size == 0 and name == '-' then -- RELOAD the current script being debugged
|
||||
server:send("200 OK 0\n")
|
||||
coroutine.yield("load")
|
||||
else
|
||||
local chunk = server:receive(size)
|
||||
if chunk then -- LOAD a new script for debugging
|
||||
local func, res = loadstring(chunk, name)
|
||||
local func, res = loadstring(chunk, "@"..name)
|
||||
if func then
|
||||
server:send("200 OK 0\n")
|
||||
debugee = func
|
||||
@@ -791,7 +740,9 @@ local function debugger_loop(sfile, sline)
|
||||
elseif command == "BASEDIR" then
|
||||
local _, _, dir = string.find(line, "^[A-Z]+%s+(.+)%s*$")
|
||||
if dir then
|
||||
basedir = dir
|
||||
basedir = iscasepreserving and string.lower(dir) or dir
|
||||
-- reset cached source as it may change with basedir
|
||||
lastsource = nil
|
||||
server:send("200 OK\n")
|
||||
else
|
||||
server:send("400 Bad Request\n")
|
||||
@@ -803,16 +754,20 @@ local function debugger_loop(sfile, sline)
|
||||
-- as it requires yielding back to debug_hook it cannot be executed
|
||||
-- if we have not seen the hook yet as happens after start().
|
||||
-- in this case we simply return an empty result
|
||||
if not seen_hook then
|
||||
server:send("200 OK " .. serpent.dump({}) .. "\n")
|
||||
local vars, ev = {}
|
||||
if seen_hook then
|
||||
ev, vars = coroutine.yield("stack")
|
||||
end
|
||||
if ev and ev ~= events.STACK then
|
||||
server:send("401 Error in Execution " .. #vars .. "\n")
|
||||
server:send(vars)
|
||||
else
|
||||
-- yield back to debug hook to get stack information
|
||||
local ev, vars = coroutine.yield("stack")
|
||||
if ev == events.STACK then
|
||||
server:send("200 OK " ..
|
||||
serpent.dump(vars, {nocode = true, sparse = false}) .. "\n")
|
||||
local ok, res = pcall(serpent.dump, vars, {nocode = true, sparse = false})
|
||||
if ok then
|
||||
server:send("200 OK " .. res .. "\n")
|
||||
else
|
||||
server:send("401 Error in Expression 0\n")
|
||||
server:send("401 Error in Execution " .. #res .. "\n")
|
||||
server:send(res)
|
||||
end
|
||||
end
|
||||
elseif command == "OUTPUT" then
|
||||
@@ -826,7 +781,7 @@ local function debugger_loop(sfile, sline)
|
||||
while true do
|
||||
if mode == 'c' then iobase.print(unpack(tbl)) end
|
||||
for n = 1, #tbl do
|
||||
tbl[n] = serpent.line(tbl[n], {nocode = true, comment = false}) end
|
||||
tbl[n] = select(2, pcall(serpent.line, tbl[n], {nocode = true, comment = false})) end
|
||||
local file = table.concat(tbl, "\t").."\n"
|
||||
server:send("204 Output " .. stream .. " " .. #file .. "\n" .. file)
|
||||
tbl = {coroutine.yield()}
|
||||
@@ -846,7 +801,7 @@ local function debugger_loop(sfile, sline)
|
||||
end
|
||||
|
||||
local function connect(controller_host, controller_port)
|
||||
return socket.connect(controller_host, controller_port)
|
||||
return (socket.connect4 or socket.connect)(controller_host, controller_port)
|
||||
end
|
||||
|
||||
local function isrunning()
|
||||
@@ -861,19 +816,8 @@ local function start(controller_host, controller_port)
|
||||
controller_host = controller_host or "localhost"
|
||||
controller_port = controller_port or mobdebug.port
|
||||
|
||||
server = socket.connect(controller_host, controller_port)
|
||||
server = (socket.connect4 or socket.connect)(controller_host, controller_port)
|
||||
if server then
|
||||
rset = {server} -- store hash to avoid recreating it later
|
||||
-- check if we are called from the debugger as this may happen
|
||||
-- when another debugger function calls start(); only check one level deep
|
||||
local this = debug.getinfo(1, "S").source
|
||||
local info = debug.getinfo(2, "Sl")
|
||||
if info.source == this then info = debug.getinfo(3, "Sl") end
|
||||
|
||||
local file = info.source
|
||||
if string.find(file, "@") == 1 then file = string.sub(file, 2) end
|
||||
if string.find(file, "%.[/\\]") == 1 then file = string.sub(file, 3) end
|
||||
|
||||
-- correct stack depth which already has some calls on it
|
||||
-- so it doesn't go into negative when those calls return
|
||||
-- as this breaks subsequence checks in stack_depth().
|
||||
@@ -883,29 +827,45 @@ local function start(controller_host, controller_port)
|
||||
-- provide our own traceback function to report the error remotely
|
||||
do
|
||||
local dtraceback = debug.traceback
|
||||
debug.traceback = function (err) genv.print(dtraceback(err, 3)) end
|
||||
debug.traceback = function (...)
|
||||
if select('#', ...) >= 1 then
|
||||
local err, lvl = ...
|
||||
if err and type(err) ~= 'thread' then
|
||||
local trace = dtraceback(err, (lvl or 2)+1)
|
||||
if genv.print == iobase.print then -- no remote redirect
|
||||
return trace
|
||||
else
|
||||
genv.print(trace) -- report the error remotely
|
||||
return -- don't report locally to avoid double reporting
|
||||
end
|
||||
end
|
||||
end
|
||||
-- direct call to debug.traceback: return the original.
|
||||
-- debug.traceback(nil, level) doesn't work in Lua 5.1
|
||||
-- (http://lua-users.org/lists/lua-l/2011-06/msg00574.html), so
|
||||
-- simply remove first frame from the stack trace
|
||||
return (dtraceback(...):gsub("(stack traceback:\n)[^\n]*\n", "%1"))
|
||||
end
|
||||
end
|
||||
coro_debugger = coroutine.create(debugger_loop)
|
||||
debug.sethook(debug_hook, "lcr")
|
||||
return coroutine.resume(coro_debugger, file, info.currentline)
|
||||
step_into = true -- start with step command
|
||||
return true
|
||||
else
|
||||
print("Could not connect to " .. controller_host .. ":" .. controller_port)
|
||||
end
|
||||
end
|
||||
|
||||
local coro_debugee
|
||||
local function controller(controller_host, controller_port)
|
||||
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
|
||||
|
||||
local exitonerror = not skip -- exit if not running a scratchpad
|
||||
server = socket.connect(controller_host, controller_port)
|
||||
local exitonerror = not scratchpad
|
||||
server = (socket.connect4 or socket.connect)(controller_host, controller_port)
|
||||
if server then
|
||||
rset = {server} -- store hash to avoid recreating it later
|
||||
|
||||
local function report(trace, err)
|
||||
local msg = err .. "\n" .. trace
|
||||
server:send("401 Error in Execution " .. #msg .. "\n")
|
||||
@@ -919,7 +879,7 @@ local function controller(controller_host, controller_port)
|
||||
while true do
|
||||
step_into = true -- start with step command
|
||||
abort = false -- reset abort flag from the previous loop
|
||||
if skip then skipcount = skip end -- force suspend right away
|
||||
if scratchpad then checkcount = mobdebug.checkcount end -- force suspend right away
|
||||
|
||||
coro_debugee = coroutine.create(debugee)
|
||||
debug.sethook(coro_debugee, debug_hook, "lcr")
|
||||
@@ -938,6 +898,13 @@ local function controller(controller_host, controller_port)
|
||||
report(debug.traceback(coro_debugee), tostring(err))
|
||||
if exitonerror then break end
|
||||
-- resume once more to clear the response the debugger wants to send
|
||||
-- need to use capture_vars(2) as three would be the level of
|
||||
-- the caller for controller(), but because of the tail call,
|
||||
-- the caller may not exist;
|
||||
-- This is not entirely safe as the user may see the local
|
||||
-- variable from console, but they will be reset anyway.
|
||||
-- This functionality is used when scratchpad is paused to
|
||||
-- gain access to remote console to modify global variables.
|
||||
local status, err = coroutine.resume(coro_debugger, events.RESTART, capture_vars(2))
|
||||
if not status or status and err == "exit" then break end
|
||||
end
|
||||
@@ -950,19 +917,14 @@ local function controller(controller_host, controller_port)
|
||||
return true
|
||||
end
|
||||
|
||||
local function scratchpad(controller_host, controller_port, frequency)
|
||||
skip = frequency or 100
|
||||
return controller(controller_host, controller_port)
|
||||
local function scratchpad(controller_host, controller_port)
|
||||
return controller(controller_host, controller_port, true)
|
||||
end
|
||||
|
||||
local function loop(controller_host, controller_port)
|
||||
skip = nil -- just in case if loop() is called after scratchpad()
|
||||
return controller(controller_host, controller_port)
|
||||
return controller(controller_host, controller_port, false)
|
||||
end
|
||||
|
||||
local coroutines = {}
|
||||
setmetatable(coroutines, {__mode = "k"}) -- "weak" keys
|
||||
|
||||
local function on()
|
||||
if not (isrunning() and server) then return end
|
||||
|
||||
@@ -983,7 +945,8 @@ local function off()
|
||||
local co = coroutine.running()
|
||||
if co then
|
||||
if coroutines[co] then coroutines[co] = false end
|
||||
debug.sethook(co)
|
||||
-- don't remove coroutine hook under LuaJIT as there is only one (global) hook
|
||||
if not jit then debug.sethook(co) end
|
||||
else
|
||||
debug.sethook()
|
||||
end
|
||||
@@ -1046,13 +1009,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
|
||||
if iswindows then file = string.lower(file) end
|
||||
file = string.gsub(file, "\\", "/") -- convert slash
|
||||
file = string.gsub(file, '^'..q(basedir), '') -- remove basedir
|
||||
if not breakpoints[file] then breakpoints[file] = {} end
|
||||
file = removebasedir(file, basedir)
|
||||
client:send("SETB " .. file .. " " .. line .. "\n")
|
||||
if client:receive() == "200 OK" then
|
||||
breakpoints[file][line] = true
|
||||
if client:receive() == "200 OK" then
|
||||
set_breakpoint(file, line)
|
||||
else
|
||||
print("Error: breakpoint not inserted")
|
||||
end
|
||||
@@ -1083,13 +1044,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
|
||||
if iswindows then file = string.lower(file) end
|
||||
file = string.gsub(file, "\\", "/") -- convert slash
|
||||
file = string.gsub(file, '^'..q(basedir), '') -- remove basedir
|
||||
if not breakpoints[file] then breakpoints[file] = {} end
|
||||
file = removebasedir(file, basedir)
|
||||
client:send("DELB " .. file .. " " .. line .. "\n")
|
||||
if client:receive() == "200 OK" then
|
||||
breakpoints[file][line] = nil
|
||||
remove_breakpoint(file, line)
|
||||
else
|
||||
print("Error: breakpoint not removed")
|
||||
end
|
||||
@@ -1097,11 +1056,11 @@ local function handle(params, client, options)
|
||||
print("Invalid command")
|
||||
end
|
||||
elseif command == "delallb" then
|
||||
for file, breaks in pairs(breakpoints) do
|
||||
for line, _ in pairs(breaks) do
|
||||
for line, breaks in pairs(breakpoints) do
|
||||
for file, _ in pairs(breaks) do
|
||||
client:send("DELB " .. file .. " " .. line .. "\n")
|
||||
if client:receive() == "200 OK" then
|
||||
breakpoints[file][line] = nil
|
||||
if client:receive() == "200 OK" then
|
||||
remove_breakpoint(file, line)
|
||||
else
|
||||
print("Error: breakpoint at file " .. file .. " line " .. line .. " not removed")
|
||||
end
|
||||
@@ -1162,14 +1121,14 @@ local function handle(params, client, options)
|
||||
file:close()
|
||||
|
||||
local file = string.gsub(exp, "\\", "/") -- convert slash
|
||||
file = string.gsub(file, '^'..q(basedir), '') -- remove basedir
|
||||
file = removebasedir(file, basedir)
|
||||
client:send("LOAD " .. #lines .. " " .. file .. "\n")
|
||||
client:send(lines)
|
||||
end
|
||||
while true do
|
||||
local params = client:receive()
|
||||
local params, err = client:receive()
|
||||
if not params then
|
||||
return nil, nil, "Debugger error: missing response after EXEC/LOAD"
|
||||
return nil, nil, "Debugger connection " .. (err or "error")
|
||||
end
|
||||
local done = true
|
||||
local _, _, status, len = string.find(params, "^(%d+).-%s+(%d+)%s*$")
|
||||
@@ -1223,12 +1182,10 @@ local function handle(params, client, options)
|
||||
print("Invalid command")
|
||||
end
|
||||
elseif command == "listb" then
|
||||
for k, v in pairs(breakpoints) do
|
||||
local b = k .. ": " -- get filename
|
||||
for k in pairs(v) do
|
||||
b = b .. k .. " " -- get line numbers
|
||||
for l, v in pairs(breakpoints) do
|
||||
for f in pairs(v) do
|
||||
print(f .. ": " .. l)
|
||||
end
|
||||
print(b)
|
||||
end
|
||||
elseif command == "listw" then
|
||||
for i, v in pairs(watches) do
|
||||
@@ -1252,18 +1209,14 @@ local function handle(params, client, options)
|
||||
return nil, nil, stack
|
||||
end
|
||||
for _,frame in ipairs(stack) do
|
||||
-- remove basedir from short_src or source
|
||||
local src = string.gsub(frame[1][2], "\\", "/") -- convert slash
|
||||
if string.find(src, "@") == 1 then src = string.sub(src, 2) end
|
||||
if string.find(src, "%./") == 1 then src = string.sub(src, 3) end
|
||||
if iswindows then src = string.lower(src) end
|
||||
frame[1][2] = string.gsub(src, '^'..q(basedir), '') -- remove basedir
|
||||
print(serpent.line(frame[1], {comment = false}))
|
||||
end
|
||||
return stack
|
||||
elseif status == "401" then
|
||||
local res = "Error in stack result"
|
||||
print(res)
|
||||
local _, _, len = string.find(resp, "%s+(%d+)%s*$")
|
||||
len = tonumber(len)
|
||||
local res = len > 0 and client:receive(len) or "Invalid stack information."
|
||||
print("Error in expression: " .. res)
|
||||
return nil, nil, res
|
||||
else
|
||||
print("Unknown error")
|
||||
@@ -1288,12 +1241,14 @@ local function handle(params, client, options)
|
||||
elseif command == "basedir" then
|
||||
local _, _, dir = string.find(params, "^[a-z]+%s+(.+)$")
|
||||
if dir then
|
||||
if iswindows then dir = string.lower(dir) end
|
||||
dir = string.gsub(dir, "\\", "/") -- convert slash
|
||||
if not string.find(dir, "/$") then dir = dir .. "/" end
|
||||
|
||||
local remdir = dir:match("\t(.+)")
|
||||
if remdir then dir = dir:gsub("/?\t.+", "/") end
|
||||
basedir = dir
|
||||
|
||||
client:send("BASEDIR "..dir.."\n")
|
||||
client:send("BASEDIR "..(remdir or dir).."\n")
|
||||
local resp = client:receive()
|
||||
local _, _, status = string.find(resp, "^(%d+)%s+%w+%s*$")
|
||||
if status == "200" then
|
||||
@@ -1403,6 +1358,22 @@ local function moai()
|
||||
end
|
||||
end
|
||||
|
||||
-- this is a function that removes all hooks and closes the socket to
|
||||
-- report back to the controller that the debugging is done.
|
||||
-- the script that called `done` can still continue.
|
||||
local function done()
|
||||
if not (isrunning() and server) then return end
|
||||
|
||||
if not jit then
|
||||
for co, debugged in pairs(coroutines) do
|
||||
if debugged then debug.sethook(co) end
|
||||
end
|
||||
end
|
||||
|
||||
debug.sethook()
|
||||
server:close()
|
||||
end
|
||||
|
||||
-- make public functions available
|
||||
mobdebug.listen = listen
|
||||
mobdebug.loop = loop
|
||||
@@ -1414,6 +1385,7 @@ mobdebug.on = on
|
||||
mobdebug.off = off
|
||||
mobdebug.moai = moai
|
||||
mobdebug.coro = coro
|
||||
mobdebug.done = done
|
||||
mobdebug.line = serpent.line
|
||||
mobdebug.dump = serpent.dump
|
||||
mobdebug.yield = nil -- callback
|
||||
|
||||
78
spec/cpp.lua
Normal file
78
spec/cpp.lua
Normal file
@@ -0,0 +1,78 @@
|
||||
-- author: Paul Kulchenko
|
||||
---------------------------------------------------------
|
||||
|
||||
local funccall = "([A-Za-z_][A-Za-z0-9_]*)%s*"
|
||||
|
||||
return {
|
||||
exts = {"cpp", "c", "hpp", "h"},
|
||||
lexer = wxstc.wxSTC_LEX_CPP,
|
||||
apitype = "cpp",
|
||||
linecomment = "//",
|
||||
stylingbits = 5,
|
||||
|
||||
isfncall = function(str)
|
||||
return string.find(str, funccall .. "%(")
|
||||
end,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_C_IDENTIFIER,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_C_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_C_COMMENT,
|
||||
wxstc.wxSTC_C_COMMENTLINE,
|
||||
wxstc.wxSTC_C_COMMENTDOC,},
|
||||
stringtxt = {wxstc.wxSTC_C_STRING,
|
||||
wxstc.wxSTC_C_CHARACTER,
|
||||
wxstc.wxSTC_C_VERBATIM,},
|
||||
stringeol = {wxstc.wxSTC_C_STRINGEOL,},
|
||||
preprocessor= {wxstc.wxSTC_C_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_C_OPERATOR,},
|
||||
number = {wxstc.wxSTC_C_NUMBER,},
|
||||
|
||||
keywords0 = {wxstc.wxSTC_C_WORD,},
|
||||
keywords1 = {wxstc.wxSTC_C_WORD2,},
|
||||
},
|
||||
|
||||
keywords = {
|
||||
[[ alignas alignof and and_eq asm auto bitand bitor break case catch
|
||||
class compl const constexpr const_cast continue
|
||||
decltype default delete do dynamic_cast else enum explicit export
|
||||
extern for friend goto if inline mutable namespace new noexcept not
|
||||
not_eq nullptr operator or or_eq private protected public register
|
||||
reinterpret_cast return sizeof static static_assert static_cast
|
||||
struct switch template this thread_local throw try typedef typeid
|
||||
typename union using virtual volatile while xor xor_eq]],
|
||||
[[ NULL bool char char16_t char32_t double false float int long
|
||||
short signed true unsigned void wchar_t]]
|
||||
},
|
||||
}
|
||||
|
||||
--[==[ C-only keywords
|
||||
[[ auto break case const continue default do else enum extern for goto if
|
||||
register return sizeof static struct switch typedef union volatile while]],
|
||||
[[ NULL char double float int long short signed unsigned void]]
|
||||
--]==]
|
||||
|
||||
--[[
|
||||
// Lexical states for SCLEX_CPP
|
||||
%define wxSTC_C_DEFAULT
|
||||
%define wxSTC_C_COMMENT
|
||||
%define wxSTC_C_COMMENTLINE
|
||||
%define wxSTC_C_COMMENTDOC
|
||||
%define wxSTC_C_NUMBER
|
||||
%define wxSTC_C_WORD
|
||||
%define wxSTC_C_STRING
|
||||
%define wxSTC_C_CHARACTER
|
||||
%define wxSTC_C_UUID
|
||||
%define wxSTC_C_PREPROCESSOR
|
||||
%define wxSTC_C_OPERATOR
|
||||
%define wxSTC_C_IDENTIFIER
|
||||
%define wxSTC_C_STRINGEOL
|
||||
%define wxSTC_C_VERBATIM
|
||||
%define wxSTC_C_REGEX
|
||||
%define wxSTC_C_COMMENTLINEDOC
|
||||
%define wxSTC_C_WORD2
|
||||
%define wxSTC_C_COMMENTDOCKEYWORD
|
||||
%define wxSTC_C_COMMENTDOCKEYWORDERROR
|
||||
%define wxSTC_C_GLOBALCLASS
|
||||
]]
|
||||
@@ -19,27 +19,19 @@ return {
|
||||
end,
|
||||
|
||||
lexerstyleconvert = {
|
||||
text = {wxstc.wxSTC_C_IDENTIFIER,
|
||||
wxstc.wxSTC_C_VERBATIM,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_REGEX,
|
||||
wxstc.wxSTC_C_GLOBALCLASS,},
|
||||
text = {wxstc.wxSTC_C_IDENTIFIER,},
|
||||
|
||||
lexerdef = {wxstc.wxSTC_C_DEFAULT,},
|
||||
comment = {wxstc.wxSTC_C_COMMENT,
|
||||
wxstc.wxSTC_C_COMMENTLINE,
|
||||
wxstc.wxSTC_C_COMMENTDOC,
|
||||
wxstc.wxSTC_C_COMMENTLINEDOC,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORD,
|
||||
wxstc.wxSTC_C_COMMENTDOCKEYWORDERROR,},
|
||||
wxstc.wxSTC_C_COMMENTDOC,},
|
||||
stringtxt = {wxstc.wxSTC_C_STRING,
|
||||
wxstc.wxSTC_C_CHARACTER,
|
||||
wxstc.wxSTC_C_UUID,},
|
||||
wxstc.wxSTC_C_VERBATIM,},
|
||||
stringeol = {wxstc.wxSTC_C_STRINGEOL,},
|
||||
preprocessor= {wxstc.wxSTC_C_PREPROCESSOR,},
|
||||
operator = {wxstc.wxSTC_C_OPERATOR,},
|
||||
number = {wxstc.wxSTC_C_NUMBER,
|
||||
wxstc.wxSTC_C_WORD},
|
||||
number = {wxstc.wxSTC_C_NUMBER,},
|
||||
|
||||
keywords0 = {wxstc.wxSTC_C_WORD,},
|
||||
keywords1 = {wxstc.wxSTC_C_WORD2,},
|
||||
|
||||
45
spec/lua.lua
45
spec/lua.lua
@@ -27,13 +27,13 @@ local function isfndef(str)
|
||||
end
|
||||
|
||||
return {
|
||||
exts = {"lua", "rockspec"},
|
||||
exts = {"lua", "rockspec", "wlua"},
|
||||
lexer = wxstc.wxSTC_LEX_LUA,
|
||||
apitype = "lua",
|
||||
linecomment = "--",
|
||||
sep = "%.:",
|
||||
isfncall = function(str)
|
||||
return string.find(str, funccall .. "%(")
|
||||
return string.find(str, funccall .. "[%({'\"]")
|
||||
end,
|
||||
isfndef = isfndef,
|
||||
isdecindent = function(str)
|
||||
@@ -93,7 +93,6 @@ return {
|
||||
line = line -1
|
||||
end
|
||||
|
||||
local added
|
||||
while (line <= endline) do
|
||||
local ls = editor:PositionFromLine(line)
|
||||
local s = bit.band(editor:GetStyleAt(ls),31)
|
||||
@@ -103,35 +102,47 @@ return {
|
||||
|
||||
-- check for assignments
|
||||
local varname = "([%w_%.]+)"
|
||||
local identifier = "([%w_%.:]+)"
|
||||
local identifier = "([%w_%.:%s]+)"
|
||||
|
||||
-- special hint
|
||||
local typ,var = tx:match("%s*%-%-=%s*"..varname.."%s+"..identifier)
|
||||
if (var and typ) then
|
||||
typ = typ:gsub("%s","")
|
||||
assigns[var] = typ
|
||||
added = true
|
||||
else
|
||||
-- real assignments
|
||||
local var,typ,rest = tx:match("%s*"..identifier.."%s*=%s*"..identifier.."(.*)")
|
||||
local comment = rest and rest:match(".*%-%-=%s*"..varname.."%s*$")
|
||||
local comma = rest and rest:match(".-%s*([,]*)%s*$")
|
||||
if (var and comment) then
|
||||
assigns[var] = comment
|
||||
added = true
|
||||
elseif (var and typ and comma=="") then
|
||||
local var,typ = tx:match("%s*"..identifier.."%s*=%s*([^;]+)")
|
||||
|
||||
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{}","")
|
||||
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","")
|
||||
if (var and typ) then
|
||||
class,func = typ:match(varname.."[%.:]"..varname)
|
||||
if (func) then
|
||||
if (assigns[typ]) then
|
||||
assigns[var] = assigns[typ]
|
||||
elseif (func) then
|
||||
-- FIXME remove this, in favor of proper api definitions
|
||||
local added
|
||||
local funcnames = {"new","load","create"}
|
||||
for i,v in ipairs(funcnames) do
|
||||
if (func:match("^"..v)) then
|
||||
if (func == v) then
|
||||
assigns[var] = class
|
||||
added = true
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif (assigns[typ]) then
|
||||
assigns[var] = assigns[typ]
|
||||
added = true
|
||||
if (not added) then
|
||||
-- let's hope autocomplete info can resolve this
|
||||
assigns[var] = typ
|
||||
end
|
||||
else
|
||||
assigns[var] = typ
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
20
src/defs.lua
20
src/defs.lua
@@ -100,6 +100,12 @@ 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
|
||||
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
|
||||
},
|
||||
|
||||
default = {
|
||||
@@ -111,6 +117,8 @@ config = {
|
||||
verbose = false,
|
||||
hostname = nil, -- hostname to use when the detected one is incorrect
|
||||
port = nil, -- port number to use
|
||||
runonstart = nil, -- if debugger should run immediately after starting
|
||||
-- default values are different for different interpreters
|
||||
}
|
||||
|
||||
outputshell = { -- output and shell settings
|
||||
@@ -186,11 +194,17 @@ app = {
|
||||
api = {
|
||||
-- global space words, e.g "table"
|
||||
["blah"] = {
|
||||
-- "function", "class", "keyword", "value", "lib"
|
||||
-- "function", "class", "keyword", "value", "lib", "method"
|
||||
-- method is for class:func functions
|
||||
type = "function",
|
||||
description = "this does something",
|
||||
|
||||
-- value and function:
|
||||
-- value/function/method:
|
||||
-- for autocomplete type guessing, insert the string
|
||||
-- that the variable name is replace with
|
||||
-- e.g. "test = somefunc()" somefunc has valuetype of "math"
|
||||
-- then typing "test." will be treated as "math." in
|
||||
-- autcomplete logic
|
||||
valuetype = "api.ClassName",
|
||||
|
||||
-- function:
|
||||
@@ -231,7 +245,7 @@ spec = {
|
||||
linecomment = "//",
|
||||
-- string for linecomments
|
||||
|
||||
sep = "[%.:]",
|
||||
sep = "%.:",
|
||||
-- class.function separator match string,
|
||||
-- e.g in lua both . and : are allowed
|
||||
-- default is "\1" which should yield no matches
|
||||
|
||||
@@ -44,8 +44,8 @@ end
|
||||
-- API loading
|
||||
|
||||
local function addAPI(apifile,only,subapis,known) -- relative to API directory
|
||||
local ftype,fname = apifile:match("api[/\\]([^/\\]+)[/\\](.*)%.")
|
||||
if not ftype then
|
||||
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
|
||||
@@ -82,12 +82,8 @@ local function addAPI(apifile,only,subapis,known) -- relative to API directory
|
||||
end
|
||||
|
||||
local function loadallAPIs (only,subapis,known)
|
||||
for _, dir in ipairs(FileSysGet("api/*", wx.wxDIR)) do
|
||||
for _, file in ipairs(FileSysGet(dir.."/*.*", wx.wxFILE)) do
|
||||
if file:match "%.lua$" then
|
||||
addAPI(file,only,subapis,known)
|
||||
end
|
||||
end
|
||||
for _, file in ipairs(FileSysGetRecursive("api", true, "*.lua")) do
|
||||
if not file:match(string_Pathsep.."$") then addAPI(file,only,subapis,known) end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -119,7 +115,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" then
|
||||
if info.type == "function" or info.type == "method" then
|
||||
local libstr = libname ~= "" and libname.."." or ""
|
||||
|
||||
-- fix description
|
||||
@@ -206,23 +202,35 @@ local function resolveAssign(editor,tx)
|
||||
return tab,a
|
||||
end
|
||||
|
||||
local classname
|
||||
local c = ""
|
||||
local c
|
||||
if (assigns) then
|
||||
-- find assign
|
||||
for w,s in tx:gmatch("([%w_]*)([%.:]?)") do
|
||||
|
||||
local old = classname
|
||||
classname = classname or (assigns[c..w])
|
||||
if (s ~= "" and old ~= classname) then
|
||||
c = classname..s
|
||||
else
|
||||
c = c..w..s
|
||||
local change = true
|
||||
while (change) do
|
||||
local classname = nil
|
||||
c = ""
|
||||
change = false
|
||||
for w,s in tx:gmatch("([%w_]+)([%.:]?)") do
|
||||
local old = classname
|
||||
-- check if what we have so far can be matched with a class name
|
||||
-- this can happen if it's a reference to a value with a known type
|
||||
classname = classname or assigns[c..w]
|
||||
if (s ~= "" and old ~= classname) then
|
||||
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
|
||||
tx = c
|
||||
end
|
||||
else
|
||||
c = tx
|
||||
end
|
||||
|
||||
-- then work from api
|
||||
return getclass(ac,c)
|
||||
end
|
||||
@@ -367,19 +375,31 @@ end
|
||||
------------
|
||||
-- Final Autocomplete
|
||||
|
||||
local cache = {}
|
||||
local cachemain = {}
|
||||
local cachemethod = {}
|
||||
local laststrategy
|
||||
local function getAutoCompApiList(childs,fragment)
|
||||
local lastmethod
|
||||
local function getAutoCompApiList(childs,fragment,method)
|
||||
fragment = fragment:lower()
|
||||
local strategy = ide.config.acandtip.strategy
|
||||
if (laststrategy ~= strategy) then cache = {}; laststrategy = strategy end
|
||||
if (laststrategy ~= strategy) then
|
||||
cachemain = {}
|
||||
cachemethod = {}
|
||||
laststrategy = strategy
|
||||
end
|
||||
|
||||
local cache = method and cachemethod or cachemain
|
||||
|
||||
if (strategy == 2) then
|
||||
local wlist = cache[childs]
|
||||
if not wlist then
|
||||
wlist = " "
|
||||
for i in pairs(childs) do
|
||||
wlist = wlist..i.." "
|
||||
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
|
||||
wlist = wlist..i.." "
|
||||
end
|
||||
end
|
||||
cache[childs] = wlist
|
||||
end
|
||||
@@ -406,29 +426,33 @@ local function getAutoCompApiList(childs,fragment)
|
||||
cache[childs] = t
|
||||
|
||||
local sub = strategy == 1
|
||||
for key in pairs(childs) do
|
||||
local used = {}
|
||||
--
|
||||
local kl = key:lower()
|
||||
for i=0,#key do
|
||||
local k = kl:sub(1,i)
|
||||
t[k] = t[k] or {}
|
||||
used[k] = true
|
||||
table.insert(t[k],key)
|
||||
end
|
||||
if (sub) then
|
||||
-- find camel case / _ separated subwords
|
||||
-- glfwGetGammaRamp -> g, gg, ggr
|
||||
-- GL_POINT_SPRIT -> g, gp, gps
|
||||
local last = ""
|
||||
for ks in string.gmatch(key,"([A-Z%d]*[a-z%d]*_?)") do
|
||||
local k = last..(ks:sub(1,1):lower())
|
||||
last = k
|
||||
|
||||
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
|
||||
local used = {}
|
||||
--
|
||||
local kl = key:lower()
|
||||
for i=0,#key do
|
||||
local k = kl:sub(1,i)
|
||||
t[k] = t[k] or {}
|
||||
if (not used[k]) then
|
||||
used[k] = true
|
||||
table.insert(t[k],key)
|
||||
used[k] = true
|
||||
table.insert(t[k],key)
|
||||
end
|
||||
if (sub) then
|
||||
-- find camel case / _ separated subwords
|
||||
-- glfwGetGammaRamp -> g, gg, ggr
|
||||
-- GL_POINT_SPRIT -> g, gp, gps
|
||||
local last = ""
|
||||
for ks in string.gmatch(key,"([A-Z%d]*[a-z%d]*_?)") do
|
||||
local k = last..(ks:sub(1,1):lower())
|
||||
last = k
|
||||
|
||||
t[k] = t[k] or {}
|
||||
if (not used[k]) then
|
||||
used[k] = true
|
||||
table.insert(t[k],key)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -447,6 +471,8 @@ function CreateAutoCompList(editor,key)
|
||||
local tip = api.tip
|
||||
local ac = api.ac
|
||||
|
||||
local method = key:match(":[^:%.]*$") ~= nil
|
||||
|
||||
-- ignore keywords
|
||||
if tip.keys[key] then return end
|
||||
|
||||
@@ -499,7 +525,7 @@ function CreateAutoCompList(editor,key)
|
||||
end
|
||||
|
||||
-- list from api
|
||||
local apilist = getAutoCompApiList(tab.childs or tab,rest)
|
||||
local apilist = getAutoCompApiList(tab.childs or tab,rest,method)
|
||||
local compstr = ""
|
||||
if apilist then
|
||||
if (#rest > 0) then
|
||||
|
||||
@@ -14,13 +14,14 @@ local BREAKPOINT_MARKER = StylesGetMarker("breakpoint")
|
||||
function NewFile(event)
|
||||
local editor = CreateEditor()
|
||||
SetupKeywords(editor, "lua")
|
||||
AddEditor(editor, ide.config.default.fullname)
|
||||
local doc = AddEditor(editor, ide.config.default.fullname)
|
||||
if doc then SetEditorSelection(doc.index) end
|
||||
return editor
|
||||
end
|
||||
|
||||
-- Find an editor page that hasn't been used at all, eg. an untouched NewFile()
|
||||
local function findDocumentToReuse()
|
||||
local editor = nil
|
||||
local function findUnusedEditor()
|
||||
local editor
|
||||
for id, document in pairs(openDocuments) do
|
||||
if (document.editor:GetLength() == 0) and
|
||||
(not document.isModified) and (not document.filePath) and
|
||||
@@ -40,7 +41,10 @@ function LoadFile(filePath, editor, file_must_exist, skipselection)
|
||||
if (not editor) then
|
||||
for id, doc in pairs(openDocuments) do
|
||||
if doc.filePath and filePath:SameAs(wx.wxFileName(doc.filePath)) then
|
||||
if not skipselection then notebook:SetSelection(doc.index) end
|
||||
if not skipselection and doc.index ~= notebook:GetSelection() then
|
||||
-- selecting the same tab doesn't trigger PAGE_CHANGE event,
|
||||
-- but moves the focus to the tab bar, which needs to be avoided.
|
||||
notebook:SetSelection(doc.index) end
|
||||
return doc.editor
|
||||
end
|
||||
end
|
||||
@@ -58,27 +62,65 @@ function LoadFile(filePath, editor, file_must_exist, skipselection)
|
||||
end
|
||||
|
||||
local current = editor and editor:GetCurrentPos()
|
||||
editor = editor or findDocumentToReuse() or CreateEditor()
|
||||
editor = editor or findUnusedEditor() or CreateEditor()
|
||||
|
||||
editor:Freeze()
|
||||
editor:Clear()
|
||||
editor:ClearAll()
|
||||
SetupKeywords(editor, GetFileExt(filePath))
|
||||
editor:MarkerDeleteAll(BREAKPOINT_MARKER)
|
||||
editor:MarkerDeleteAll(CURRENT_LINE_MARKER)
|
||||
editor:AppendText(file_text or "")
|
||||
editor:MarkerDeleteAll(-1)
|
||||
editor:SetText(file_text or "")
|
||||
|
||||
-- check the editor as it can be empty if the file has malformed UTF8;
|
||||
-- skip binary files as they may have any sequences; can't show them anyway.
|
||||
if file_text and #file_text > 0 and #(editor:GetText()) == 0
|
||||
and not isBinary(file_text) then
|
||||
local replacement, invalid = "\022"
|
||||
file_text, invalid = fixUTF8(file_text, replacement)
|
||||
if #invalid > 0 then
|
||||
editor:AppendText(file_text)
|
||||
local lastline = nil
|
||||
for _, n in ipairs(invalid) do
|
||||
local line = editor:LineFromPosition(n)
|
||||
if line ~= lastline then
|
||||
DisplayOutputLn(("%s:%d: %s")
|
||||
:format(filePath, line+1, TR("Replaced an invalid UTF8 character with %s."):format(replacement)))
|
||||
lastline = line
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
editor:Colourise(0, -1)
|
||||
editor:Thaw()
|
||||
|
||||
if current then editor:GotoPos(current) end
|
||||
if (ide.config.editor.autotabs) then
|
||||
if (file_text and ide.config.editor.autotabs) then
|
||||
local found = string.find(file_text,"\t") ~= nil
|
||||
editor:SetUseTabs(found)
|
||||
end
|
||||
|
||||
if (file_text and ide.config.editor.checkeol) then
|
||||
-- Auto-detect CRLF/LF line-endings
|
||||
local foundcrlf = string.find(file_text,"\r\n") ~= nil
|
||||
local foundlf = (string.find(file_text,"[^\r]\n") ~= nil)
|
||||
or (string.find(file_text,"^\n") ~= nil) -- edge case: file beginning with LF and having no other LF
|
||||
if foundcrlf and foundlf then -- file with mixed line-endings
|
||||
DisplayOutputLn(("%s: %s")
|
||||
:format(filePath, TR("Mixed end-of-line encodings detected.")..' '..
|
||||
TR("Use '%s' to show line endings and '%s' to convert them.")
|
||||
:format("GetEditor():SetViewEOL(1)", "GetEditor():ConvertEOLs(GetEditor():GetEOLMode())")))
|
||||
elseif foundcrlf then
|
||||
editor:SetEOLMode(wxstc.wxSTC_EOL_CRLF)
|
||||
elseif foundlf then
|
||||
editor:SetEOLMode(wxstc.wxSTC_EOL_LF)
|
||||
-- else (e.g. file is 1 line long or uses another line-ending): use default EOL mode
|
||||
end
|
||||
end
|
||||
|
||||
editor:EmptyUndoBuffer()
|
||||
local id = editor:GetId()
|
||||
if not openDocuments[id] then -- the editor has not been added to notebook
|
||||
if openDocuments[id] then -- existing editor; switch to the tab
|
||||
notebook:SetSelection(openDocuments[id].index)
|
||||
else -- the editor has not been added to notebook
|
||||
AddEditor(editor, wx.wxFileName(filePath):GetFullName()
|
||||
or ide.config.default.fullname)
|
||||
end
|
||||
@@ -87,10 +129,6 @@ function LoadFile(filePath, editor, file_must_exist, skipselection)
|
||||
openDocuments[id].modTime = GetFileModTime(filePath)
|
||||
SetDocumentModified(id, false)
|
||||
|
||||
IndicateFunctions(editor)
|
||||
|
||||
SettingsAppendFileToHistory(filePath)
|
||||
|
||||
-- activate the editor; this is needed for those cases when the editor is
|
||||
-- created from some other element, for example, from a project tree.
|
||||
if not skipselection then SetEditorSelection() end
|
||||
@@ -110,9 +148,7 @@ local function getExtsString()
|
||||
knownexts = knownexts:len() > 0 and knownexts:sub(1,-2) or nil
|
||||
|
||||
local exts = knownexts and TR("Known Files").." ("..knownexts..")|"..knownexts.."|" or ""
|
||||
exts = exts..TR("All files").." (*)|*"
|
||||
|
||||
return exts
|
||||
return exts..TR("All files").." (*)|*"
|
||||
end
|
||||
|
||||
function OpenFile(event)
|
||||
@@ -177,10 +213,17 @@ function SaveFileAs(editor)
|
||||
fn:Normalize() -- want absolute path for dialog
|
||||
|
||||
local ext = fn:GetExt()
|
||||
if (not ext or #ext == 0) and editor.spec and editor.spec.exts then
|
||||
ext = editor.spec.exts[1]
|
||||
-- set the extension on the file if assigned as this is used by OSX/Linux
|
||||
-- to present the correct default "save as type" choice.
|
||||
if ext then fn:SetExt(ext) end
|
||||
end
|
||||
local fileDialog = wx.wxFileDialog(ide.frame, TR("Save file as"),
|
||||
fn:GetPath(wx.wxPATH_GET_VOLUME),
|
||||
fn:GetFullName(),
|
||||
"*."..(ext and #ext > 0 and ext or "*"),
|
||||
-- specify the current extension plus all other extensions based on specs
|
||||
(ext and #ext > 0 and "*."..ext.."|*."..ext.."|" or "")..getExtsString(),
|
||||
wx.wxFD_SAVE)
|
||||
|
||||
if fileDialog:ShowModal() == wx.wxID_OK then
|
||||
@@ -190,9 +233,12 @@ function SaveFileAs(editor)
|
||||
SetEditorSelection() -- update title of the editor
|
||||
FileTreeRefresh() -- refresh the tree to reflect the new file
|
||||
FileTreeMarkSelected(filePath)
|
||||
SetupKeywords(editor, GetFileExt(filePath))
|
||||
IndicateFunctions(editor)
|
||||
if MarkupStyle then MarkupStyle(editor) end
|
||||
if ext ~= GetFileExt(filePath) then
|
||||
-- new extension, so setup new keywords and re-apply indicators
|
||||
SetupKeywords(editor, GetFileExt(filePath))
|
||||
IndicateFunctions(editor)
|
||||
MarkupStyle(editor)
|
||||
end
|
||||
saved = true
|
||||
end
|
||||
end
|
||||
@@ -256,7 +302,8 @@ local function removePage(index)
|
||||
notebook:SetSelection(prevIndex)
|
||||
end
|
||||
|
||||
SetEditorSelection() -- will use notebook GetSelection to update
|
||||
-- need to set editor selection as it's called *after* PAGE_CHANGED event
|
||||
SetEditorSelection()
|
||||
end
|
||||
|
||||
function ClosePage(selection)
|
||||
@@ -285,6 +332,21 @@ function ClosePage(selection)
|
||||
end
|
||||
end
|
||||
|
||||
function CloseAllPagesExcept(selection)
|
||||
local toclose = {}
|
||||
for _, document in pairs(ide.openDocuments) do
|
||||
table.insert(toclose, document.index)
|
||||
end
|
||||
|
||||
table.sort(toclose)
|
||||
|
||||
-- close pages for those files that match the project in the reverse order
|
||||
-- (as ids shift when pages are closed)
|
||||
for i = #toclose, 1, -1 do
|
||||
if toclose[i] ~= selection then ClosePage(toclose[i]) end
|
||||
end
|
||||
end
|
||||
|
||||
-- Show a dialog to save a file before closing editor.
|
||||
-- returns wxID_YES, wxID_NO, or wxID_CANCEL if allow_cancel
|
||||
function SaveModifiedDialog(editor, allow_cancel)
|
||||
@@ -330,50 +392,47 @@ function SaveOnExit(allow_cancel)
|
||||
return true
|
||||
end
|
||||
|
||||
-- circle through "fold all" => "hide base lines" => "unfold all"
|
||||
function FoldSome()
|
||||
local editor = GetEditor()
|
||||
editor:Colourise(0, -1) -- update doc's folding info
|
||||
local visible, baseFound, expanded, folded
|
||||
for ln = 2, editor.LineCount - 1 do
|
||||
local foldall = false -- at least on header unfolded => fold all
|
||||
local hidebase = false -- at least one base is visible => hide all
|
||||
|
||||
for ln = 0, editor.LineCount - 1 do
|
||||
local foldRaw = editor:GetFoldLevel(ln)
|
||||
local foldLvl = math.mod(foldRaw, 4096)
|
||||
local foldHdr = math.mod(math.floor(foldRaw / 8192), 2) == 1
|
||||
if not baseFound and (foldLvl == wxstc.wxSTC_FOLDLEVELBASE) then
|
||||
baseFound = true
|
||||
visible = editor:GetLineVisible(ln)
|
||||
end
|
||||
if foldHdr then
|
||||
if editor:GetFoldExpanded(ln) then
|
||||
expanded = true
|
||||
else
|
||||
folded = true
|
||||
end
|
||||
end
|
||||
if expanded and folded and baseFound then break end
|
||||
end
|
||||
local show = not visible or (not baseFound and expanded) or (expanded and folded)
|
||||
local hide = visible and folded
|
||||
|
||||
if show then
|
||||
editor:ShowLines(1, editor.LineCount-1)
|
||||
-- at least one header is expanded
|
||||
foldall = foldall or (foldHdr and editor:GetFoldExpanded(ln))
|
||||
|
||||
-- at least one base can be hidden
|
||||
hidebase = hidebase or (
|
||||
not foldHdr
|
||||
and ln > 1 -- first line can't be hidden, so ignore it
|
||||
and foldLvl == wxstc.wxSTC_FOLDLEVELBASE
|
||||
and bit.band(foldRaw, wxstc.wxSTC_FOLDLEVELWHITEFLAG) == 0
|
||||
and editor:GetLineVisible(ln))
|
||||
end
|
||||
|
||||
for ln = 1, editor.LineCount - 1 do
|
||||
-- shows lines; this doesn't change fold status for folded lines
|
||||
if not foldall and not hidebase then editor:ShowLines(0, editor.LineCount-1) end
|
||||
|
||||
for ln = 0, editor.LineCount-1 do
|
||||
local foldRaw = editor:GetFoldLevel(ln)
|
||||
local foldLvl = math.mod(foldRaw, 4096)
|
||||
local foldHdr = math.mod(math.floor(foldRaw / 8192), 2) == 1
|
||||
if show then
|
||||
if foldHdr then
|
||||
if not editor:GetFoldExpanded(ln) then editor:ToggleFold(ln) end
|
||||
end
|
||||
elseif hide and (foldLvl == wxstc.wxSTC_FOLDLEVELBASE) then
|
||||
if not foldHdr then
|
||||
editor:HideLines(ln, ln)
|
||||
end
|
||||
elseif foldHdr then
|
||||
if editor:GetFoldExpanded(ln) then
|
||||
editor:ToggleFold(ln)
|
||||
end
|
||||
|
||||
if foldall then
|
||||
if foldHdr and editor:GetFoldExpanded(ln) then
|
||||
editor:ToggleFold(ln) end
|
||||
elseif hidebase then
|
||||
if not foldHdr and (foldLvl == wxstc.wxSTC_FOLDLEVELBASE) then
|
||||
editor:HideLines(ln, ln) end
|
||||
else -- unfold all
|
||||
if foldHdr and not editor:GetFoldExpanded(ln) then
|
||||
editor:ToggleFold(ln) end
|
||||
end
|
||||
end
|
||||
editor:EnsureCaretVisible()
|
||||
@@ -492,12 +551,7 @@ end
|
||||
function SetOpenFiles(nametab,params)
|
||||
for i,doc in ipairs(nametab) do
|
||||
local editor = LoadFile(doc.filename,nil,true,true) -- skip selection
|
||||
if editor then
|
||||
editor:SetCurrentPos(doc.cursorpos or 0)
|
||||
editor:SetSelectionStart(doc.cursorpos or 0)
|
||||
editor:SetSelectionEnd(doc.cursorpos or 0)
|
||||
editor:EnsureCaretVisible()
|
||||
end
|
||||
if editor then editor:GotoPosDelayed(doc.cursorpos or 0) end
|
||||
end
|
||||
notebook:SetSelection(params and params.index or 0)
|
||||
SetEditorSelection()
|
||||
@@ -507,33 +561,35 @@ local beforeFullScreenPerspective
|
||||
function ShowFullScreen(setFullScreen)
|
||||
if setFullScreen then
|
||||
beforeFullScreenPerspective = uimgr:SavePerspective()
|
||||
uimgr:GetPane("bottomnotebook"):Show(false)
|
||||
uimgr:GetPane("projpanel"):Show(false)
|
||||
|
||||
local panes = frame.uimgr:GetAllPanes()
|
||||
for index = 0, panes:GetCount()-1 do
|
||||
local name = panes:Item(index).name
|
||||
if name ~= "notebook" then frame.uimgr:GetPane(name):Hide() end
|
||||
end
|
||||
uimgr:Update()
|
||||
SetEditorSelection() -- make sure the focus is on the editor
|
||||
elseif beforeFullScreenPerspective then
|
||||
uimgr:LoadPerspective(beforeFullScreenPerspective)
|
||||
uimgr:LoadPerspective(beforeFullScreenPerspective, true)
|
||||
beforeFullScreenPerspective = nil
|
||||
end
|
||||
|
||||
uimgr:GetPane("toolBar"):Show(not setFullScreen)
|
||||
uimgr:Update()
|
||||
-- On OSX, toolbar and status bar are not hidden when switched to
|
||||
-- full screen: http://trac.wxwidgets.org/ticket/14259; do manually.
|
||||
-- need to turn off before showing full screen and turn on after,
|
||||
-- otherwise the window is restored incorrectly and is reduced in size.
|
||||
if ide.osname == 'Macintosh' and setFullScreen then
|
||||
frame:GetStatusBar():Hide()
|
||||
frame:GetToolBar():Hide()
|
||||
end
|
||||
|
||||
-- protect from systems that don't have ShowFullScreen (GTK on linux?)
|
||||
pcall(function() frame:ShowFullScreen(setFullScreen) end)
|
||||
end
|
||||
|
||||
local function restoreFiles(files)
|
||||
-- open files, but ignore some functions that are not needed;
|
||||
-- as we may be opening multiple files, it doesn't make sense to
|
||||
-- select editor and do some other similar work after each file.
|
||||
local noop, func = function() end, LoadFile
|
||||
local genv = {SetEditorSelection = noop, SettingsAppendFileToHistory = noop}
|
||||
setmetatable(genv, {__index = _G})
|
||||
local env = getfenv(func)
|
||||
setfenv(func, genv)
|
||||
-- provide fake index so that it doesn't activate it as the index may be not
|
||||
-- quite correct if some of the existing files are already open in the IDE.
|
||||
SetOpenFiles(files, {index = #files + notebook:GetPageCount()})
|
||||
setfenv(func, env)
|
||||
if ide.osname == 'Macintosh' and not setFullScreen then
|
||||
frame:GetStatusBar():Show()
|
||||
frame:GetToolBar():Show()
|
||||
end
|
||||
end
|
||||
|
||||
function ProjectConfig(dir, config)
|
||||
@@ -560,10 +616,7 @@ function SetOpenTabs(params)
|
||||
:format(doc.filename, doc.tabname))
|
||||
end
|
||||
end
|
||||
editor:SetCurrentPos(doc.cursorpos or 0)
|
||||
editor:SetSelectionStart(doc.cursorpos or 0)
|
||||
editor:SetSelectionEnd(doc.cursorpos or 0)
|
||||
editor:EnsureCaretVisible()
|
||||
editor:GotoPosDelayed(doc.cursorpos or 0)
|
||||
end
|
||||
notebook:SetSelection(params and params.index or 0)
|
||||
SetEditorSelection()
|
||||
@@ -611,11 +664,22 @@ local function saveAutoRecovery(event)
|
||||
TR("Saved auto-recover at %s."):format(os.date("%H:%M:%S")), 1)
|
||||
end
|
||||
|
||||
local function fastWrap(func, ...)
|
||||
-- ignore SetEditorSelection that is not needed as `func` may work on
|
||||
-- multipe files, but editor needs to be selected once.
|
||||
local SES = SetEditorSelection
|
||||
SetEditorSelection = function() end
|
||||
func(...)
|
||||
SetEditorSelection = SES
|
||||
end
|
||||
|
||||
function StoreRestoreProjectTabs(curdir, newdir)
|
||||
local win = ide.osname == 'Windows'
|
||||
local interpreter = ide.interpreter.fname
|
||||
local current, closing, restore = notebook:GetSelection(), 0, false
|
||||
|
||||
if ide.osname ~= 'Macintosh' then notebook:Freeze() end
|
||||
|
||||
if curdir and #curdir > 0 then
|
||||
local lowcurdir = win and string.lower(curdir) or curdir
|
||||
local lownewdir = win and string.lower(newdir) or newdir
|
||||
@@ -641,16 +705,22 @@ function StoreRestoreProjectTabs(curdir, newdir)
|
||||
|
||||
-- close pages for those files that match the project in the reverse order
|
||||
-- (as ids shift when pages are closed)
|
||||
for i = #closdocs, 1, -1 do ClosePage(closdocs[i].id) end
|
||||
for i = #closdocs, 1, -1 do fastWrap(ClosePage, closdocs[i].id) end
|
||||
end
|
||||
|
||||
local files, params = ProjectConfig(newdir)
|
||||
if files then restoreFiles(files) end
|
||||
if files then
|
||||
-- provide fake index so that it doesn't activate it as the index may be not
|
||||
-- quite correct if some of the existing files are already open in the IDE.
|
||||
fastWrap(SetOpenFiles, files, {index = #files + notebook:GetPageCount()})
|
||||
end
|
||||
|
||||
if params and params.interpreter and ide.interpreter.fname ~= params.interpreter then
|
||||
ProjectSetInterpreter(params.interpreter) -- set the interpreter
|
||||
end
|
||||
|
||||
if ide.osname ~= 'Macintosh' then notebook:Thaw() end
|
||||
|
||||
local index = params and params.index
|
||||
if notebook:GetPageCount() == 0 then NewFile()
|
||||
elseif restore and current >= 0 then notebook:SetSelection(current)
|
||||
@@ -666,7 +736,7 @@ function StoreRestoreProjectTabs(curdir, newdir)
|
||||
ProjectConfig(newdir, {})
|
||||
end
|
||||
|
||||
function CloseWindow(event)
|
||||
local function closeWindow(event)
|
||||
-- if the app is already exiting, then help it exit; wxwidgets on Windows
|
||||
-- is supposed to report Shutdown/logoff events by setting CanVeto() to
|
||||
-- false, but it doesn't happen. We simply leverage the fact that
|
||||
@@ -683,20 +753,32 @@ function CloseWindow(event)
|
||||
end
|
||||
|
||||
ShowFullScreen(false)
|
||||
ide.frame:Hide() -- hide everything while the IDE exits
|
||||
SettingsSaveAll()
|
||||
if DebuggerCloseWatchWindow then DebuggerCloseWatchWindow() end
|
||||
if DebuggerCloseStackWindow then DebuggerCloseStackWindow() end
|
||||
if DebuggerShutdown then DebuggerShutdown() end
|
||||
ide.settings:delete() -- always delete the config
|
||||
if ide.session.timer then ide.session.timer:Stop() end
|
||||
event:Skip()
|
||||
|
||||
-- without explicit exit() the IDE crashes with SIGILL exception when closed
|
||||
-- on MacOS compiled under 64bit with wxwidgets 2.9.3
|
||||
if ide.osname == "Macintosh" then os.exit() end
|
||||
SettingsSaveAll()
|
||||
ide.settings:Flush()
|
||||
|
||||
do -- hide all floating panes first
|
||||
local panes = frame.uimgr:GetAllPanes()
|
||||
for index = 0, panes:GetCount()-1 do
|
||||
local pane = frame.uimgr:GetPane(panes:Item(index).name)
|
||||
if pane:IsFloating() then pane:Hide() end
|
||||
end
|
||||
end
|
||||
frame.uimgr:Update() -- hide floating panes
|
||||
frame.uimgr:UnInit()
|
||||
frame:Hide() -- hide the main frame while the IDE exits
|
||||
|
||||
-- first need to detach all processes IDE has launched as the current
|
||||
-- process is likely to terminate before child processes are terminated,
|
||||
-- which may lead to a crash when EVT_END_PROCESS event is called.
|
||||
DetachChildProcess()
|
||||
DebuggerShutdown()
|
||||
|
||||
if ide.session.timer then ide.session.timer:Stop() end
|
||||
|
||||
event:Skip()
|
||||
end
|
||||
frame:Connect(wx.wxEVT_CLOSE_WINDOW, CloseWindow)
|
||||
frame:Connect(wx.wxEVT_CLOSE_WINDOW, closeWindow)
|
||||
|
||||
frame:Connect(wx.wxEVT_TIMER, saveAutoRecovery)
|
||||
|
||||
|
||||
@@ -13,10 +13,9 @@ debugger.server = nil -- DebuggerServer object when debugging, else nil
|
||||
debugger.running = false -- true when the debuggee is running
|
||||
debugger.listening = false -- true when the debugger is listening for a client
|
||||
debugger.portnumber = ide.config.debugger.port or mobdebug.port -- the port # to use for debugging
|
||||
debugger.watchWindow = nil -- the watchWindow, nil when not created
|
||||
debugger.watchCtrl = nil -- the child ctrl in the watchWindow
|
||||
debugger.stackWindow = nil -- the stackWindow, nil when not created
|
||||
debugger.stackCtrl = nil -- the child ctrl in the stackWindow
|
||||
debugger.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
|
||||
@@ -32,10 +31,18 @@ local CURRENT_LINE_MARKER_VALUE = 2^CURRENT_LINE_MARKER
|
||||
local BREAKPOINT_MARKER = StylesGetMarker("breakpoint")
|
||||
local BREAKPOINT_MARKER_VALUE = 2^BREAKPOINT_MARKER
|
||||
|
||||
local activate = {CHECKONLY = 1, NOREPORT = 2}
|
||||
|
||||
local function q(s) return s:gsub('([%(%)%.%%%+%-%*%?%[%^%$%]])','%%%1') end
|
||||
|
||||
local function updateWatchesSync(num)
|
||||
local watchCtrl = debugger.watchCtrl
|
||||
if watchCtrl and debugger.server and not debugger.running
|
||||
and ide.frame.uimgr:GetPane("watchpanel"):IsShown()
|
||||
and not debugger.scratchpad and not (debugger.options or {}).noeval then
|
||||
local bgcl = watchCtrl:GetBackgroundColour()
|
||||
local hicl = wx.wxColour(math.floor(bgcl:Red()*.9),
|
||||
math.floor(bgcl:Green()*.9), math.floor(bgcl:Blue()*.9))
|
||||
for idx = 0, watchCtrl:GetItemCount() - 1 do
|
||||
if not num or idx == num then
|
||||
local expression = watchCtrl:GetItemText(idx)
|
||||
@@ -52,9 +59,7 @@ local function updateWatchesSync(num)
|
||||
watchCtrl:GetItem(litem)
|
||||
watchCtrl:SetItemBackgroundColour(idx,
|
||||
watchCtrl:GetItem(litem) and newval ~= litem:GetText()
|
||||
and ide.config.styles.caretlinebg
|
||||
and wx.wxColour(unpack(ide.config.styles.caretlinebg.bg))
|
||||
or watchCtrl:GetBackgroundColour())
|
||||
and hicl or bgcl)
|
||||
end
|
||||
|
||||
watchCtrl:SetItem(idx, 1, newval)
|
||||
@@ -77,8 +82,9 @@ end
|
||||
|
||||
local function updateStackSync()
|
||||
local stackCtrl = debugger.stackCtrl
|
||||
if stackCtrl and debugger.server
|
||||
and not debugger.running and not debugger.scratchpad then
|
||||
if stackCtrl and debugger.server and not debugger.running
|
||||
and ide.frame.uimgr:GetPane("stackpanel"):IsShown()
|
||||
and not debugger.scratchpad then
|
||||
local stack, _, err = debugger.stack()
|
||||
if not stack or #stack == 0 then
|
||||
stackCtrl:DeleteAllItems()
|
||||
@@ -109,7 +115,9 @@ local function updateStackSync()
|
||||
or " (defined in "..call[2]..")"))
|
||||
local callitem = stackCtrl:AppendItem(root, text, 0)
|
||||
for name,val in pairs(frame[2]) do
|
||||
local value, comment = val[1], val[2]
|
||||
-- comment can be not necessarily a string for tables with metatables
|
||||
-- that provide its own __tostring method
|
||||
local value, comment = val[1], tostring(val[2])
|
||||
local text = ("%s = %s%s"):
|
||||
format(name, mobdebug.line(value, params),
|
||||
simpleType[type(value)] and "" or (" --[["..comment.."]]"))
|
||||
@@ -119,7 +127,7 @@ local function updateStackSync()
|
||||
end
|
||||
end
|
||||
for name,val in pairs(frame[3]) do
|
||||
local value, comment = val[1], val[2]
|
||||
local value, comment = val[1], tostring(val[2])
|
||||
local text = ("%s = %s%s"):
|
||||
format(name, mobdebug.line(value, params),
|
||||
simpleType[type(value)] and "" or (" --[["..comment.."]]"))
|
||||
@@ -132,6 +140,7 @@ local function updateStackSync()
|
||||
stackCtrl:Expand(callitem)
|
||||
end
|
||||
stackCtrl:EnsureVisible(stackCtrl:GetFirstChild(root))
|
||||
stackCtrl:SetScrollPos(wx.wxHORIZONTAL, 0, true)
|
||||
stackCtrl:Thaw()
|
||||
end
|
||||
end
|
||||
@@ -154,6 +163,28 @@ local function updateWatches(num)
|
||||
end
|
||||
end
|
||||
|
||||
local function debuggerToggleViews(show)
|
||||
local mgr = ide.frame.uimgr
|
||||
local refresh = false
|
||||
for view, needed in pairs(debugger.toggleview) do
|
||||
local pane = mgr:GetPane(view)
|
||||
if show then -- starting debugging and pane is not shown
|
||||
debugger.toggleview[view] = not pane:IsShown()
|
||||
if debugger.toggleview[view] and needed then
|
||||
pane:Show()
|
||||
refresh = true
|
||||
end
|
||||
else -- completing debugging and pane is shown
|
||||
debugger.toggleview[view] = pane:IsShown() and needed
|
||||
if debugger.toggleview[view] then
|
||||
pane:Hide()
|
||||
refresh = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if refresh then mgr:Update() end
|
||||
end
|
||||
|
||||
local function killClient()
|
||||
if (debugger.pid) then
|
||||
-- using SIGTERM for some reason kills not only the debugee process,
|
||||
@@ -170,7 +201,7 @@ local function killClient()
|
||||
end
|
||||
end
|
||||
|
||||
local function activateDocument(file, line)
|
||||
local function activateDocument(file, line, activatehow)
|
||||
if not file then return end
|
||||
|
||||
if not wx.wxIsAbsolutePath(file) and debugger.basedir then
|
||||
@@ -184,29 +215,56 @@ local function activateDocument(file, line)
|
||||
-- skip those tabs that may have file without names (untitled.lua)
|
||||
if document.filePath and fileName:SameAs(wx.wxFileName(document.filePath)) then
|
||||
local editor = document.editor
|
||||
local selection = document.index
|
||||
notebook:SetSelection(selection)
|
||||
SetEditorSelection(selection)
|
||||
|
||||
ClearAllCurrentLineMarkers()
|
||||
if line then
|
||||
editor:MarkerAdd(line-1, CURRENT_LINE_MARKER)
|
||||
editor:EnsureVisibleEnforcePolicy(line-1)
|
||||
if line == 0 then -- special case; find the first executable line
|
||||
line = math.huge
|
||||
local func = loadstring(editor:GetText())
|
||||
if func then -- .activelines == {[3] = true, [4] = true, ...}
|
||||
for l in pairs(debug.getinfo(func, "L").activelines) do
|
||||
if l < line then line = l end
|
||||
end
|
||||
end
|
||||
if line == math.huge then line = 1 end
|
||||
end
|
||||
local line = line - 1 -- editor line operations are zero-based
|
||||
editor:MarkerAdd(line, CURRENT_LINE_MARKER)
|
||||
|
||||
-- found and marked what we are looking for;
|
||||
-- don't need to activate with CHECKONLY (this assumes line is given)
|
||||
if activatehow == activate.CHECKONLY then return editor end
|
||||
|
||||
local firstline = editor:DocLineFromVisible(editor:GetFirstVisibleLine())
|
||||
local lastline = math.min(editor:GetLineCount(),
|
||||
editor:DocLineFromVisible(editor:GetFirstVisibleLine() + editor:LinesOnScreen()))
|
||||
-- if the line is already on the screen, then don't enforce policy
|
||||
if line <= firstline or line >= lastline then
|
||||
editor:EnsureVisibleEnforcePolicy(line)
|
||||
end
|
||||
end
|
||||
|
||||
local selection = document.index
|
||||
RequestAttention()
|
||||
notebook:SetSelection(selection)
|
||||
SetEditorSelection(selection)
|
||||
|
||||
activated = editor
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not activated and not indebugger and not debugger.loop
|
||||
if not (activated or indebugger or debugger.loop or activatehow == activate.CHECKONLY)
|
||||
and ide.config.editor.autoactivate then
|
||||
-- found file, but can't activate yet (because this part may be executed
|
||||
-- in a different co-routine), so schedule pending activation.
|
||||
-- in a different coroutine), so schedule pending activation.
|
||||
if wx.wxFileName(file):FileExists() then
|
||||
debugger.activate = {file, line}
|
||||
return true -- report successful activation, even though it's pending
|
||||
end
|
||||
|
||||
if not debugger.missing[file] then -- only report files once per session
|
||||
-- only report files once per session and if not asked to skip
|
||||
if not debugger.missing[file] and activatehow ~= activate.NOREPORT then
|
||||
debugger.missing[file] = true
|
||||
DisplayOutputLn(TR("Couldn't activate file '%s' for debugging; continuing without it.")
|
||||
:format(file))
|
||||
@@ -254,7 +312,7 @@ debugger.shell = function(expression, isstatement)
|
||||
expression = expression:gsub("^%s*=%s*","")
|
||||
local _, values, err = debugger.evaluate(expression)
|
||||
if not forceexpression and err and
|
||||
(err:find("'<eof>' expected near '") or
|
||||
(err:find("'?<eof>'? expected near '") or
|
||||
err:find("'%(' expected near") or
|
||||
err:find("unexpected symbol near '")) then
|
||||
_, values, err = debugger.execute(expression)
|
||||
@@ -292,6 +350,16 @@ debugger.shell = function(expression, isstatement)
|
||||
end
|
||||
end
|
||||
|
||||
local function stoppedAtBreakpoint(file, line)
|
||||
-- if this document can be activated and the current line has a breakpoint
|
||||
local editor = activateDocument(file, line, activate.CHECKONLY)
|
||||
if not editor then return false end
|
||||
|
||||
local current = editor:MarkerNext(0, CURRENT_LINE_MARKER_VALUE)
|
||||
local breakpoint = editor:MarkerNext(current, BREAKPOINT_MARKER_VALUE)
|
||||
return breakpoint > -1 and breakpoint == current
|
||||
end
|
||||
|
||||
debugger.listen = function()
|
||||
local server = socket.bind("*", debugger.portnumber)
|
||||
DisplayOutputLn(TR("Debugger server started at %s:%d.")
|
||||
@@ -309,6 +377,10 @@ debugger.listen = function()
|
||||
end)
|
||||
|
||||
local options = debugger.options or {}
|
||||
-- this may be a remote call without using an interpreter and as such
|
||||
-- debugger.options may not be set, but runonstart is still configured.
|
||||
if not options.runstart then options.runstart = ide.config.debugger.runonstart end
|
||||
|
||||
if not debugger.scratchpad then SetAllEditorsReadOnly(true) end
|
||||
|
||||
debugger.server = copas.wrap(skt)
|
||||
@@ -373,6 +445,9 @@ debugger.listen = function()
|
||||
.." "..TR("Compilation error")
|
||||
..":\n"..err)
|
||||
return debugger.terminate()
|
||||
elseif options.runstart and stoppedAtBreakpoint(file, line) then
|
||||
activateDocument(file, line)
|
||||
options.runstart = false
|
||||
end
|
||||
elseif not (options.run or debugger.scratchpad) then
|
||||
local file, line, err = debugger.loadfile(startfile)
|
||||
@@ -380,12 +455,22 @@ debugger.listen = function()
|
||||
-- OR (2) it can "refuse" to load it if the client was started
|
||||
-- with start() method, which can't load new files
|
||||
-- if file and line are set, this indicates option #2
|
||||
if file and line then
|
||||
local activated = activateDocument(file, line)
|
||||
if err then
|
||||
DisplayOutputLn(TR("Can't debug the script in the active editor window.")
|
||||
.." "..TR("Compilation error")
|
||||
..":\n"..err)
|
||||
return debugger.terminate()
|
||||
elseif options.runstart then
|
||||
if stoppedAtBreakpoint(file or startfile, line or 0) then
|
||||
activateDocument(file or startfile, line or 0)
|
||||
options.runstart = false
|
||||
end
|
||||
elseif file and line then
|
||||
local activated = activateDocument(file, line, activate.NOREPORT)
|
||||
|
||||
-- if not found, check using full file path and reset basedir
|
||||
if not activated and not wx.wxIsAbsolutePath(file) then
|
||||
activated = activateDocument(startpath..file, line)
|
||||
activated = activateDocument(startpath..file, line, activate.NOREPORT)
|
||||
if activated then
|
||||
debugger.basedir = startpath
|
||||
debugger.handle("basedir " .. debugger.basedir)
|
||||
@@ -394,6 +479,42 @@ debugger.listen = function()
|
||||
end
|
||||
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
|
||||
-- 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
|
||||
-- and Linux it only handles 'native' separator;
|
||||
-- need to translate for GetDirs to work.
|
||||
local file = file:gsub("\\", "/")
|
||||
local parts = wx.wxFileName(file):GetDirs()
|
||||
local name = wx.wxFileName(file):GetFullName()
|
||||
|
||||
-- find the longest remote path that can be mapped locally
|
||||
local longestpath, remotedir
|
||||
while true do
|
||||
local mapped = GetFullPathIfExists(basedir, name)
|
||||
if mapped then
|
||||
longestpath = mapped
|
||||
remotedir = file:gsub(q(name):gsub("/", ".").."$", "")
|
||||
end
|
||||
if #parts == 0 then break end
|
||||
name = table.remove(parts, #parts) .. "/" .. name
|
||||
end
|
||||
|
||||
-- if found a local mapping under basedir
|
||||
activated = longestpath and activateDocument(longestpath, line, activate.NOREPORT)
|
||||
if activated then
|
||||
-- find remote basedir by removing the tail from remote file
|
||||
debugger.handle("basedir " .. debugger.basedir .. "\t" .. remotedir)
|
||||
-- reset breakpoints again as remote basedir has changed
|
||||
reSetBreakpoints()
|
||||
DisplayOutputLn(TR("Mapped remote request for '%s' to '%s'.")
|
||||
:format(remotedir, debugger.basedir))
|
||||
end
|
||||
end
|
||||
|
||||
if not activated then
|
||||
DisplayOutputLn(TR("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.")
|
||||
:format(file))
|
||||
@@ -403,14 +524,9 @@ debugger.listen = function()
|
||||
-- debugger may still be available for scratchpad,
|
||||
-- if the interpreter signals scratchpad support, so enable it.
|
||||
debugger.scratchable = ide.interpreter.scratchextloop ~= nil
|
||||
elseif err then
|
||||
DisplayOutputLn(TR("Can't debug the script in the active editor window.")
|
||||
.." "..TR("Compilation error")
|
||||
..":\n"..err)
|
||||
return debugger.terminate()
|
||||
else
|
||||
debugger.scratchable = true
|
||||
activateDocument(startfile, 1)
|
||||
activateDocument(startfile, 0) -- find the appropriate line
|
||||
end
|
||||
end
|
||||
|
||||
@@ -418,6 +534,7 @@ debugger.listen = function()
|
||||
ShellSupportRemote(debugger.shell)
|
||||
end
|
||||
|
||||
debuggerToggleViews(true)
|
||||
updateStackSync()
|
||||
updateWatchesSync()
|
||||
|
||||
@@ -443,9 +560,7 @@ debugger.handle = function(command, server, options)
|
||||
local verbose = ide.config.debugger.verbose
|
||||
local osexit, gprint
|
||||
osexit, os.exit = os.exit, function () end
|
||||
if (verbose) then
|
||||
gprint, _G.print = _G.print, function (...) DisplayOutputLn(...) end
|
||||
end
|
||||
gprint, _G.print = _G.print, function (...) if verbose then DisplayOutputLn(...) end end
|
||||
|
||||
debugger.running = true
|
||||
if verbose then DisplayOutputLn("Debugger sent (command):", command) end
|
||||
@@ -454,7 +569,7 @@ debugger.handle = function(command, server, options)
|
||||
debugger.running = false
|
||||
|
||||
os.exit = osexit
|
||||
if (verbose) then _G.print = gprint end
|
||||
_G.print = gprint
|
||||
return file, line, err
|
||||
end
|
||||
|
||||
@@ -498,6 +613,7 @@ debugger.exec = function(command)
|
||||
if debugger.breaking then
|
||||
DisplayOutputLn(TR("Debugging suspended at %s:%s (couldn't activate the file).")
|
||||
:format(file, line))
|
||||
updateStackAndWatches()
|
||||
return
|
||||
end
|
||||
-- redo now; if the call is from the debugger, then repeat
|
||||
@@ -601,54 +717,6 @@ debugger.quickeval = function(var, callback)
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
-- public api
|
||||
|
||||
function DebuggerAttachDefault(options)
|
||||
debugger.options = options
|
||||
if (debugger.listening) then return end
|
||||
debugger.listen()
|
||||
end
|
||||
|
||||
function DebuggerShutdown()
|
||||
if debugger.server then debugger.terminate() end
|
||||
if debugger.pid then killClient() end
|
||||
end
|
||||
|
||||
function DebuggerStop()
|
||||
if (debugger.server) then
|
||||
debugger.server = nil
|
||||
debugger.pid = nil
|
||||
SetAllEditorsReadOnly(false)
|
||||
ShellSupportRemote(nil)
|
||||
ClearAllCurrentLineMarkers()
|
||||
DebuggerScratchpadOff()
|
||||
local lines = TR("traced %d instruction", debugger.stats.line):format(debugger.stats.line)
|
||||
DisplayOutputLn(TR("Debugging session completed (%s)."):format(lines))
|
||||
else
|
||||
-- it's possible that the application couldn't start, or that the
|
||||
-- debugger in the application didn't start, which means there is
|
||||
-- no debugger.server, but scratchpad may still be on. Turn it off.
|
||||
DebuggerScratchpadOff()
|
||||
end
|
||||
end
|
||||
|
||||
function DebuggerCloseStackWindow()
|
||||
if (debugger.stackWindow) then
|
||||
SettingsSaveFramePosition(debugger.stackWindow, "StackWindow")
|
||||
debugger.stackCtrl = nil
|
||||
debugger.stackWindow = nil
|
||||
end
|
||||
end
|
||||
|
||||
function DebuggerCloseWatchWindow()
|
||||
if (debugger.watchWindow) then
|
||||
SettingsSaveFramePosition(debugger.watchWindow, "WatchWindow")
|
||||
debugger.watchCtrl = nil
|
||||
debugger.watchWindow = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- need imglist to be a file local variable as SetImageList takes ownership
|
||||
-- of it and if done inside a function, icons do not work as expected
|
||||
local imglist = wx.wxImageList(16,16)
|
||||
@@ -663,34 +731,15 @@ do
|
||||
imglist:Add(getBitmap(wx.wxART_REPORT_VIEW, wx.wxART_OTHER, size))
|
||||
end
|
||||
|
||||
function DebuggerCreateStackWindow()
|
||||
if (debugger.stackWindow) then return updateStackAndWatches() end
|
||||
local width = 360
|
||||
local stackWindow = wx.wxFrame(ide.frame, wx.wxID_ANY,
|
||||
TR("Stack Window"),
|
||||
wx.wxDefaultPosition, wx.wxSize(width, 200),
|
||||
wx.wxDEFAULT_FRAME_STYLE + wx.wxFRAME_FLOAT_ON_PARENT)
|
||||
|
||||
debugger.stackWindow = stackWindow
|
||||
|
||||
local stackCtrl = wx.wxTreeCtrl(stackWindow, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
local width, height = 360, 200
|
||||
function debuggerCreateStackWindow()
|
||||
local stackCtrl = wx.wxTreeCtrl(ide.frame, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxSize(width, height),
|
||||
wx.wxTR_LINES_AT_ROOT + wx.wxTR_HAS_BUTTONS + wx.wxTR_SINGLE + wx.wxTR_HIDE_ROOT)
|
||||
|
||||
debugger.stackCtrl = stackCtrl
|
||||
|
||||
stackCtrl:SetImageList(imglist)
|
||||
stackWindow:CentreOnParent()
|
||||
SettingsRestoreFramePosition(stackWindow, "StackWindow")
|
||||
stackWindow:Show(true)
|
||||
|
||||
stackWindow:Connect(wx.wxEVT_CLOSE_WINDOW,
|
||||
function (event)
|
||||
DebuggerCloseStackWindow()
|
||||
stackWindow = nil
|
||||
stackCtrl = nil
|
||||
event:Skip()
|
||||
end)
|
||||
|
||||
stackCtrl:Connect( wx.wxEVT_COMMAND_TREE_ITEM_EXPANDING,
|
||||
function (event)
|
||||
@@ -715,33 +764,24 @@ function DebuggerCreateStackWindow()
|
||||
stackCtrl:SortChildren(item_id)
|
||||
return true
|
||||
end)
|
||||
stackCtrl:Connect( wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSED,
|
||||
function() return true end)
|
||||
|
||||
updateStackAndWatches()
|
||||
local notebook = wxaui.wxAuiNotebook(frame, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wxaui.wxAUI_NB_DEFAULT_STYLE + wxaui.wxAUI_NB_TAB_EXTERNAL_MOVE
|
||||
- wxaui.wxAUI_NB_CLOSE_ON_ACTIVE_TAB + wx.wxNO_BORDER)
|
||||
notebook:AddPage(stackCtrl, TR("Stack"), true)
|
||||
|
||||
local mgr = ide.frame.uimgr
|
||||
mgr:AddPane(notebook, wxaui.wxAuiPaneInfo():
|
||||
Name("stackpanel"):Float():
|
||||
MinSize(width/2,height/2):
|
||||
BestSize(width,height):FloatingSize(width,height):
|
||||
PinButton(true):Hide())
|
||||
mgr.defaultPerspective = mgr:SavePerspective() -- resave default perspective
|
||||
end
|
||||
|
||||
function DebuggerCreateWatchWindow()
|
||||
if (debugger.watchWindow) then return updateWatches() end
|
||||
local width = 360
|
||||
local watchWindow = wx.wxFrame(ide.frame, wx.wxID_ANY,
|
||||
TR("Watch Window"),
|
||||
wx.wxDefaultPosition, wx.wxSize(width, 200),
|
||||
wx.wxDEFAULT_FRAME_STYLE + wx.wxFRAME_FLOAT_ON_PARENT)
|
||||
|
||||
debugger.watchWindow = watchWindow
|
||||
|
||||
local watchMenu = wx.wxMenu{
|
||||
{ ID_ADDWATCH, TR("&Add Watch")..KSC(ID_ADDWATCH) },
|
||||
{ ID_EDITWATCH, TR("&Edit Watch")..KSC(ID_EDITWATCH) },
|
||||
{ ID_REMOVEWATCH, TR("&Remove Watch")..KSC(ID_REMOVEWATCH) },
|
||||
{ ID_EVALUATEWATCH, TR("Evaluate &Watches")..KSC(ID_EVALUATEWATCH) }}
|
||||
|
||||
local watchMenuBar = wx.wxMenuBar()
|
||||
watchMenuBar:Append(watchMenu, TR("&Watches"))
|
||||
watchWindow:SetMenuBar(watchMenuBar)
|
||||
|
||||
local watchCtrl = wx.wxListCtrl(watchWindow, wx.wxID_ANY,
|
||||
local function debuggerCreateWatchWindow()
|
||||
local watchCtrl = wx.wxListCtrl(frame, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wx.wxLC_REPORT + wx.wxLC_EDIT_LABELS)
|
||||
|
||||
@@ -757,9 +797,10 @@ function DebuggerCreateWatchWindow()
|
||||
info:SetWidth(width * 0.56)
|
||||
watchCtrl:InsertColumn(1, info)
|
||||
|
||||
watchWindow:CentreOnParent()
|
||||
SettingsRestoreFramePosition(watchWindow, "WatchWindow")
|
||||
watchWindow:Show(true)
|
||||
local watchMenu = wx.wxMenu{
|
||||
{ ID_ADDWATCH, TR("&Add Watch")..KSC(ID_ADDWATCH) },
|
||||
{ ID_EDITWATCH, TR("&Edit Watch")..KSC(ID_EDITWATCH) },
|
||||
{ ID_DELETEWATCH, TR("&Delete Watch")..KSC(ID_DELETEWATCH) }}
|
||||
|
||||
local function findSelectedWatchItem()
|
||||
local count = watchCtrl:GetSelectedItemCount()
|
||||
@@ -774,53 +815,47 @@ function DebuggerCreateWatchWindow()
|
||||
end
|
||||
|
||||
local defaultExpr = ""
|
||||
local function addWatch()
|
||||
local row = watchCtrl:InsertItem(watchCtrl:GetItemCount(), TR("Expr"))
|
||||
watchCtrl:SetItem(row, 0, defaultExpr)
|
||||
watchCtrl:SetItem(row, 1, TR("Value"))
|
||||
watchCtrl:EditLabel(row)
|
||||
end
|
||||
|
||||
watchWindow:Connect(wx.wxEVT_CLOSE_WINDOW,
|
||||
local function editWatch()
|
||||
local row = findSelectedWatchItem()
|
||||
if row >= 0 then watchCtrl:EditLabel(row) end
|
||||
end
|
||||
|
||||
local function deleteWatch()
|
||||
local row = findSelectedWatchItem()
|
||||
if row >= 0 then watchCtrl:DeleteItem(row) end
|
||||
end
|
||||
|
||||
watchCtrl:Connect(wx.wxEVT_CONTEXT_MENU,
|
||||
function (event)
|
||||
DebuggerCloseWatchWindow()
|
||||
watchWindow = nil
|
||||
watchCtrl = nil
|
||||
watchCtrl:PopupMenu(watchMenu)
|
||||
end)
|
||||
|
||||
watchCtrl:Connect(wx.wxEVT_KEY_DOWN,
|
||||
function (event)
|
||||
local keycode = event:GetKeyCode()
|
||||
if (keycode == wx.WXK_DELETE) then return deleteWatch()
|
||||
elseif (keycode == wx.WXK_INSERT) then return addWatch()
|
||||
elseif (keycode == wx.WXK_F2) then return editWatch()
|
||||
end
|
||||
event:Skip()
|
||||
end)
|
||||
|
||||
watchWindow:Connect(ID_ADDWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function ()
|
||||
local row = watchCtrl:InsertItem(watchCtrl:GetItemCount(), TR("Expr"))
|
||||
watchCtrl:SetItem(row, 0, defaultExpr)
|
||||
watchCtrl:SetItem(row, 1, TR("Value"))
|
||||
watchCtrl:EditLabel(row)
|
||||
end)
|
||||
watchCtrl:Connect(ID_ADDWATCH, wx.wxEVT_COMMAND_MENU_SELECTED, addWatch)
|
||||
|
||||
watchWindow:Connect(ID_EDITWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function ()
|
||||
local row = findSelectedWatchItem()
|
||||
if row >= 0 then
|
||||
watchCtrl:EditLabel(row)
|
||||
end
|
||||
end)
|
||||
watchWindow:Connect(ID_EDITWATCH, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable(watchCtrl:GetSelectedItemCount() > 0)
|
||||
end)
|
||||
watchCtrl:Connect(ID_EDITWATCH, wx.wxEVT_COMMAND_MENU_SELECTED, editWatch)
|
||||
watchCtrl:Connect(ID_EDITWATCH, wx.wxEVT_UPDATE_UI,
|
||||
function (event) event:Enable(watchCtrl:GetSelectedItemCount() > 0) end)
|
||||
|
||||
watchWindow:Connect(ID_REMOVEWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function ()
|
||||
local row = findSelectedWatchItem()
|
||||
if row >= 0 then
|
||||
watchCtrl:DeleteItem(row)
|
||||
end
|
||||
end)
|
||||
watchWindow:Connect(ID_REMOVEWATCH, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable(watchCtrl:GetSelectedItemCount() > 0)
|
||||
end)
|
||||
|
||||
watchWindow:Connect(ID_EVALUATEWATCH, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () updateWatches() end)
|
||||
watchWindow:Connect(ID_EVALUATEWATCH, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
event:Enable(watchCtrl:GetItemCount() > 0)
|
||||
end)
|
||||
watchCtrl:Connect(ID_DELETEWATCH, wx.wxEVT_COMMAND_MENU_SELECTED, deleteWatch)
|
||||
watchCtrl:Connect(ID_DELETEWATCH, wx.wxEVT_UPDATE_UI,
|
||||
function (event) event:Enable(watchCtrl:GetSelectedItemCount() > 0) end)
|
||||
|
||||
watchCtrl:Connect(wx.wxEVT_COMMAND_LIST_END_LABEL_EDIT,
|
||||
function (event)
|
||||
@@ -835,10 +870,37 @@ function DebuggerCreateWatchWindow()
|
||||
end
|
||||
event:Skip()
|
||||
end)
|
||||
|
||||
local notebook = wxaui.wxAuiNotebook(frame, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wxaui.wxAUI_NB_DEFAULT_STYLE + wxaui.wxAUI_NB_TAB_EXTERNAL_MOVE
|
||||
- wxaui.wxAUI_NB_CLOSE_ON_ACTIVE_TAB + wx.wxNO_BORDER)
|
||||
notebook:AddPage(watchCtrl, TR("Watch"), true)
|
||||
|
||||
local mgr = ide.frame.uimgr
|
||||
mgr:AddPane(notebook, wxaui.wxAuiPaneInfo():
|
||||
Name("watchpanel"):Float():
|
||||
MinSize(width/2,height/2):
|
||||
BestSize(width,height):FloatingSize(width,height):
|
||||
PinButton(true):Hide())
|
||||
mgr.defaultPerspective = mgr:SavePerspective() -- resave default perspective
|
||||
end
|
||||
|
||||
debuggerCreateStackWindow()
|
||||
debuggerCreateWatchWindow()
|
||||
|
||||
----------------------------------------------
|
||||
-- public api
|
||||
|
||||
DebuggerRefreshPanels = updateStackAndWatches
|
||||
|
||||
function DebuggerAddWatch(watch)
|
||||
if (not debugger.watchWindow) then DebuggerCreateWatchWindow() end
|
||||
local mgr = ide.frame.uimgr
|
||||
local pane = mgr:GetPane("watchpanel")
|
||||
if (not pane:IsShown()) then
|
||||
pane:Show()
|
||||
mgr:Update()
|
||||
end
|
||||
|
||||
local watchCtrl = debugger.watchCtrl
|
||||
-- check if this expression is already on the list
|
||||
@@ -853,6 +915,36 @@ function DebuggerAddWatch(watch)
|
||||
updateWatches(row)
|
||||
end
|
||||
|
||||
function DebuggerAttachDefault(options)
|
||||
debugger.options = options
|
||||
if (debugger.listening) then return end
|
||||
debugger.listen()
|
||||
end
|
||||
|
||||
function DebuggerShutdown()
|
||||
if debugger.server then debugger.terminate() end
|
||||
if debugger.pid then killClient() end
|
||||
end
|
||||
|
||||
function DebuggerStop()
|
||||
if (debugger.server) then
|
||||
debugger.server = nil
|
||||
debugger.pid = nil
|
||||
SetAllEditorsReadOnly(false)
|
||||
ShellSupportRemote(nil)
|
||||
ClearAllCurrentLineMarkers()
|
||||
DebuggerScratchpadOff()
|
||||
debuggerToggleViews(false)
|
||||
local lines = TR("traced %d instruction", debugger.stats.line):format(debugger.stats.line)
|
||||
DisplayOutputLn(TR("Debugging session completed (%s)."):format(lines))
|
||||
else
|
||||
-- it's possible that the application couldn't start, or that the
|
||||
-- debugger in the application didn't start, which means there is
|
||||
-- no debugger.server, but scratchpad may still be on. Turn it off.
|
||||
DebuggerScratchpadOff()
|
||||
end
|
||||
end
|
||||
|
||||
function DebuggerMakeFileName(editor, filePath)
|
||||
return filePath or ide.config.default.fullname
|
||||
end
|
||||
@@ -881,7 +973,6 @@ end
|
||||
|
||||
-- scratchpad functions
|
||||
|
||||
local function q(s) return s:gsub('([%(%)%.%%%+%-%*%?%[%^%$%]])','%%%1') end
|
||||
function DebuggerRefreshScratchpad()
|
||||
if debugger.scratchpad and debugger.scratchpad.updated and not debugger.scratchpad.paused then
|
||||
|
||||
|
||||
@@ -17,8 +17,7 @@ local projcombobox = ide.frame.projpanel.projcombobox
|
||||
-- Only update if the text has changed.
|
||||
local statusTextTable = { "OVR?", "R/O?", "Cursor Pos" }
|
||||
|
||||
-- set funclist font to be the same as the combobox in the project dropdown
|
||||
funclist:SetFont(ide.font.fNormal)
|
||||
funclist:SetFont(ide.font.dNormal)
|
||||
|
||||
local function updateStatusText(editor)
|
||||
local texts = { "", "", "" }
|
||||
@@ -151,6 +150,7 @@ function SetEditorSelection(selection)
|
||||
editor:SetSTCFocus(true)
|
||||
local id = editor:GetId()
|
||||
FileTreeMarkSelected(openDocuments[id] and openDocuments[id].filePath or '')
|
||||
AddToFileHistory(openDocuments[id] and openDocuments[id].filePath)
|
||||
else
|
||||
FileTreeMarkSelected('')
|
||||
end
|
||||
@@ -212,7 +212,12 @@ function EditorAutoComplete(editor)
|
||||
|
||||
local lt = linetx:sub(1,localpos)
|
||||
lt = lt:gsub("%s*(["..editor.spec.sep.."])%s*", "%1")
|
||||
lt = lt:match("[^%[%(%s]*$")
|
||||
-- strip closed brace scopes
|
||||
lt = lt:gsub("%b()","")
|
||||
lt = lt:gsub("%b[]","")
|
||||
lt = lt:gsub("%b{}","")
|
||||
-- match from starting brace
|
||||
lt = lt:match("[^%[%(%{%s]*$")
|
||||
|
||||
-- know now which string is to be completed
|
||||
local userList = CreateAutoCompList(editor,lt)
|
||||
@@ -300,6 +305,16 @@ function EditorCallTip(editor, pos, x, y)
|
||||
end
|
||||
end
|
||||
|
||||
function EditorIsModified(editor)
|
||||
local modified = false
|
||||
if editor then
|
||||
local id = editor:GetId()
|
||||
modified = openDocuments[id]
|
||||
and (openDocuments[id].isModified or not openDocuments[id].filePath)
|
||||
end
|
||||
return modified
|
||||
end
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Create an editor
|
||||
function CreateEditor()
|
||||
@@ -330,9 +345,15 @@ function CreateEditor()
|
||||
editor:SetWrapVisualFlagsLocation(wxstc.wxSTC_WRAPVISUALFLAGLOC_END_BY_TEXT)
|
||||
end
|
||||
|
||||
if (ide.config.editor.defaulteol == wxstc.wxSTC_EOL_CRLF
|
||||
or ide.config.editor.defaulteol == wxstc.wxSTC_EOL_LF) then
|
||||
editor:SetEOLMode(ide.config.editor.defaulteol)
|
||||
-- else: keep wxStyledTextCtrl default behavior (CRLF on Windows, LF on Unix)
|
||||
end
|
||||
|
||||
editor:SetCaretLineVisible(ide.config.editor.caretline and 1 or 0)
|
||||
|
||||
editor:SetVisiblePolicy(wxstc.wxSTC_VISIBLE_SLOP, 3)
|
||||
editor:SetVisiblePolicy(wxstc.wxSTC_VISIBLE_STRICT, 3)
|
||||
|
||||
editor:SetMarginWidth(0, editor:TextWidth(32, "99999_")) -- line # margin
|
||||
|
||||
@@ -351,9 +372,12 @@ function CreateEditor()
|
||||
editor:SetFoldFlags(wxstc.wxSTC_FOLDFLAG_LINEBEFORE_CONTRACTED +
|
||||
wxstc.wxSTC_FOLDFLAG_LINEAFTER_CONTRACTED)
|
||||
|
||||
editor:SetProperty("fold", "1")
|
||||
editor:SetProperty("fold.compact", "1")
|
||||
editor:SetProperty("fold.comment", "1")
|
||||
-- allow multiple selection and multi-cursor editing if supported
|
||||
if ide.wxver >= "2.9.5" then
|
||||
editor:SetMultipleSelection(1)
|
||||
editor:SetAdditionalCaretsBlink(1)
|
||||
editor:SetAdditionalSelectionTyping(1)
|
||||
end
|
||||
|
||||
do
|
||||
local fg, bg = wx.wxWHITE, wx.wxColour(128, 128, 128)
|
||||
@@ -377,6 +401,34 @@ function CreateEditor()
|
||||
editor:AutoCompStops([[ \n\t=-+():.,;*/!"'$%&~'#°^@?´`<>][|}{]])
|
||||
end
|
||||
|
||||
-- GotoPos should work by itself, but it doesn't (wx 2.9.5).
|
||||
-- This is likely because the editor window hasn't been refreshed yet,
|
||||
-- so its LinesOnScreen method returns 0/-1, which skews the calculations.
|
||||
-- To avoid this, the caret line is made visible at the first opportunity.
|
||||
do
|
||||
local redolater
|
||||
function editor:GotoPosDelayed(pos)
|
||||
local badtime = self:LinesOnScreen() <= 0 -- -1 on OSX, 0 on Windows
|
||||
if pos then
|
||||
if badtime then
|
||||
redolater = pos
|
||||
-- without this GotoPos the content is not scrolled correctly on
|
||||
-- Windows, but with this it's not scrolled correctly on OSX.
|
||||
if ide.osname ~= 'Macintosh' then self:GotoPos(pos) end
|
||||
else
|
||||
redolater = nil
|
||||
self:GotoPos(pos)
|
||||
end
|
||||
elseif not badtime and redolater then
|
||||
-- reset the left margin first to make sure that the position
|
||||
-- is set "from the left" to get the best content displayed.
|
||||
self:SetXOffset(0)
|
||||
self:GotoPos(redolater)
|
||||
redolater = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
editor.ev = {}
|
||||
editor:Connect(wxstc.wxEVT_STC_MARGINCLICK,
|
||||
function (event)
|
||||
@@ -398,17 +450,17 @@ function CreateEditor()
|
||||
|
||||
editor:Connect(wxstc.wxEVT_STC_MODIFIED,
|
||||
function (event)
|
||||
SetAutoRecoveryMark()
|
||||
|
||||
if (editor.assignscache and editor:GetCurrentLine() ~= editor.assignscache.line) then
|
||||
editor.assignscache = false
|
||||
end
|
||||
local evtype = event:GetModificationType()
|
||||
if (bit.band(evtype,wxstc.wxSTC_MOD_INSERTTEXT) ~= 0) then
|
||||
SetAutoRecoveryMark()
|
||||
table.insert(editor.ev,{event:GetPosition(),event:GetLinesAdded()})
|
||||
DynamicWordsAdd("post",editor,nil,editor:LineFromPosition(event:GetPosition()),event:GetLinesAdded())
|
||||
end
|
||||
if (bit.band(evtype,wxstc.wxSTC_MOD_DELETETEXT) ~= 0) then
|
||||
SetAutoRecoveryMark()
|
||||
table.insert(editor.ev,{event:GetPosition(),0})
|
||||
DynamicWordsAdd("post",editor,nil,editor:LineFromPosition(event:GetPosition()),0)
|
||||
end
|
||||
@@ -437,7 +489,7 @@ function CreateEditor()
|
||||
local localpos = pos-linestart
|
||||
local linetxtopos = linetx:sub(1,localpos)
|
||||
|
||||
if (ch == char_CR and eol==2) or (ch == char_LF and eol==0) then
|
||||
if (ch == char_LF) then
|
||||
if (line > 0) then
|
||||
local indent = editor:GetLineIndentation(line - 1)
|
||||
local linedone = editor:GetLine(line - 1)
|
||||
@@ -549,16 +601,33 @@ function CreateEditor()
|
||||
SetDocumentModified(editor:GetId(), true)
|
||||
end)
|
||||
|
||||
-- "updateStatusText" should be called in UPDATEUI event, but it creates
|
||||
-- several performance problems on Windows (using wx2.9.5+) when
|
||||
-- brackets or backspace is used (very slow screen repaint with 0.5s delay).
|
||||
-- Moving it to PAINTED event creates problems on OSX (using wx2.9.5+),
|
||||
-- where refresh of R/W and R/O status in the status bar is delayed.
|
||||
|
||||
editor:Connect(wxstc.wxEVT_STC_PAINTED,
|
||||
function ()
|
||||
if ide.osname == 'Windows' then updateStatusText(editor) end
|
||||
end)
|
||||
|
||||
editor:Connect(wxstc.wxEVT_STC_UPDATEUI,
|
||||
function ()
|
||||
updateStatusText(editor)
|
||||
if ide.osname ~= 'Windows' then updateStatusText(editor) end
|
||||
|
||||
editor:GotoPosDelayed()
|
||||
updateBraceMatch(editor)
|
||||
local minupdated
|
||||
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])
|
||||
if MarkupStyle then MarkupStyle(editor,line,line+iv[2]+1) end
|
||||
end
|
||||
if MarkupStyleRefresh then MarkupStyleRefresh(editor, editor.ev) end
|
||||
local firstline = editor:DocLineFromVisible(editor:GetFirstVisibleLine())
|
||||
local lastline = math.min(editor:GetLineCount(),
|
||||
editor:DocLineFromVisible(editor:GetFirstVisibleLine() + editor:LinesOnScreen()))
|
||||
MarkupStyle(editor,minupdated or firstline,lastline)
|
||||
editor.ev = {}
|
||||
end)
|
||||
|
||||
@@ -573,6 +642,16 @@ function CreateEditor()
|
||||
event:Skip()
|
||||
end)
|
||||
|
||||
if ide.config.editor.nomousezoom then
|
||||
-- disable zoom using mouse wheel as it triggers zooming when scrolling
|
||||
-- on OSX with kinetic scroll and then pressing CMD.
|
||||
editor:Connect(wx.wxEVT_MOUSEWHEEL,
|
||||
function (event)
|
||||
if wx.wxGetKeyState(wx.WXK_CONTROL) then return end
|
||||
event:Skip()
|
||||
end)
|
||||
end
|
||||
|
||||
local inhandler = false
|
||||
editor:Connect(wx.wxEVT_SET_FOCUS,
|
||||
function (event)
|
||||
@@ -586,23 +665,30 @@ function CreateEditor()
|
||||
editor:Connect(wx.wxEVT_KEY_DOWN,
|
||||
function (event)
|
||||
local keycode = event:GetKeyCode()
|
||||
local mod = event:GetModifiers()
|
||||
local first, last = 0, notebook:GetPageCount()-1
|
||||
if keycode == wx.WXK_ESCAPE and frame:IsFullScreen() then
|
||||
ShowFullScreen(false)
|
||||
elseif event:ControlDown() and
|
||||
(keycode == wx.WXK_PAGEUP or keycode == wx.WXK_TAB and event:ShiftDown()) then
|
||||
-- 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"
|
||||
and (mod == wx.wxMOD_RAW_CONTROL or mod == (wx.wxMOD_RAW_CONTROL + wx.wxMOD_SHIFT))
|
||||
and (keycode == wx.WXK_HOME or keycode == wx.WXK_END) then
|
||||
local pos = keycode == wx.WXK_HOME and 0 or editor:GetLength()
|
||||
if event:ShiftDown() -- mark selection and scroll to caret
|
||||
then editor:SetCurrentPos(pos) editor:EnsureCaretVisible()
|
||||
else editor:GotoPos(pos) end
|
||||
elseif mod == wx.wxMOD_RAW_CONTROL and keycode == wx.WXK_PAGEUP
|
||||
or mod == (wx.wxMOD_RAW_CONTROL + wx.wxMOD_SHIFT) and keycode == wx.WXK_TAB then
|
||||
if notebook:GetSelection() == first
|
||||
then notebook:SetSelection(last)
|
||||
else notebook:AdvanceSelection(false) end
|
||||
elseif event:ControlDown() and
|
||||
(keycode == wx.WXK_PAGEDOWN or keycode == wx.WXK_TAB) then
|
||||
elseif mod == wx.wxMOD_RAW_CONTROL
|
||||
and (keycode == wx.WXK_PAGEDOWN or keycode == wx.WXK_TAB) then
|
||||
if notebook:GetSelection() == last
|
||||
then notebook:SetSelection(first)
|
||||
else notebook:AdvanceSelection(true) end
|
||||
elseif (keycode == wx.WXK_DELETE or keycode == wx.WXK_BACK)
|
||||
-- ide.osname == 'Macintosh' has wx.wxMOD_NONE not defined
|
||||
-- for some reason (at least in wxlua 2.8.12.1)
|
||||
and (event:GetModifiers() == (wx.wxMOD_NONE or 0)) then
|
||||
and (mod == wx.wxMOD_NONE) then
|
||||
-- Delete and Backspace behave the same way for selected text
|
||||
if #(editor:GetSelectedText()) > 0 then
|
||||
editor:SetTargetStart(editor:GetSelectionStart())
|
||||
@@ -628,8 +714,12 @@ function CreateEditor()
|
||||
editor:SetTargetEnd(pos+1)
|
||||
end
|
||||
editor:ReplaceTarget("")
|
||||
elseif ide.osname == "Unix" and ide.wxver >= "2.9.5"
|
||||
and keycode == ('T'):byte() and mod == wx.wxMOD_CONTROL then
|
||||
ide.frame:AddPendingEvent(wx.wxCommandEvent(
|
||||
wx.wxEVT_COMMAND_MENU_SELECTED, ID_SHOWTOOLTIP))
|
||||
else
|
||||
if ide.osname == 'Macintosh' and event:CmdDown() then
|
||||
if ide.osname == 'Macintosh' and mod == wx.wxMOD_META then
|
||||
return -- ignore a key press if Command key is also pressed
|
||||
end
|
||||
event:Skip()
|
||||
@@ -640,13 +730,13 @@ function CreateEditor()
|
||||
editor:Connect(wx.wxEVT_CONTEXT_MENU,
|
||||
function (event)
|
||||
local menu = wx.wxMenu()
|
||||
menu:Append(wx.wxID_UNDO, TR("&Undo"))
|
||||
menu:Append(wx.wxID_REDO, TR("&Redo"))
|
||||
menu:Append(ID_UNDO, TR("&Undo"))
|
||||
menu:Append(ID_REDO, TR("&Redo"))
|
||||
menu:AppendSeparator()
|
||||
menu:Append(wx.wxID_CUT, TR("Cu&t"))
|
||||
menu:Append(wx.wxID_COPY, TR("&Copy"))
|
||||
menu:Append(wx.wxID_PASTE, TR("&Paste"))
|
||||
menu:Append(wx.wxID_SELECTALL, TR("Select &All"))
|
||||
menu:Append(ID_CUT, TR("Cu&t"))
|
||||
menu:Append(ID_COPY, TR("&Copy"))
|
||||
menu:Append(ID_PASTE, TR("&Paste"))
|
||||
menu:Append(ID_SELECTALL, TR("Select &All"))
|
||||
menu:AppendSeparator()
|
||||
menu:Append(ID_QUICKADDWATCH, TR("Add Watch Expression"))
|
||||
menu:Append(ID_QUICKEVAL, TR("Evaluate in Console"))
|
||||
@@ -686,7 +776,7 @@ function AddEditor(editor, name)
|
||||
local id = editor:GetId()
|
||||
local document = {}
|
||||
document.editor = editor
|
||||
document.index = notebook:GetSelection()
|
||||
document.index = notebook:GetPageIndex(editor)
|
||||
document.fileName = nil
|
||||
document.filePath = nil
|
||||
document.modTime = nil
|
||||
@@ -809,6 +899,17 @@ function SetupKeywords(editor, ext, forcespec, styles, font, fontitalic)
|
||||
editor.spec = ide.specs.none
|
||||
end
|
||||
|
||||
-- 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")
|
||||
|
||||
-- quickfix to prevent weird looks, otherwise need to update styling mechanism for cpp
|
||||
-- cpp "greyed out" styles are styleid + 64
|
||||
editor:SetProperty("lexer.cpp.track.preprocessor", "0")
|
||||
editor:SetProperty("lexer.cpp.update.preprocessor", "0")
|
||||
|
||||
StylesApplyToEditor(styles or ide.config.styles, editor,
|
||||
font or ide.font.eNormal,fontitalic or ide.font.eItalic,lexerstyleconvert)
|
||||
end
|
||||
@@ -816,42 +917,50 @@ end
|
||||
----------------------------------------------------
|
||||
-- function list for current file
|
||||
|
||||
-- wx.wxEVT_SET_FOCUS is not triggered for wxChoice on Mac (wx 2.8.12),
|
||||
-- so use wx.wxEVT_LEFT_DOWN instead
|
||||
funclist:Connect(ide.osname == 'Macintosh' and wx.wxEVT_LEFT_DOWN or wx.wxEVT_SET_FOCUS,
|
||||
function (event)
|
||||
event:Skip()
|
||||
local function refreshFunctionList(event)
|
||||
event:Skip()
|
||||
|
||||
local editor = GetEditor()
|
||||
if (editor and not (editor.spec and editor.spec.isfndef)) then return end
|
||||
local editor = GetEditor()
|
||||
if (editor and not (editor.spec and editor.spec.isfndef)) then return end
|
||||
|
||||
-- parse current file and update list
|
||||
-- first populate with the current label to minimize flicker
|
||||
-- then populate the list and update the label
|
||||
local current = funclist:GetCurrentSelection()
|
||||
local label = funclist:GetString(current)
|
||||
local default = funclist:GetString(0)
|
||||
funclist:Clear()
|
||||
funclist:Append(current ~= wx.wxNOT_FOUND and label or default, 0)
|
||||
funclist:SetSelection(0)
|
||||
-- parse current file and update list
|
||||
-- first populate with the current label to minimize flicker
|
||||
-- then populate the list and update the label
|
||||
local current = funclist:GetCurrentSelection()
|
||||
local label = funclist:GetString(current)
|
||||
local default = funclist:GetString(0)
|
||||
funclist:Clear()
|
||||
funclist:Append(current ~= wx.wxNOT_FOUND and label or default, 0)
|
||||
funclist:SetSelection(0)
|
||||
|
||||
local lines = 0
|
||||
local linee = (editor and editor:GetLineCount() or 0)-1
|
||||
for line=lines,linee do
|
||||
local tx = editor:GetLine(line)
|
||||
local s,_,cap,l = editor.spec.isfndef(tx)
|
||||
if (s) then
|
||||
local ls = editor:PositionFromLine(line)
|
||||
local style = bit.band(editor:GetStyleAt(ls+s),31)
|
||||
if not (editor.spec.iscomment[style] or editor.spec.isstring[style]) then
|
||||
funclist:Append((l and " " or "")..cap,line)
|
||||
end
|
||||
local lines = 0
|
||||
local linee = (editor and editor:GetLineCount() or 0)-1
|
||||
for line=lines,linee do
|
||||
local tx = editor:GetLine(line)
|
||||
local s,_,cap,l = editor.spec.isfndef(tx)
|
||||
if (s) then
|
||||
local ls = editor:PositionFromLine(line)
|
||||
local style = bit.band(editor:GetStyleAt(ls+s),31)
|
||||
if not (editor.spec.iscomment[style] or editor.spec.isstring[style]) then
|
||||
funclist:Append((l and " " or "")..cap,line)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
funclist:SetString(0, default)
|
||||
funclist:SetSelection(current ~= wx.wxNOT_FOUND and current or 0)
|
||||
end)
|
||||
funclist:SetString(0, default)
|
||||
funclist:SetSelection(current ~= wx.wxNOT_FOUND and current or 0)
|
||||
end
|
||||
|
||||
-- wx.wxEVT_SET_FOCUS is not triggered for wxChoice on Mac (wx 2.8.12),
|
||||
-- so use wx.wxEVT_LEFT_DOWN instead; none of the events are triggered for
|
||||
-- wxChoice on Linux (wx 2.9.5+), so use EVT_ENTER_WINDOW attached to the
|
||||
-- toolbar itself until something better is available.
|
||||
if ide.osname == 'Unix' then
|
||||
ide.frame.toolBar:Connect(wx.wxEVT_ENTER_WINDOW, refreshFunctionList)
|
||||
else
|
||||
local event = ide.osname == 'Macintosh' and wx.wxEVT_LEFT_DOWN or wx.wxEVT_SET_FOCUS
|
||||
funclist:Connect(event, refreshFunctionList)
|
||||
end
|
||||
|
||||
funclist:Connect(wx.wxEVT_COMMAND_CHOICE_SELECTED,
|
||||
function (event)
|
||||
|
||||
@@ -26,9 +26,13 @@ ide.filetree = {
|
||||
}
|
||||
local filetree = ide.filetree
|
||||
|
||||
local iscaseinsensitive = wx.wxFileName("A"):SameAs(wx.wxFileName("a"))
|
||||
|
||||
-- generic tree
|
||||
-- ------------
|
||||
|
||||
local IMG_DIRECTORY, IMG_FILE_KNOWN, IMG_FILE_OTHER = 0, 1, 2
|
||||
|
||||
do
|
||||
local getBitmap = (ide.app.createbitmap or wx.wxArtProvider.GetBitmap)
|
||||
local size = wx.wxSize(16, 16)
|
||||
@@ -37,51 +41,25 @@ do
|
||||
filetree.imglist:Add(getBitmap(wx.wxART_FOLDER, wx.wxART_OTHER, size))
|
||||
-- 1 = file known spec
|
||||
filetree.imglist:Add(getBitmap(wx.wxART_HELP_PAGE, wx.wxART_OTHER, size))
|
||||
-- 2 = file rest
|
||||
-- 2 = file other
|
||||
filetree.imglist:Add(getBitmap(wx.wxART_NORMAL_FILE, wx.wxART_OTHER, size))
|
||||
end
|
||||
|
||||
local function treeAddDir(tree,parent_id,rootdir)
|
||||
local item, cookie = tree:GetFirstChild(parent_id)
|
||||
local items = {}
|
||||
while true do
|
||||
if not item:IsOk() then break end
|
||||
local item, cookie = tree:GetFirstChild(parent_id)
|
||||
while item:IsOk() do
|
||||
items[tree:GetItemText(item) .. tree:GetItemImage(item)] = item
|
||||
item, cookie = tree:GetNextChild(parent_id, cookie)
|
||||
end
|
||||
|
||||
local cache = {}
|
||||
local curr
|
||||
local search = rootdir..string_Pathsep.."*"
|
||||
|
||||
-- append directories
|
||||
for _,dir in ipairs(FileSysGet(search,wx.wxDIR)) do
|
||||
local name = dir:match("%"..string_Pathsep.."("..stringset_File.."+)$")
|
||||
local icon = 0
|
||||
local item = items[name .. icon]
|
||||
if item then -- existing item
|
||||
-- keep deleting items until we find item
|
||||
while true do
|
||||
local next = curr and tree:GetNextSibling(curr)
|
||||
or tree:GetFirstChild(parent_id)
|
||||
if not next:IsOk() or name == tree:GetItemText(next) then
|
||||
curr = next
|
||||
break
|
||||
end
|
||||
tree:Delete(next)
|
||||
end
|
||||
else -- new item
|
||||
local dir_id = curr and tree:InsertItem(parent_id, curr, name, icon)
|
||||
or tree:PrependItem(parent_id, name, icon)
|
||||
tree:SetItemHasChildren(dir_id,FileSysHasContent(dir))
|
||||
curr = dir_id
|
||||
end
|
||||
end
|
||||
|
||||
-- then append files
|
||||
for _,file in ipairs(FileSysGet(search,wx.wxFILE)) do
|
||||
local name = file:match("%"..string_Pathsep.."("..stringset_File.."+)$")
|
||||
for _, file in ipairs(FileSysGetRecursive(rootdir)) do
|
||||
local name, dir = file:match("("..stringset_File.."+)("..string_Pathsep.."?)$")
|
||||
local known = GetSpec(GetFileExt(name))
|
||||
local icon = known and 1 or 2
|
||||
local icon = #dir>0 and IMG_DIRECTORY or known and IMG_FILE_KNOWN or IMG_FILE_OTHER
|
||||
local item = items[name .. icon]
|
||||
if item then -- existing item
|
||||
-- keep deleting items until we find item
|
||||
@@ -97,7 +75,9 @@ local function treeAddDir(tree,parent_id,rootdir)
|
||||
else -- new item
|
||||
curr = curr and tree:InsertItem(parent_id, curr, name, icon)
|
||||
or tree:PrependItem(parent_id, name, icon)
|
||||
if #dir>0 then tree:SetItemHasChildren(curr, FileSysHasContent(file)) end
|
||||
end
|
||||
if curr:IsOk() then cache[iscaseinsensitive and name:lower() or name] = curr end
|
||||
end
|
||||
|
||||
-- delete any leftovers (something that exists in the tree, but not on disk)
|
||||
@@ -108,6 +88,11 @@ local function treeAddDir(tree,parent_id,rootdir)
|
||||
tree:Delete(next)
|
||||
end
|
||||
|
||||
-- cache the mapping from names to tree items
|
||||
local data = wx.wxLuaTreeItemData()
|
||||
data:SetData(cache)
|
||||
tree:SetItemData(parent_id, data)
|
||||
|
||||
tree:SetItemHasChildren(parent_id,
|
||||
tree:GetChildrenCount(parent_id, false) > 0)
|
||||
end
|
||||
@@ -118,10 +103,11 @@ local function treeGetItemFullName(tree,treedata,item_id)
|
||||
|
||||
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 separate, normalize the path
|
||||
-- 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()
|
||||
@@ -135,25 +121,34 @@ local function treeSetRoot(tree,treedata,rootdir)
|
||||
return
|
||||
end
|
||||
|
||||
local root_id = tree:AddRoot(rootdir,0)
|
||||
local root_id = tree:AddRoot(rootdir, IMG_DIRECTORY)
|
||||
treedata.root_id = root_id
|
||||
treedata.rootdir = rootdir
|
||||
|
||||
treeAddDir(tree,root_id,rootdir)
|
||||
filetree.newfiledir = rootdir
|
||||
|
||||
tree:Expand(root_id)
|
||||
-- make sure that the item can expand
|
||||
tree:SetItemHasChildren(root_id, true)
|
||||
tree:Expand(root_id) -- this will also populate the tree
|
||||
end
|
||||
|
||||
local function treeSetConnectorsAndIcons(tree,treedata)
|
||||
tree:SetImageList(filetree.imglist)
|
||||
|
||||
local function refreshAncestors(node)
|
||||
while node:IsOk() do
|
||||
local dir = treeGetItemFullName(tree,treedata,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)
|
||||
treeAddDir(tree,item_id,dir)
|
||||
|
||||
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,
|
||||
@@ -161,21 +156,14 @@ local function treeSetConnectorsAndIcons(tree,treedata)
|
||||
tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
|
||||
function( event )
|
||||
local item_id = event:GetItem()
|
||||
|
||||
local name = treeGetItemFullName(tree,treedata,item_id)
|
||||
-- refresh the folder
|
||||
if (tree:GetItemImage(item_id) == 0) then
|
||||
if wx.wxFileName(name):DirExists() then
|
||||
treeAddDir(tree,item_id,name) -- refresh the content
|
||||
else -- stale filetree information; rescan
|
||||
treeAddDir(tree,tree:GetItemParent(item_id),name)
|
||||
end
|
||||
if (tree:GetItemImage(item_id) == IMG_DIRECTORY) then
|
||||
if wx.wxDirExists(name) then treeAddDir(tree,item_id,name)
|
||||
else refreshAncestors(tree:GetItemParent(item_id)) end -- stale content
|
||||
else -- open file
|
||||
if wx.wxFileName(name):FileExists() then
|
||||
LoadFile(name,nil,true)
|
||||
else -- stale filetree information; rescan
|
||||
treeAddDir(tree,tree:GetItemParent(item_id),name)
|
||||
end
|
||||
if wx.wxFileExists(name) then LoadFile(name,nil,true)
|
||||
else refreshAncestors(tree:GetItemParent(item_id)) end -- stale content
|
||||
end
|
||||
end)
|
||||
-- toggle a folder on
|
||||
@@ -183,7 +171,7 @@ local function treeSetConnectorsAndIcons(tree,treedata)
|
||||
function( event )
|
||||
local item_id = tree:HitTest(event:GetPosition())
|
||||
-- only toggle if this is a folder and the click is on the label
|
||||
if item_id and tree:GetItemImage(item_id) == 0 then
|
||||
if item_id and tree:GetItemImage(item_id) == IMG_DIRECTORY then
|
||||
tree:Toggle(item_id)
|
||||
tree:SelectItem(item_id)
|
||||
else
|
||||
@@ -229,12 +217,19 @@ projpanel:SetSizer(projSizer)
|
||||
-- proj connectors
|
||||
-- ---------------
|
||||
|
||||
local inupdate = false
|
||||
local function projcomboboxUpdate(event)
|
||||
if inupdate then return end
|
||||
local cur = projcombobox:GetValue()
|
||||
local fn = wx.wxFileName(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)
|
||||
inupdate = false
|
||||
end
|
||||
|
||||
projpanel:Connect(ID "filetree.proj.drivecb", wx.wxEVT_COMMAND_COMBOBOX_SELECTED, projcomboboxUpdate)
|
||||
@@ -246,11 +241,13 @@ treeSetConnectorsAndIcons(projtree,filetree.projdata)
|
||||
-- ---------------
|
||||
|
||||
function filetree:updateProjectDir(newdir, cboxsel)
|
||||
if (newdir and newdir:sub(-3,-2) == string_Pathsep) then
|
||||
newdir = newdir:sub(0,-2)
|
||||
end
|
||||
if (not newdir) or not wx.wxDirExists(newdir) then return end
|
||||
local dirname = wx.wxFileName.DirName(newdir)
|
||||
|
||||
if ((not newdir) or filetree.projdirText == newdir or not wx.wxDirExists(newdir)) then return end
|
||||
if filetree.projdirText and #filetree.projdirText > 0
|
||||
and dirname:SameAs(wx.wxFileName.DirName(filetree.projdirText)) 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)
|
||||
@@ -285,8 +282,8 @@ projpanel.projcombobox = projcombobox
|
||||
projpanel.projtree = projtree
|
||||
|
||||
function FileTreeGetDir()
|
||||
return projpanel:IsShown() and filetree.newfiledir
|
||||
and wx.wxFileName.DirName(filetree.newfiledir):GetFullPath()
|
||||
return projpanel:IsShown() and filetree.projdata.rootdir
|
||||
and wx.wxFileName.DirName(filetree.projdata.rootdir):GetFullPath()
|
||||
end
|
||||
|
||||
function FileTreeSetProjects(tab)
|
||||
@@ -304,21 +301,33 @@ local function findItem(tree, match)
|
||||
local node = projtree:GetRootItem()
|
||||
local label = tree:GetItemText(node)
|
||||
|
||||
local s, e = string.find(match, label, 1, true)
|
||||
local s, e
|
||||
if iscaseinsensitive then
|
||||
s, e = string.find(match:lower(), label:lower(), 1, true)
|
||||
else
|
||||
s, e = string.find(match, label, 1, true)
|
||||
end
|
||||
if not s or s ~= 1 then return end
|
||||
|
||||
for token in string.gmatch(string.sub(match,e+1), "[^%"..string_Pathsep.."]+") do
|
||||
local dir = treeGetItemFullName(tree,filetree.projdata,node)
|
||||
treeAddDir(tree,node,dir)
|
||||
local 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)
|
||||
treeAddDir(tree,node,dir)
|
||||
|
||||
local item, cookie = tree:GetFirstChild(node)
|
||||
while true do
|
||||
if not item:IsOk() then return end -- not found
|
||||
if tree:GetItemText(item) == token then
|
||||
node = item
|
||||
break
|
||||
local item, cookie = tree:GetFirstChild(node)
|
||||
while true do
|
||||
if not item:IsOk() then return end -- not found
|
||||
if tree:GetItemText(item) == token then
|
||||
node = item
|
||||
break
|
||||
end
|
||||
item, cookie = tree:GetNextChild(node, cookie)
|
||||
end
|
||||
item, cookie = tree:GetNextChild(node, cookie)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -345,10 +354,12 @@ function FileTreeMarkSelected(file)
|
||||
end
|
||||
if item_id then
|
||||
projtree:EnsureVisible(item_id)
|
||||
projtree:SetScrollPos(wx.wxHORIZONTAL, 0, true)
|
||||
projtree:SetItemBold(item_id, true)
|
||||
end
|
||||
curr_file = file
|
||||
projtree:Refresh() -- to force refresh on Mac (ide.osname == 'Macintosh')
|
||||
if ide.wxver < "2.9.5" and ide.osname == 'Macintosh' then
|
||||
projtree:Refresh() end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -53,19 +53,23 @@ local function setSearchFlags(editor)
|
||||
editor:SetSearchFlags(flags)
|
||||
end
|
||||
|
||||
local function setTarget(editor, fDown, fInclude)
|
||||
local function setTarget(editor, fDown, fAll, fWrap)
|
||||
local selStart = editor:GetSelectionStart()
|
||||
local selEnd = editor:GetSelectionEnd()
|
||||
local len = editor:GetLength()
|
||||
local s, e
|
||||
if fDown then
|
||||
e= len
|
||||
s = iff(fInclude, selStart, selEnd +1)
|
||||
s = iff(fAll, selStart, selEnd)
|
||||
e = len
|
||||
else
|
||||
s = 0
|
||||
e = iff(fInclude, selEnd, selStart-1)
|
||||
e = iff(fAll, selEnd, selStart)
|
||||
end
|
||||
if not fDown and not fInclude then s, e = e, s end
|
||||
-- if going up and not search/replace All, then switch the range to
|
||||
-- allow the next match to be properly marked
|
||||
if not fDown and not fAll then s, e = e, s end
|
||||
-- if wrap around and search all requested, then search the entire document
|
||||
if fAll and fWrap then s, e = 0, len end
|
||||
editor:SetTargetStart(s)
|
||||
editor:SetTargetEnd(e)
|
||||
return e
|
||||
@@ -92,17 +96,33 @@ function findReplace:GetSelectedString()
|
||||
local endSel = editor:GetSelectionEnd()
|
||||
if (startSel ~= endSel) and (editor:LineFromPosition(startSel) == editor:LineFromPosition(endSel)) then
|
||||
findReplace.findText = editor:GetSelectedText()
|
||||
findReplace.foundString = true
|
||||
return true
|
||||
end
|
||||
end
|
||||
return editor and findReplace.foundString
|
||||
return false
|
||||
end
|
||||
|
||||
local function shake(window, shakes, duration, vigour)
|
||||
shakes = shakes or 4
|
||||
duration = duration or 0.5
|
||||
vigour = vigour or 0.05
|
||||
|
||||
local delay = math.floor(duration/shakes/2)
|
||||
local position = window:GetPosition() -- get current position
|
||||
local deltax = window:GetSize():GetWidth()*vigour
|
||||
for s = 1, shakes do
|
||||
window:Move(position:GetX()-deltax, position:GetY())
|
||||
wx.wxMilliSleep(delay)
|
||||
window:Move(position:GetX()+deltax, position:GetY())
|
||||
wx.wxMilliSleep(delay)
|
||||
end
|
||||
window:Move(position) -- restore position
|
||||
end
|
||||
|
||||
function findReplace:FindString(reverse)
|
||||
if findReplace:HasText() then
|
||||
local editor = findReplace:GetEditor()
|
||||
local fDown = iff(reverse, not findReplace.fDown, findReplace.fDown)
|
||||
local lenFind = string.len(findReplace.findText)
|
||||
setSearchFlags(editor)
|
||||
setTarget(editor, fDown)
|
||||
local posFind = editor:SearchInTarget(findReplace.findText)
|
||||
@@ -113,13 +133,15 @@ function findReplace:FindString(reverse)
|
||||
end
|
||||
if posFind == -1 then
|
||||
findReplace.foundString = false
|
||||
ide.frame:SetStatusText("Text not found.")
|
||||
ide.frame:SetStatusText(TR("Text not found."))
|
||||
shake(findReplace.dialog)
|
||||
else
|
||||
findReplace.foundString = true
|
||||
local start = editor:GetTargetStart()
|
||||
local finish = editor:GetTargetEnd()
|
||||
EnsureRangeVisible(start, finish)
|
||||
editor:SetSelection(start, finish)
|
||||
ide.frame:SetStatusText("")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -157,34 +179,40 @@ end
|
||||
-- registers every position item was found
|
||||
-- supposed for "Search/Replace in Files"
|
||||
|
||||
function findReplace:ReplaceString(fReplaceAll,inFileRegister)
|
||||
function findReplace:ReplaceString(fReplaceAll, inFileRegister)
|
||||
local replaced = false
|
||||
|
||||
if findReplace:HasText() then
|
||||
local replaceLen = string.len(findReplace.replaceText)
|
||||
local findLen = string.len(findReplace.findText)
|
||||
local editor = findReplace:GetEditor()
|
||||
local endTarget = inFileRegister and setTargetAll(editor) or
|
||||
setTarget(editor, findReplace.fDown, fReplaceAll)
|
||||
setTarget(editor, findReplace.fDown, fReplaceAll, findReplace.fWrap)
|
||||
|
||||
if fReplaceAll then
|
||||
setSearchFlags(editor)
|
||||
local occurrences = 0
|
||||
local posFind = editor:SearchInTarget(findReplace.findText)
|
||||
if (posFind ~= -1) then
|
||||
if(not inFileRegister) then editor:BeginUndoAction() end
|
||||
if (not inFileRegister) then editor:BeginUndoAction() end
|
||||
while posFind ~= -1 do
|
||||
if(inFileRegister) then inFileRegister(posFind) end
|
||||
if (inFileRegister) then inFileRegister(posFind) end
|
||||
|
||||
local length = editor:GetLength()
|
||||
editor:ReplaceTarget(findReplace.replaceText)
|
||||
editor:SetTargetStart(posFind + replaceLen)
|
||||
endTarget = endTarget + replaceLen - findLen
|
||||
-- adjust the endTarget as the position could have changed;
|
||||
-- can't simply subtract findText length as it could be a regexp
|
||||
endTarget = endTarget + (editor:GetLength() - length)
|
||||
editor:SetTargetEnd(endTarget)
|
||||
posFind = editor:SearchInTarget(findReplace.findText)
|
||||
occurrences = occurrences + 1
|
||||
end
|
||||
if(not inFileRegister) then editor:EndUndoAction() end
|
||||
if (not inFileRegister) then editor:EndUndoAction() end
|
||||
|
||||
replaced = true
|
||||
end
|
||||
ide.frame:SetStatusText(("%s %s."):format(
|
||||
TR("Replaced"), TR("%d instance", occurrences):format(occurrences)))
|
||||
else
|
||||
if findReplace.foundString then
|
||||
local start = editor:GetSelectionStart()
|
||||
@@ -206,22 +234,17 @@ local function onFileRegister(pos)
|
||||
local line = editor:LineFromPosition(pos)
|
||||
local linepos = pos - editor:PositionFromLine(line)
|
||||
local result = "("..(line+1)..","..(linepos+1).."): "..editor:GetLine(line)
|
||||
DisplayOutput(findReplace.curfilename..result)
|
||||
DisplayOutputLn(findReplace.curfilename..result:gsub("\r?\n$",""))
|
||||
findReplace.occurrences = findReplace.occurrences + 1
|
||||
end
|
||||
|
||||
local function ProcInFiles(startdir,mask,subdirs,replace)
|
||||
if (subdirs) then
|
||||
local dirs = FileSysGet(startdir..string_Pathsep.."*",wx.wxDIR)
|
||||
for _,dir in ipairs(dirs) do
|
||||
ProcInFiles(dir,mask,true,replace)
|
||||
end
|
||||
end
|
||||
|
||||
local files = FileSysGet(startdir..string_Pathsep..mask,wx.wxFILE)
|
||||
local files = FileSysGetRecursive(startdir,subdirs,mask)
|
||||
for _,file in ipairs(files) do
|
||||
-- ignore .bak files when replacing and asked to store .bak files
|
||||
if not (replace and findReplace.fMakeBak and file:find('.bak$')) then
|
||||
-- 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
|
||||
|
||||
local filetext = FileRead(file)
|
||||
@@ -251,38 +274,51 @@ function findReplace:RunInFiles(replace)
|
||||
wx.wxDefaultPosition, wx.wxSize(1,1), wx.wxBORDER_STATIC)
|
||||
findReplace.occurrences = 0
|
||||
|
||||
local fname = wx.wxFileName(findReplace.filedirText)
|
||||
local startdir = findReplace.filedirText
|
||||
DisplayOutput("FindInFiles: "..(replace and "Replacing" or "Searching for").." '"..findReplace.findText.."'.\n")
|
||||
DisplayOutputLn(("%s '%s'."):format(
|
||||
(replace and TR("Replacing") or TR("Searching for")),
|
||||
findReplace.findText))
|
||||
|
||||
ProcInFiles(startdir, findReplace.filemaskText, findReplace.fSubDirs, replace)
|
||||
|
||||
DisplayOutput("FindInFiles: "..findReplace.occurrences.." instance(s) have been "..
|
||||
(replace and "replaced" or "found")..".\n")
|
||||
DisplayOutputLn(("%s %s."):format(
|
||||
(replace and TR("Replaced") or TR("Found")),
|
||||
TR("%d instance", findReplace.occurrences):format(findReplace.occurrences)))
|
||||
|
||||
findReplace.oveditor = nil
|
||||
end
|
||||
|
||||
local function createFindReplaceDialog(replace,infiles)
|
||||
function findReplace:createDialog(replace,infiles)
|
||||
local ID_FIND_NEXT = 1
|
||||
local ID_REPLACE = 2
|
||||
local ID_REPLACE_ALL = 3
|
||||
local ID_SETDIR = 4
|
||||
|
||||
local mac = ide.osname == 'Macintosh'
|
||||
|
||||
local findReplace = self
|
||||
|
||||
local position = wx.wxDefaultPosition
|
||||
if findReplace.dialog then
|
||||
-- grab current position before destroying the dialog
|
||||
position = findReplace.dialog:GetPosition()
|
||||
findReplace.dialog:Destroy()
|
||||
end
|
||||
|
||||
local findDialog = wx.wxDialog(ide.frame, wx.wxID_ANY, infiles and TR("Find In Files") or TR("Find"),
|
||||
position, wx.wxDefaultSize, wx.wxDEFAULT_DIALOG_STYLE)
|
||||
|
||||
findReplace.replace = replace
|
||||
findReplace.infiles = infiles
|
||||
|
||||
local findDialog = wx.wxDialog(ide.frame, wx.wxID_ANY, infiles and "Find In Files" or "Find",
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxDEFAULT_DIALOG_STYLE)
|
||||
|
||||
-- Create right hand buttons and sizer
|
||||
local findButton = wx.wxButton(findDialog, ID_FIND_NEXT, infiles and "&Find All" or "&Find Next")
|
||||
findButton:SetDefault()
|
||||
local replaceButton = wx.wxButton(findDialog, ID_REPLACE, infiles and replace and "&Replace All" or "&Replace")
|
||||
local findButton = wx.wxButton(findDialog, ID_FIND_NEXT, infiles and TR("&Find All") or TR("&Find Next"))
|
||||
local replaceButton = wx.wxButton(findDialog, ID_REPLACE, infiles and replace and TR("&Replace All") or TR("&Replace"))
|
||||
local replaceAllButton = nil
|
||||
if (replace and not infiles) then
|
||||
replaceAllButton = wx.wxButton(findDialog, ID_REPLACE_ALL, "Replace &All")
|
||||
replaceAllButton = wx.wxButton(findDialog, ID_REPLACE_ALL, TR("Replace &All"))
|
||||
end
|
||||
local cancelButton = wx.wxButton(findDialog, wx.wxID_CANCEL, "Cancel")
|
||||
local cancelButton = wx.wxButton(findDialog, wx.wxID_CANCEL, TR("Cancel"))
|
||||
|
||||
local buttonsSizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||
buttonsSizer:Add(findButton, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 3)
|
||||
@@ -293,15 +329,16 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
buttonsSizer:Add(cancelButton, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 3)
|
||||
|
||||
-- Create find/replace text entry sizer
|
||||
local findStatText = wx.wxStaticText( findDialog, wx.wxID_ANY, "Find: ")
|
||||
local findStatText = wx.wxStaticText(findDialog, wx.wxID_ANY, TR("Find")..": ")
|
||||
local findTextCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.findText,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.findTextArray, wx.wxCB_DROPDOWN)
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.findTextArray,
|
||||
wx.wxCB_DROPDOWN + (mac and wx.wxTE_PROCESS_ENTER or 0))
|
||||
findTextCombo:SetFocus()
|
||||
|
||||
local infilesMaskStat,infilesMaskCombo
|
||||
local infilesDirStat,infilesDirCombo,infilesDirButton
|
||||
if (infiles) then
|
||||
infilesMaskStat = wx.wxStaticText( findDialog, wx.wxID_ANY, "File Type: ")
|
||||
infilesMaskStat = wx.wxStaticText(findDialog, wx.wxID_ANY, TR("File Type")..": ")
|
||||
infilesMaskCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.filemaskText,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.filemaskTextArray)
|
||||
|
||||
@@ -310,15 +347,18 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
findReplace.filedirText = fname:GetPath(wx.wxPATH_GET_VOLUME)
|
||||
end
|
||||
|
||||
infilesDirStat = wx.wxStaticText( findDialog, wx.wxID_ANY, "Directory: ")
|
||||
infilesDirCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.filedirText, wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.filedirTextArray)
|
||||
infilesDirStat = wx.wxStaticText(findDialog, wx.wxID_ANY, TR("Directory")..": ")
|
||||
infilesDirCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.filedirText,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.filedirTextArray)
|
||||
infilesDirButton = wx.wxButton(findDialog, ID_SETDIR, "...",wx.wxDefaultPosition, wx.wxSize(26,20))
|
||||
end
|
||||
|
||||
local replaceStatText, replaceTextCombo
|
||||
if (replace) then
|
||||
replaceStatText = wx.wxStaticText( findDialog, wx.wxID_ANY, "Replace: ")
|
||||
replaceTextCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.replaceText, wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.replaceTextArray)
|
||||
replaceStatText = wx.wxStaticText(findDialog, wx.wxID_ANY, TR("Replace")..": ")
|
||||
replaceTextCombo = wx.wxComboBox(findDialog, wx.wxID_ANY, findReplace.replaceText,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, findReplace.replaceTextArray,
|
||||
wx.wxCB_DROPDOWN + (mac and wx.wxTE_PROCESS_ENTER or 0))
|
||||
end
|
||||
|
||||
local findReplaceSizer = wx.wxFlexGridSizer(2, 3, 0, 0)
|
||||
@@ -345,13 +385,13 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
-- the StaticBox(Sizer) needs to be created before checkboxes, otherwise
|
||||
-- checkboxes don't get any clicks on OSX (ide.osname == 'Macintosh')
|
||||
-- as the z-order for event traversal appears to be incorrect.
|
||||
local optionsSizer = wx.wxStaticBoxSizer(wx.wxVERTICAL, findDialog, "Options" )
|
||||
local optionsSizer = wx.wxStaticBoxSizer(wx.wxVERTICAL, findDialog, TR("Options"))
|
||||
|
||||
-- Create find/replace option checkboxes
|
||||
local wholeWordCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Match &whole word")
|
||||
local matchCaseCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Match &case")
|
||||
local wrapAroundCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Wrap ar&ound")
|
||||
local regexCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "Regular &expression")
|
||||
local wholeWordCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, TR("Match &whole word"))
|
||||
local matchCaseCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, TR("Match &case"))
|
||||
local wrapAroundCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, TR("Wrap ar&ound"))
|
||||
local regexCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, TR("Regular &expression"))
|
||||
wholeWordCheckBox:SetValue(findReplace.fWholeWord)
|
||||
matchCaseCheckBox:SetValue(findReplace.fMatchCase)
|
||||
wrapAroundCheckBox:SetValue(findReplace.fWrap)
|
||||
@@ -373,10 +413,10 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
local scopeSizer
|
||||
if (infiles) then
|
||||
-- the StaticBox(Sizer) needs to be created before checkboxes
|
||||
scopeSizer = wx.wxStaticBoxSizer(wx.wxVERTICAL, findDialog, "In Files")
|
||||
scopeSizer = wx.wxStaticBoxSizer(wx.wxVERTICAL, findDialog, TR("In Files"))
|
||||
|
||||
subDirCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, "&Subdirectories")
|
||||
makeBakCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, ".&bak on Replace")
|
||||
subDirCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, TR("&Subdirectories"))
|
||||
makeBakCheckBox = wx.wxCheckBox(findDialog, wx.wxID_ANY, TR(".&bak on Replace"))
|
||||
subDirCheckBox:SetValue(findReplace.fSubDirs)
|
||||
makeBakCheckBox:SetValue(findReplace.fMakeBak)
|
||||
|
||||
@@ -386,7 +426,8 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
|
||||
scopeSizer:Add(optionSizer, 0, 0, 5)
|
||||
else
|
||||
scopeRadioBox = wx.wxRadioBox(findDialog, wx.wxID_ANY, "Scope", wx.wxDefaultPosition, wx.wxDefaultSize, {"&Up", "&Down"}, 1, wx.wxRA_SPECIFY_COLS)
|
||||
scopeRadioBox = wx.wxRadioBox(findDialog, wx.wxID_ANY, TR("Scope"), wx.wxDefaultPosition,
|
||||
wx.wxDefaultSize, {TR("&Up"), TR("&Down")}, 1, wx.wxRA_SPECIFY_COLS)
|
||||
scopeRadioBox:SetSelection(iff(findReplace.fDown, 1, 0))
|
||||
|
||||
scopeSizer = wx.wxBoxSizer(wx.wxVERTICAL, findDialog)
|
||||
@@ -406,7 +447,7 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
mainSizer:Add(leftSizer, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 10)
|
||||
mainSizer:Add(buttonsSizer, 0, wx.wxALL + wx.wxGROW + wx.wxCENTER, 10)
|
||||
|
||||
mainSizer:SetSizeHints( findDialog )
|
||||
mainSizer:SetSizeHints(findDialog)
|
||||
findDialog:SetSizer(mainSizer)
|
||||
|
||||
local function TransferDataFromWindow()
|
||||
@@ -437,12 +478,26 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
return true
|
||||
end
|
||||
|
||||
-- this is a workaround for Enter issue in wxComboBox on OSX:
|
||||
-- https://groups.google.com/d/msg/wx-users/EVJr8GqyNUA/CUALp585E78J
|
||||
if (mac and ide.wxver >= "2.9.5") then
|
||||
local function simulateEnter()
|
||||
findDialog:AddPendingEvent(wx.wxCommandEvent(
|
||||
wx.wxEVT_COMMAND_BUTTON_CLICKED, ID_FIND_NEXT))
|
||||
end
|
||||
findTextCombo:Connect(wx.wxEVT_COMMAND_TEXT_ENTER, simulateEnter)
|
||||
if replace then
|
||||
replaceTextCombo:Connect(wx.wxEVT_COMMAND_TEXT_ENTER, simulateEnter)
|
||||
end
|
||||
end
|
||||
|
||||
findDialog:Connect(ID_FIND_NEXT, wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
function()
|
||||
TransferDataFromWindow()
|
||||
if (findReplace.infiles) then
|
||||
findReplace:RunInFiles()
|
||||
findReplace.dialog:Destroy()
|
||||
findReplace.dialog = nil
|
||||
else
|
||||
findReplace:FindString()
|
||||
end
|
||||
@@ -456,13 +511,12 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
if (findReplace.infiles) then
|
||||
findReplace:RunInFiles(true)
|
||||
findReplace.dialog:Destroy()
|
||||
findReplace.dialog = nil
|
||||
else
|
||||
findReplace:ReplaceString()
|
||||
end
|
||||
else
|
||||
findReplace.dialog:Destroy()
|
||||
findReplace.dialog = createFindReplaceDialog(true,infiles)
|
||||
findReplace.dialog:Show(true)
|
||||
findReplace:createDialog(true,infiles)
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -478,7 +532,7 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
if infilesDirButton then
|
||||
findDialog:Connect(ID_SETDIR, wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
function()
|
||||
local filePicker = wx.wxDirDialog(findDialog, "Choose a project directory",
|
||||
local filePicker = wx.wxDirDialog(findDialog, TR("Choose a project directory"),
|
||||
findReplace.filedirText~="" and findReplace.filedirText or wx.wxGetCwd(),wx.wxFLP_USE_TEXTCTRL)
|
||||
|
||||
local res = filePicker:ShowModal(true)
|
||||
@@ -486,22 +540,26 @@ local function createFindReplaceDialog(replace,infiles)
|
||||
infilesDirCombo:SetValue(filePicker:GetPath())
|
||||
end
|
||||
end)
|
||||
|
||||
end
|
||||
|
||||
findDialog:Connect(wx.wxID_ANY, wx.wxEVT_CLOSE_WINDOW,
|
||||
function (event)
|
||||
TransferDataFromWindow()
|
||||
event:Skip()
|
||||
findDialog:Show(false)
|
||||
findDialog:Destroy()
|
||||
end)
|
||||
-- if on OSX then select the current value of the default dropdown
|
||||
-- and don't set the default as it doesn't make Enter to work, but
|
||||
-- prevents associated hotkey (Cmd-F) from working (wx2.9.5).
|
||||
if ide.osname == 'Macintosh' then
|
||||
findTextCombo:SetSelection(0, #findTextCombo:GetValue())
|
||||
else
|
||||
findButton:SetDefault()
|
||||
end
|
||||
|
||||
-- reset search when re-creating dialog to avoid modifying selected
|
||||
-- fragment after successful search and updated replacement
|
||||
findReplace.foundString = false
|
||||
findReplace.dialog = findDialog
|
||||
findDialog:Show(true)
|
||||
return findDialog
|
||||
end
|
||||
|
||||
function findReplace:Show(replace,infiles)
|
||||
self.dialog = nil
|
||||
self.dialog = createFindReplaceDialog(replace,infiles)
|
||||
self.dialog:Show(true)
|
||||
self:GetSelectedString()
|
||||
self:createDialog(replace,infiles)
|
||||
end
|
||||
|
||||
@@ -4,22 +4,30 @@
|
||||
local ide = ide
|
||||
|
||||
-- Pick some reasonable fixed width fonts to use for the editor
|
||||
local function setFont(style, config, name, size)
|
||||
local function setFont(style, config)
|
||||
return wx.wxFont(config.fontsize or size or 10, wx.wxFONTFAMILY_MODERN, style,
|
||||
wx.wxFONTWEIGHT_NORMAL, false, config.fontname or name,
|
||||
wx.wxFONTWEIGHT_NORMAL, false, config.fontname or "",
|
||||
config.fontencoding or wx.wxFONTENCODING_DEFAULT)
|
||||
end
|
||||
ide.font.eNormal = setFont(wx.wxFONTSTYLE_NORMAL, ide.config.editor, wx.__WXMSW__ and "Courier New" or "")
|
||||
ide.font.eItalic = setFont(wx.wxFONTSTYLE_ITALIC, ide.config.editor, wx.__WXMSW__ and "Courier New" or "")
|
||||
ide.font.eNormal = setFont(wx.wxFONTSTYLE_NORMAL, ide.config.editor)
|
||||
ide.font.eItalic = setFont(wx.wxFONTSTYLE_ITALIC, ide.config.editor)
|
||||
|
||||
ide.font.oNormal = setFont(wx.wxFONTSTYLE_NORMAL, ide.config.outputshell, wx.__WXMSW__ and "Courier New" or "")
|
||||
ide.font.oItalic = setFont(wx.wxFONTSTYLE_ITALIC, ide.config.outputshell, wx.__WXMSW__ and "Courier New" or "")
|
||||
ide.font.oNormal = setFont(wx.wxFONTSTYLE_NORMAL, ide.config.outputshell)
|
||||
ide.font.oItalic = setFont(wx.wxFONTSTYLE_ITALIC, ide.config.outputshell)
|
||||
|
||||
-- treeCtrl font requires slightly different handling
|
||||
local gui, config = wx.wxTreeCtrl():GetFont(), ide.config.filetree
|
||||
if config.fontsize then gui:SetPointSize(config.fontsize) end
|
||||
if config.fontname then gui:SetFaceName(config.fontname) end
|
||||
ide.font.fNormal = gui
|
||||
do local gui, config = wx.wxTreeCtrl():GetFont(), ide.config.filetree
|
||||
if config.fontsize then gui:SetPointSize(config.fontsize) end
|
||||
if config.fontname then gui:SetFaceName(config.fontname) end
|
||||
ide.font.fNormal = gui
|
||||
end
|
||||
|
||||
-- funcList font requires similar handling
|
||||
do local gui, config = wx.wxTreeCtrl():GetFont(), ide.config.funclist
|
||||
if config.fontsize then gui:SetPointSize(config.fontsize) end
|
||||
if config.fontname then gui:SetFaceName(config.fontname) end
|
||||
ide.font.dNormal = gui
|
||||
end
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Create the wxFrame
|
||||
@@ -42,8 +50,8 @@ local function createFrame()
|
||||
local menuBar = wx.wxMenuBar()
|
||||
local statusBar = frame:CreateStatusBar(6)
|
||||
local section_width = statusBar:GetTextExtent("OVRW")
|
||||
statusBar:SetStatusStyles({wx.wxSB_RAISED, wx.wxSB_RAISED, wx.wxSB_RAISED,
|
||||
wx.wxSB_RAISED, wx.wxSB_RAISED, wx.wxSB_RAISED})
|
||||
statusBar:SetStatusStyles({wx.wxSB_FLAT, wx.wxSB_FLAT, wx.wxSB_FLAT,
|
||||
wx.wxSB_FLAT, wx.wxSB_FLAT, wx.wxSB_FLAT})
|
||||
statusBar:SetStatusWidths(
|
||||
{-1, section_width*6, section_width, section_width, section_width*4, section_width*4})
|
||||
statusBar:SetStatusText(GetIDEString("statuswelcome"))
|
||||
@@ -64,28 +72,20 @@ local function SCinB(id) -- shortcut in brackets
|
||||
end
|
||||
|
||||
local function createToolBar(frame)
|
||||
local toolBar = wx.wxToolBar(frame, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize, wx.wxTB_FLAT + wx.wxTB_NODIVIDER)
|
||||
local funclist = wx.wxChoice.new(toolBar,ID "toolBar.funclist",
|
||||
-- Linux requires a bit larger size for the function list in the toolbar.
|
||||
-- Mac also requires a bit larger size, but setting it to 20 resets
|
||||
-- back to 16 when the toolbar is refreshed.
|
||||
wx.wxDefaultPosition, wx.wxSize.new(240,ide.osname == "Unix" and 24 or 16))
|
||||
local toolBar = frame:CreateToolBar(wx.wxTB_FLAT + wx.wxTB_NODIVIDER, wx.wxID_ANY)
|
||||
-- wxChoice is a bit too narrow on Linux, so make it a bit larger
|
||||
local funclist = wx.wxChoice.new(toolBar, ID "toolBar.funclist",
|
||||
wx.wxDefaultPosition, wx.wxSize.new(240, ide.osname == 'Unix' and 28 or 24))
|
||||
|
||||
-- usually the bmp size isn't necessary, but the HELP icon is not the right size in MSW
|
||||
-- there are two sets of icons: use 24 on OSX and 16 on others.
|
||||
local toolBmpSize =
|
||||
ide.osname == 'Macintosh' and wx.wxSize(24, 24) or wx.wxSize(16, 16)
|
||||
local getBitmap = (ide.app.createbitmap or wx.wxArtProvider.GetBitmap)
|
||||
local toolBmpSize = wx.wxSize(16, 16)
|
||||
toolBar:AddTool(ID_NEW, "New", getBitmap(wx.wxART_NORMAL_FILE, wx.wxART_TOOLBAR, toolBmpSize), TR("Create an empty document")..SCinB(ID_NEW))
|
||||
toolBar:AddTool(ID_OPEN, "Open", getBitmap(wx.wxART_FILE_OPEN, wx.wxART_TOOLBAR, toolBmpSize), TR("Open an existing document")..SCinB(ID_OPEN))
|
||||
toolBar:AddTool(ID_SAVE, "Save", getBitmap(wx.wxART_FILE_SAVE, wx.wxART_TOOLBAR, toolBmpSize), TR("Save the current document")..SCinB(ID_SAVE))
|
||||
toolBar:AddTool(ID_SAVEALL, "Save All", getBitmap(wx.wxART_NEW_DIR, wx.wxART_TOOLBAR, toolBmpSize), TR("Save all open documents")..SCinB(ID_SAVEALL))
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddTool(ID_CUT, "Cut", getBitmap(wx.wxART_CUT, wx.wxART_TOOLBAR, toolBmpSize), TR("Cut selected text to clipboard")..SCinB(ID_CUT))
|
||||
toolBar:AddTool(ID_COPY, "Copy", getBitmap(wx.wxART_COPY, wx.wxART_TOOLBAR, toolBmpSize), TR("Copy selected text to clipboard")..SCinB(ID_COPY))
|
||||
toolBar:AddTool(ID_PASTE, "Paste", getBitmap(wx.wxART_PASTE, wx.wxART_TOOLBAR, toolBmpSize), TR("Paste text from the clipboard")..SCinB(ID_PASTE))
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddTool(ID_UNDO, "Undo", getBitmap(wx.wxART_UNDO, wx.wxART_TOOLBAR, toolBmpSize), TR("Undo last edit")..SCinB(ID_UNDO))
|
||||
toolBar:AddTool(ID_REDO, "Redo", getBitmap(wx.wxART_REDO, wx.wxART_TOOLBAR, toolBmpSize), TR("Redo last edit undone")..SCinB(ID_REDO))
|
||||
toolBar:AddTool(ID_PROJECTDIRFROMFILE, "Update", getBitmap(wx.wxART_GO_DIR_UP , wx.wxART_TOOLBAR, toolBmpSize), TR("Set project directory from current file")..SCinB(ID_PROJECTDIRFROMFILE))
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddTool(ID_FIND, "Find", getBitmap(wx.wxART_FIND, wx.wxART_TOOLBAR, toolBmpSize), TR("Find text")..SCinB(ID_FIND))
|
||||
toolBar:AddTool(ID_REPLACE, "Replace", getBitmap(wx.wxART_FIND_AND_REPLACE, wx.wxART_TOOLBAR, toolBmpSize), TR("Find and replace text")..SCinB(ID_REPLACE))
|
||||
@@ -103,8 +103,6 @@ local function createToolBar(frame)
|
||||
toolBar:AddTool(ID_VIEWWATCHWINDOW, "Watch window", getBitmap("wxART_DEBUG_WATCH", wx.wxART_TOOLBAR, toolBmpSize), TR("View the watch window")..SCinB(ID_VIEWWATCHWINDOW))
|
||||
end
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddTool(ID_PROJECTDIRFROMFILE, "Update", getBitmap(wx.wxART_GO_DIR_UP , wx.wxART_TOOLBAR, toolBmpSize), TR("Set project directory from current file")..SCinB(ID_PROJECTDIRFROMFILE))
|
||||
toolBar:AddSeparator()
|
||||
toolBar:AddControl(funclist)
|
||||
toolBar:Realize()
|
||||
|
||||
@@ -118,22 +116,29 @@ local function createNotebook(frame)
|
||||
local notebook = wxaui.wxAuiNotebook(frame, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxDefaultSize,
|
||||
wxaui.wxAUI_NB_DEFAULT_STYLE + wxaui.wxAUI_NB_TAB_EXTERNAL_MOVE
|
||||
+ wx.wxNO_BORDER)
|
||||
+ wxaui.wxAUI_NB_WINDOWLIST_BUTTON + wx.wxNO_BORDER)
|
||||
|
||||
-- the following group of event handlers allows the active editor
|
||||
-- to get/keep focus after execution of Run and other commands
|
||||
local current -- the currently active editor, needed by the focus selection
|
||||
local function onPageChange(event)
|
||||
current = event:GetSelection() -- update the active editor reference
|
||||
SetEditorSelection(current)
|
||||
event:Skip() -- skip to let page change
|
||||
end
|
||||
notebook:Connect(wx.wxEVT_SET_FOCUS, -- Notepad tabs shouldn't be selectable,
|
||||
-- wxEVT_SET_FOCUS could be used, but it only works on Windows with wx2.9.5+
|
||||
notebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED,
|
||||
function (event)
|
||||
SetEditorSelection(current) -- select the currently active editor
|
||||
local ed = GetEditor(notebook:GetSelection())
|
||||
local doc = ed and ed:GetId() and ide.openDocuments[ed:GetId()]
|
||||
|
||||
-- skip activation when any of the following is true:
|
||||
-- (1) there is no document yet, the editor tab was just added,
|
||||
-- so no changes needed as there will be a proper later call;
|
||||
-- (2) the page change event was triggered after a tab is closed;
|
||||
-- (3) on OSX from AddPage event when changing from the last tab
|
||||
-- (this is to work around a duplicate event generated in this case
|
||||
-- that first activates the added tab and then some other tab (2.9.5)).
|
||||
|
||||
local double = (ide.osname == 'Macintosh'
|
||||
and event:GetOldSelection() == notebook:GetPageCount()
|
||||
and debug:traceback():find("'AddPage'"))
|
||||
|
||||
if doc and event:GetOldSelection() ~= -1 and not double then
|
||||
SetEditorSelection(notebook:GetSelection()) end
|
||||
end)
|
||||
notebook:Connect(wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, onPageChange)
|
||||
notebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, onPageChange)
|
||||
|
||||
notebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE,
|
||||
function (event)
|
||||
@@ -141,6 +146,62 @@ local function createNotebook(frame)
|
||||
event:Veto() -- don't propagate the event as the page is already closed
|
||||
end)
|
||||
|
||||
-- tabs can be dragged around which may change their indexes;
|
||||
-- when this happens stored indexes need to be updated to reflect the change.
|
||||
-- there is DRAG_DONE event that I'd prefer to use, but it
|
||||
-- doesn't fire for some reason using wxwidgets 2.9.5 (tested on Windows).
|
||||
if ide.wxver >= "2.9.5" then
|
||||
notebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_END_DRAG,
|
||||
function (event)
|
||||
for page = 0, notebook:GetPageCount()-1 do
|
||||
local editor = GetEditor(page)
|
||||
if editor then ide.openDocuments[editor:GetId()].index = page end
|
||||
end
|
||||
event:Skip()
|
||||
end)
|
||||
end
|
||||
|
||||
local selection
|
||||
notebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP,
|
||||
function (event)
|
||||
selection = event:GetSelection() -- save tab index the event is for
|
||||
local menu = wx.wxMenu()
|
||||
menu:Append(ID_CLOSE, TR("&Close Page"))
|
||||
menu:Append(ID_CLOSEALL, TR("Close A&ll Pages"))
|
||||
menu:Append(ID_CLOSEOTHER, TR("Close &Other Pages"))
|
||||
menu:AppendSeparator()
|
||||
menu:Append(ID_SAVE, TR("&Save"))
|
||||
menu:Append(ID_SAVEAS, TR("Save &As..."))
|
||||
notebook:PopupMenu(menu)
|
||||
end)
|
||||
|
||||
local function IfAtLeastOneTab(event) event:Enable(notebook:GetPageCount() > 0) 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)
|
||||
end)
|
||||
notebook:Connect(ID_SAVE, wx.wxEVT_UPDATE_UI, IfModified)
|
||||
notebook:Connect(ID_SAVEAS, wx.wxEVT_COMMAND_MENU_SELECTED, function()
|
||||
SaveFileAs(GetEditor(selection))
|
||||
end)
|
||||
notebook:Connect(ID_SAVEAS, wx.wxEVT_UPDATE_UI, IfAtLeastOneTab)
|
||||
notebook:Connect(ID_CLOSE, wx.wxEVT_COMMAND_MENU_SELECTED, function()
|
||||
ClosePage(selection)
|
||||
end)
|
||||
notebook:Connect(ID_CLOSE, wx.wxEVT_UPDATE_UI, IfAtLeastOneTab)
|
||||
notebook:Connect(ID_CLOSEALL, wx.wxEVT_COMMAND_MENU_SELECTED, function()
|
||||
CloseAllPagesExcept(nil)
|
||||
end)
|
||||
notebook:Connect(ID_CLOSEALL, wx.wxEVT_UPDATE_UI, IfAtLeastOneTab)
|
||||
notebook:Connect(ID_CLOSEOTHER, wx.wxEVT_COMMAND_MENU_SELECTED, function ()
|
||||
CloseAllPagesExcept(selection)
|
||||
end)
|
||||
notebook:Connect(ID_CLOSEOTHER, wx.wxEVT_UPDATE_UI, function (event)
|
||||
event:Enable(notebook:GetPageCount() > 1)
|
||||
end)
|
||||
|
||||
frame.notebook = notebook
|
||||
return notebook
|
||||
end
|
||||
@@ -160,10 +221,6 @@ local function createBottomNotebook(frame)
|
||||
|
||||
bottomnotebook:AddPage(errorlog, TR("Output"), true)
|
||||
bottomnotebook:AddPage(shellbox, TR("Local console"), false)
|
||||
bottomnotebook:Connect(wxaui.wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE,
|
||||
function (event)
|
||||
event:Veto() -- don't allow closing pages in this notebook
|
||||
end)
|
||||
|
||||
frame.bottomnotebook = bottomnotebook
|
||||
bottomnotebook.errorlog = errorlog
|
||||
@@ -192,35 +249,19 @@ do
|
||||
local frame = ide.frame
|
||||
local mgr = frame.uimgr
|
||||
|
||||
mgr:AddPane(frame.toolBar, wxaui.wxAuiPaneInfo():
|
||||
Name("toolBar"):Caption("Main Toolbar"):
|
||||
MinSize(300,16):
|
||||
ToolbarPane():Top():CloseButton(false):
|
||||
LeftDockable(false):RightDockable(false):Hide())
|
||||
|
||||
mgr:AddPane(frame.notebook, wxaui.wxAuiPaneInfo():
|
||||
Name("notebook"):
|
||||
CenterPane():PaneBorder(false):Hide())
|
||||
|
||||
CenterPane():PaneBorder(false))
|
||||
mgr:AddPane(frame.projpanel, wxaui.wxAuiPaneInfo():
|
||||
Name("projpanel"):Caption(TR("Project")):
|
||||
MinSize(200,200):FloatingSize(200,400):
|
||||
Left():Layer(1):Position(1):
|
||||
CloseButton(true):MaximizeButton(false):PinButton(true):Hide())
|
||||
|
||||
CloseButton(true):MaximizeButton(false):PinButton(true))
|
||||
mgr:AddPane(frame.bottomnotebook, wxaui.wxAuiPaneInfo():
|
||||
Name("bottomnotebook"):
|
||||
MinSize(200,200):FloatingSize(400,250):
|
||||
MinSize(100,100):BestSize(200,200):FloatingSize(400,200):
|
||||
Bottom():Layer(1):Position(1):
|
||||
CloseButton(true):MaximizeButton(false):PinButton(true):Hide())
|
||||
|
||||
mgr:GetPane("toolBar"):Show(true)
|
||||
mgr:GetPane("bottomnotebook"):Show(true)
|
||||
mgr:GetPane("projpanel"):Show(true)
|
||||
mgr:GetPane("notebook"):Show(true)
|
||||
|
||||
local pp = mgr:SavePerspective()
|
||||
mgr.defaultPerspective = pp
|
||||
|
||||
mgr:Update()
|
||||
CloseButton(true):MaximizeButton(false):PinButton(true))
|
||||
|
||||
mgr.defaultPerspective = mgr:SavePerspective()
|
||||
end
|
||||
|
||||
@@ -5,18 +5,22 @@
|
||||
-- Generate a unique new wxWindowID
|
||||
local ID_IDCOUNTER = wx.wxID_HIGHEST + 1
|
||||
function NewID()
|
||||
ID_IDCOUNTER = ID_IDCOUNTER + 1
|
||||
return ID_IDCOUNTER
|
||||
ID_IDCOUNTER = ID_IDCOUNTER + 1
|
||||
return ID_IDCOUNTER
|
||||
end
|
||||
|
||||
-- File menu
|
||||
ID_NEW = wx.wxID_NEW
|
||||
ID_OPEN = wx.wxID_OPEN
|
||||
ID_CLOSE = NewID()
|
||||
ID_CLOSEALL = NewID()
|
||||
ID_CLOSEOTHER = NewID()
|
||||
ID_SAVE = wx.wxID_SAVE
|
||||
ID_SAVEAS = wx.wxID_SAVEAS
|
||||
ID_SAVEALL = NewID()
|
||||
ID_RECENTFILES = NewID()
|
||||
ID_RECENTFILESPREV = NewID()
|
||||
ID_RECENTFILESNEXT = NewID()
|
||||
ID_EXIT = wx.wxID_EXIT
|
||||
-- Edit menu
|
||||
ID_CUT = wx.wxID_CUT
|
||||
@@ -31,6 +35,11 @@ ID_AUTOCOMPLETEENABLE = NewID()
|
||||
ID_COMMENT = NewID()
|
||||
ID_FOLD = NewID()
|
||||
ID_CLEARDYNAMICWORDS = NewID()
|
||||
-- don't use wx.wxID_PREFERENCES to avoid merging with OSX app menu, because
|
||||
-- Apple guidelines describe Preferences as a "normal" item without submenus.
|
||||
ID_PREFERENCES = NewID()
|
||||
ID_PREFERENCESSYSTEM = NewID()
|
||||
ID_PREFERENCESUSER = NewID()
|
||||
-- Search menu
|
||||
ID_FIND = wx.wxID_FIND
|
||||
ID_FINDNEXT = NewID()
|
||||
@@ -71,8 +80,7 @@ ID_ABOUT = wx.wxID_ABOUT
|
||||
-- Watch window menu items
|
||||
ID_ADDWATCH = NewID()
|
||||
ID_EDITWATCH = NewID()
|
||||
ID_REMOVEWATCH = NewID()
|
||||
ID_EVALUATEWATCH = NewID()
|
||||
ID_DELETEWATCH = NewID()
|
||||
-- Editor popup menu items
|
||||
ID_QUICKADDWATCH = NewID()
|
||||
ID_QUICKEVAL = NewID()
|
||||
|
||||
@@ -68,20 +68,25 @@ function M.show_warnings(top_ast)
|
||||
if name ~= 'self' then
|
||||
local func = parent.parent and parent.parent.parent
|
||||
local assignment = not func.tag or func.tag == 'Set' or func.tag == 'Localrec'
|
||||
-- anonymous functions can also be defined in expressions,
|
||||
-- for example, 'Op' or 'Return' tags
|
||||
local expression = not assignment and func.tag
|
||||
local func1 = func[1][1]
|
||||
local fname = assignment and func1 and type(func1[1]) == 'string' and func1[1]
|
||||
or (func1.tag == 'Index' and index(func1))
|
||||
local fname = assignment and func1 and type(func1[1]) == 'string'
|
||||
and func1[1] or (func1 and func1.tag == 'Index' and index(func1))
|
||||
-- "function foo(bar)" => func.tag == 'Set'
|
||||
-- `Set{{`Id{"foo"}},{`Function{{`Id{"bar"}},{}}}}
|
||||
-- "local function foo(bar)" => func.tag == 'Localrec'
|
||||
-- "local _, foo = 1, function(bar)" => func.tag == 'Local'
|
||||
-- "print(function(bar) end)" => func.tag == nil
|
||||
-- "a = a or function(bar) end" => func.tag == nil
|
||||
-- "return(function(bar) end)" => func.tag == 'Return'
|
||||
-- "function tbl:foo(bar)" => func.tag == 'Set'
|
||||
-- `Set{{`Index{`Id{"tbl"},`String{"foo"}}},{`Function{{`Id{"self"},`Id{"bar"}},{}}}}
|
||||
-- "function tbl.abc:foo(bar)" => func.tag == 'Set'
|
||||
-- `Set{{`Index{`Index{`Id{"tbl"},`String{"abc"}},`String{"foo"}}},{`Function{{`Id{"self"},`Id{"bar"}},{}}}},
|
||||
warn("unused parameter '" .. name .. "'" ..
|
||||
(func and assignment
|
||||
(func and (assignment or expression)
|
||||
and (fname and func.tag
|
||||
and (" in function '" .. fname .. "'")
|
||||
or " in anonymous function")
|
||||
|
||||
@@ -1,11 +1,27 @@
|
||||
local ide = ide
|
||||
|
||||
function KSC(id, default)
|
||||
-- this is only for the rare case of someone assigning a complete list
|
||||
-- to ide.config.keymap.
|
||||
local keymap = ide.config.keymap
|
||||
return keymap[id] and "\t"..keymap[id] or default or ""
|
||||
end
|
||||
--[[
|
||||
Accelerator general syntax is any combination of "CTRL", "ALT" and "SHIFT"
|
||||
strings (case doesn't matter) separated by either '-' or '+' characters and
|
||||
followed by the accelerator itself. The accelerator may be any alphanumeric
|
||||
character, any function key (from F1 to F12) or one of the special characters
|
||||
listed below (again, case doesn't matter):
|
||||
|
||||
DEL/DELETE Delete key
|
||||
INS/INSERT Insert key
|
||||
ENTER/RETURN Enter key
|
||||
PGUP PageUp key
|
||||
PGDN PageDown key
|
||||
LEFT Left cursor arrow key
|
||||
RIGHT Right cursor arrow key
|
||||
UP Up cursor arrow key
|
||||
DOWN Down cursor arrow key
|
||||
HOME Home key
|
||||
END End key
|
||||
SPACE Space
|
||||
TAB Tab key
|
||||
ESC/ESCAPE Escape key (Windows only)
|
||||
--]]
|
||||
|
||||
ide.config.keymap = {
|
||||
-- File menu
|
||||
@@ -16,6 +32,8 @@ ide.config.keymap = {
|
||||
[ID_SAVEAS] = "Alt-Shift-S",
|
||||
[ID_SAVEALL] = "",
|
||||
[ID_RECENTFILES] = "",
|
||||
[ID_RECENTFILESPREV] = "Ctrl-<",
|
||||
[ID_RECENTFILESNEXT] = "Ctrl->",
|
||||
[ID_EXIT] = "Ctrl-Q",
|
||||
-- Edit menu
|
||||
[ID_CUT] = "Ctrl-X",
|
||||
@@ -68,32 +86,15 @@ ide.config.keymap = {
|
||||
-- Watch window menu items
|
||||
[ID_ADDWATCH] = "Ins",
|
||||
[ID_EDITWATCH] = "F2",
|
||||
[ID_REMOVEWATCH] = "Del",
|
||||
[ID_EVALUATEWATCH] = "",
|
||||
[ID_DELETEWATCH] = "Del",
|
||||
-- Editor popup menu items
|
||||
[ID_QUICKADDWATCH] = "",
|
||||
[ID_QUICKEVAL] = "",
|
||||
}
|
||||
|
||||
--[[
|
||||
Accelerator general syntax is any combination of "CTRL", "ALT" and "SHIFT"
|
||||
strings (case doesn't matter) separated by either '-' or '+' characters and
|
||||
followed by the accelerator itself. The accelerator may be any alphanumeric
|
||||
character, any function key (from F1 to F12) or one of the special characters
|
||||
listed below (again, case doesn't matter):
|
||||
|
||||
DEL/DELETE Delete key
|
||||
INS/INSERT Insert key
|
||||
ENTER/RETURN Enter key
|
||||
PGUP PageUp key
|
||||
PGDN PageDown key
|
||||
LEFT Left cursor arrow key
|
||||
RIGHT Right cursor arrow key
|
||||
UP Up cursor arrow key
|
||||
DOWN Down cursor arrow key
|
||||
HOME Home key
|
||||
END End key
|
||||
SPACE Space
|
||||
TAB Tab key
|
||||
ESC/ESCAPE Escape key (Windows only)
|
||||
--]]
|
||||
function KSC(id, default)
|
||||
-- this is only for the rare case of someone assigning a complete list
|
||||
-- to ide.config.keymap.
|
||||
local keymap = ide.config.keymap
|
||||
return keymap[id] and "\t"..keymap[id] or default or ""
|
||||
end
|
||||
|
||||
@@ -41,7 +41,7 @@ end
|
||||
local function q(s) return s:gsub('(.)','%%%1') end
|
||||
|
||||
local MD_MARK_PTRN = '' -- combination of all markup marks that can start styling
|
||||
for key,value in pairs(markup) do
|
||||
for key in pairs(markup) do
|
||||
if key ~= MD_MARK_MARK then MD_MARK_PTRN = MD_MARK_PTRN .. q(key) end
|
||||
end
|
||||
MarkupAddStyles(ide.config.styles)
|
||||
@@ -76,12 +76,9 @@ function MarkupHotspotClick(pos, editor)
|
||||
-- check if requested to open in a new window
|
||||
local newwindow = string.find(text, MD_LINK_NEWWINDOW, 1, true) -- plain search
|
||||
if newwindow then text = string.gsub(text, "^%" .. MD_LINK_NEWWINDOW, "") end
|
||||
local name = wx.wxFileName(filepath):GetPath(wx.wxPATH_GET_VOLUME
|
||||
+ wx.wxPATH_GET_SEPARATOR) .. text
|
||||
-- load/activate file
|
||||
local filename = wx.wxFileName(name)
|
||||
filename:Normalize() -- remove .., ., and other similar elements
|
||||
if filename:FileExists() and
|
||||
local filename = GetFullPathIfExists(
|
||||
wx.wxFileName(filepath):GetPath(wx.wxPATH_GET_VOLUME), text)
|
||||
if filename and
|
||||
(newwindow or SaveModifiedDialog(editor, true) ~= wx.wxID_CANCEL) then
|
||||
if not newwindow and ide.osname == 'Macintosh' then editor:GotoPos(0) end
|
||||
LoadFile(filename,not newwindow and editor or nil,true)
|
||||
@@ -135,22 +132,28 @@ function MarkupStyle(editor, lines, linee)
|
||||
-- always style to the end as there may be comments that need re-styling
|
||||
-- technically, this should be GetLineCount()-1, but we want to style
|
||||
-- beyond the last line to make sure it is styled correctly
|
||||
local linee = linee or editor:GetLineCount()
|
||||
local linec = editor:GetLineCount()
|
||||
local linee = linee or linec
|
||||
|
||||
local iscomment = {}
|
||||
for i,v in pairs(editor.spec.iscomment) do
|
||||
iscomment[i] = v
|
||||
end
|
||||
|
||||
local es = editor:GetEndStyled()
|
||||
local needfix = false
|
||||
|
||||
for line=lines,linee do
|
||||
local tx = editor:GetLine(line)
|
||||
local ls = editor:PositionFromLine(line)
|
||||
|
||||
editor:StartStyling(ls, 0)
|
||||
|
||||
local from = 1
|
||||
local off = -1
|
||||
|
||||
-- doing WrapCount(line) when line == linec (which may be beyond
|
||||
-- the last line) occasionally crashes the application on OSX.
|
||||
local wrapped = line < linec and editor:WrapCount(line) or 0
|
||||
|
||||
while from do
|
||||
tx = string.sub(tx,from)
|
||||
local f,t,w,mark = ismarkup(tx)
|
||||
@@ -181,33 +184,17 @@ function MarkupStyle(editor, lines, linee)
|
||||
end
|
||||
from = t and (t+1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- this could work by calling MarkupStyle directly from EVT_UPDATEUI,
|
||||
-- but the styling didn't work correctly as the style on block comments
|
||||
-- (which is used to identify where the markup should be applied)
|
||||
-- was not always correct during UPDATEUI event.
|
||||
-- to rectify this, we style immediately (by calling MarkupStyle
|
||||
-- from UPDATEUI), but also store the starting point and re-style during
|
||||
-- the next UPDATEUI/IDLE event when the block comment style is correct.
|
||||
local needStyle = {}
|
||||
local frame
|
||||
function MarkupStyleRefresh(editor, ev)
|
||||
if not frame then
|
||||
frame = ide.frame
|
||||
frame:Connect(wx.wxEVT_IDLE,
|
||||
function(event) MarkupStyleRefresh(); event:Skip() end)
|
||||
end
|
||||
|
||||
if not ev or #ev == 0 then -- no new records, refresh deferred ones
|
||||
for ed,line in pairs(needStyle) do
|
||||
MarkupStyle(ed, line)
|
||||
needStyle[ed] = nil
|
||||
end
|
||||
else -- store records from the event table to defer refresh
|
||||
for _,pos in ipairs(ev) do
|
||||
needStyle[editor] = editor:LineFromPosition(pos[1])
|
||||
end
|
||||
|
||||
-- has this line changed its wrapping because of invisible styling?
|
||||
if wrapped > 1 and editor:WrapCount(line) < wrapped then needfix = true end
|
||||
end
|
||||
editor:StartStyling(es, 31)
|
||||
|
||||
-- if any wrapped lines have changed, then reset WrapMode to fix the drawing
|
||||
if needfix then
|
||||
-- this fixes an issue with duplicate lines in Scintilla when
|
||||
-- invisible styles hide some of the content that would be wrapped.
|
||||
local wrapmode = editor:GetWrapMode()
|
||||
if wrapmode ~= wxstc.wxSTC_WRAP_NONE then editor:SetWrapMode(wrapmode) end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,7 +25,14 @@ 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") },
|
||||
{ },
|
||||
}
|
||||
|
||||
local preferencesMenu = wx.wxMenu{
|
||||
{ID_PREFERENCESSYSTEM, TR("Settings: System")..KSC(ID_PREFERENCESSYSTEM)},
|
||||
{ID_PREFERENCESUSER, TR("Settings: User")..KSC(ID_PREFERENCESUSER)},
|
||||
}
|
||||
editMenu:Append(ID_PREFERENCES, TR("Preferences"), preferencesMenu)
|
||||
menuBar:Append(editMenu, TR("&Edit"))
|
||||
|
||||
editMenu:Check(ID_AUTOCOMPLETEENABLE, ide.config.autocomplete)
|
||||
@@ -47,12 +54,11 @@ function OnUpdateUIEditMenu(event)
|
||||
if editor == nil then event:Enable(false); return end
|
||||
|
||||
local alwaysOn = { [ID_SELECTALL] = true, [ID_FOLD] = true,
|
||||
-- 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}
|
||||
local menu_id = event:GetId()
|
||||
local enable =
|
||||
((menu_id == ID_COPY or menu_id == ID_CUT) and
|
||||
(editor:GetClassInfo():GetClassName() ~= 'wxStyledTextCtrl'
|
||||
or editor:GetSelectionStart() ~= editor:GetSelectionEnd())) or
|
||||
menu_id == ID_PASTE and editor:CanPaste() or
|
||||
menu_id == ID_UNDO and editor:CanUndo() or
|
||||
menu_id == ID_REDO and editor:CanRedo() or
|
||||
@@ -74,8 +80,12 @@ function OnEditMenu(event)
|
||||
then event:Skip(); return end
|
||||
|
||||
local menu_id = event:GetId()
|
||||
if menu_id == ID_CUT then editor:Cut()
|
||||
elseif menu_id == ID_COPY then editor:Copy()
|
||||
if menu_id == ID_CUT then
|
||||
if editor:GetSelectionStart() == editor:GetSelectionEnd()
|
||||
then editor:LineCut() else editor:Cut() end
|
||||
elseif menu_id == ID_COPY then
|
||||
if editor:GetSelectionStart() == editor:GetSelectionEnd()
|
||||
then editor:LineCopy() else editor:Copy() end
|
||||
elseif menu_id == ID_PASTE then editor:Paste()
|
||||
elseif menu_id == ID_SELECTALL then editor:SelectAll()
|
||||
elseif menu_id == ID_UNDO then editor:Undo()
|
||||
@@ -88,6 +98,32 @@ for _, event in pairs({ID_CUT, ID_COPY, ID_PASTE, ID_SELECTALL, ID_UNDO, ID_REDO
|
||||
frame:Connect(event, wx.wxEVT_UPDATE_UI, OnUpdateUIEditMenu)
|
||||
end
|
||||
|
||||
local function generateConfigMessage(type)
|
||||
return ([==[--[[--
|
||||
Use this file to specify %s preferences.
|
||||
Review [examples](+%s) or check [online documentation](%s) for details.
|
||||
--]]--
|
||||
]==])
|
||||
:format(type, MergeFullPath(ide.editorFilename, "../cfg/user-sample.lua"),
|
||||
"http://studio.zerobrane.com/documentation.html")
|
||||
end
|
||||
|
||||
frame:Connect(ID_PREFERENCESSYSTEM, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function ()
|
||||
local editor = LoadFile(ide.configs.system)
|
||||
if editor and #editor:GetText() == 0 then
|
||||
editor:AddText(generateConfigMessage("System")) end
|
||||
end)
|
||||
|
||||
frame:Connect(ID_PREFERENCESUSER, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function ()
|
||||
local editor = LoadFile(ide.configs.user)
|
||||
if editor and #editor:GetText() == 0 then
|
||||
editor:AddText(generateConfigMessage("User")) end
|
||||
end)
|
||||
frame:Connect(ID_PREFERENCESUSER, wx.wxEVT_UPDATE_UI,
|
||||
function (event) event:Enable(ide.configs.user ~= nil) end)
|
||||
|
||||
frame:Connect(ID_CLEARDYNAMICWORDS, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () DynamicWordsReset() end)
|
||||
|
||||
@@ -126,9 +162,9 @@ frame:Connect(ID_COMMENT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
end
|
||||
local lc = editor.spec.linecomment
|
||||
for line in string.gmatch(editor:GetSelectedText()..'\n', "(.-)\r?\n") do
|
||||
if string.sub(line,1,2) == lc then
|
||||
line = string.sub(line,3)
|
||||
else
|
||||
if string.sub(line,1,#lc) == lc then
|
||||
line = string.sub(line,#lc+1)
|
||||
elseif #line > 0 then
|
||||
line = lc..line
|
||||
end
|
||||
table.insert(buf, line)
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
local ide = ide
|
||||
local frame = ide.frame
|
||||
local menuBar = frame.menuBar
|
||||
local notebook = frame.notebook
|
||||
local openDocuments = ide.openDocuments
|
||||
|
||||
local fileMenu = wx.wxMenu({
|
||||
{ ID_NEW, TR("&New")..KSC(ID_NEW), TR("Create an empty document") },
|
||||
{ ID_OPEN, TR("&Open...")..KSC(ID_OPEN), TR("Open an existing document") },
|
||||
{ ID_CLOSE, TR("&Close page")..KSC(ID_CLOSE), TR("Close the current editor window") },
|
||||
{ ID_CLOSE, TR("&Close Page")..KSC(ID_CLOSE), TR("Close the current editor window") },
|
||||
{ },
|
||||
{ ID_SAVE, TR("&Save")..KSC(ID_SAVE), TR("Save the current document") },
|
||||
{ ID_SAVEAS, TR("Save &As...")..KSC(ID_SAVEAS), TR("Save the current document to a file with a new name") },
|
||||
@@ -24,62 +25,154 @@ local filehistorymenu = wx.wxMenu({})
|
||||
local filehistory = wx.wxMenuItem(fileMenu, ID_RECENTFILES,
|
||||
TR("Recent Files")..KSC(ID_RECENTFILES), TR("File history"), wx.wxITEM_NORMAL, filehistorymenu)
|
||||
fileMenu:Insert(8,filehistory)
|
||||
function UpdateFileHistoryUI(list)
|
||||
-- remove all at first
|
||||
for i=1,filehistorymenu:GetMenuItemCount() do
|
||||
filehistorymenu:Delete( ID("file.recentfiles."..i))
|
||||
end
|
||||
for i=1,#list do
|
||||
local file = list[i].filename
|
||||
local item = wx.wxMenuItem(filehistorymenu, ID("file.recentfiles."..i),file,"")
|
||||
filehistorymenu:Append(item)
|
||||
end
|
||||
end
|
||||
|
||||
for i=1,ide.config.filehistorylength do
|
||||
frame:Connect(ID("file.recentfiles."..i), wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local item = filehistorymenu:FindItemByPosition(i-1)
|
||||
local filename = item:GetLabel()
|
||||
LoadFile(filename)
|
||||
do -- recent file history
|
||||
local iscaseinsensitive = wx.wxFileName("A"):SameAs(wx.wxFileName("a"))
|
||||
local function isSameAs(f1, f2)
|
||||
return f1 == f2 or iscaseinsensitive and f1:lower() == f2:lower()
|
||||
end
|
||||
|
||||
local filehistory = {[0] = 1}
|
||||
|
||||
-- add file to the file history removing duplicates
|
||||
local function addFileHistory(filename)
|
||||
-- a new (empty) tab is opened; don't change the history
|
||||
if not filename then return end
|
||||
|
||||
local fn = wx.wxFileName(filename)
|
||||
if fn:Normalize() then filename = fn:GetFullPath() end
|
||||
|
||||
local index = filehistory[0]
|
||||
|
||||
-- special case: selecting the current file (or moving through the history)
|
||||
if filehistory[index] and isSameAs(filename, filehistory[index].filename) then return end
|
||||
|
||||
-- something else is selected
|
||||
-- (1) flip the history from 1 to the current index
|
||||
for i = 1, math.floor(index/2) do
|
||||
filehistory[i], filehistory[index-i+1] = filehistory[index-i+1], filehistory[i]
|
||||
end
|
||||
)
|
||||
|
||||
-- (2) if the file is in the history, remove it
|
||||
for i = #filehistory, 1, -1 do
|
||||
if isSameAs(filename, filehistory[i].filename) then
|
||||
table.remove(filehistory, i)
|
||||
end
|
||||
end
|
||||
|
||||
-- (3) add the file to the top and update the index
|
||||
table.insert(filehistory, 1, {filename=filename})
|
||||
filehistory[0] = 1
|
||||
|
||||
-- (4) remove all entries that are no longer needed
|
||||
while #filehistory>ide.config.filehistorylength do table.remove(filehistory) end
|
||||
end
|
||||
|
||||
local function remFileHistory(filename)
|
||||
if not filename then return end
|
||||
|
||||
local fn = wx.wxFileName(filename)
|
||||
if fn:Normalize() then filename = fn:GetFullPath() end
|
||||
|
||||
local index = filehistory[0]
|
||||
|
||||
-- special case: removing the current file
|
||||
if filehistory[index] and isSameAs(filename, filehistory[index].filename) then
|
||||
-- (1) flip the history from 1 to the current index
|
||||
for i = 1, math.floor(index/2) do
|
||||
filehistory[i], filehistory[index-i+1] = filehistory[index-i+1], filehistory[i]
|
||||
end
|
||||
end
|
||||
|
||||
-- (2) if the file is in the history, remove it
|
||||
for i = #filehistory, 1, -1 do
|
||||
if isSameAs(filename, filehistory[i].filename) then
|
||||
table.remove(filehistory, i)
|
||||
end
|
||||
end
|
||||
|
||||
-- (3) update index
|
||||
filehistory[0] = 1
|
||||
end
|
||||
|
||||
local updateRecentFiles -- need forward declaration because of recursive refs
|
||||
|
||||
local function loadRecent(event)
|
||||
local id = event:GetId()
|
||||
local item = filehistorymenu:FindItem(id)
|
||||
local filename = item:GetLabel()
|
||||
local index = filehistory[0]
|
||||
filehistory[0] = (
|
||||
(index > 1 and id == ID("file.recentfiles."..(index-1)) and index-1) or
|
||||
(index < #filehistory) and id == ID("file.recentfiles."..(index+1)) and index+1 or
|
||||
1)
|
||||
if not LoadFile(filename, nil, true) then
|
||||
wx.wxMessageBox(
|
||||
TR("File '%s' no longer exists."):format(filename),
|
||||
GetIDEString("editormessage"),
|
||||
wx.wxOK + wx.wxCENTRE, ide.frame)
|
||||
remFileHistory(filename)
|
||||
updateRecentFiles(filehistory)
|
||||
end
|
||||
end
|
||||
|
||||
updateRecentFiles = function (list)
|
||||
local items = filehistorymenu:GetMenuItemCount()
|
||||
for i=1, #list do
|
||||
local file = list[i].filename
|
||||
local id = ID("file.recentfiles."..i)
|
||||
local label = file..(
|
||||
i == list[0]-1 and KSC(ID_RECENTFILESNEXT) or
|
||||
i == list[0]+1 and KSC(ID_RECENTFILESPREV) or
|
||||
"")
|
||||
if i <= items then -- this is an existing item; update the label
|
||||
filehistorymenu:FindItem(id):SetItemLabel(label)
|
||||
else -- need to add an item
|
||||
local item = wx.wxMenuItem(filehistorymenu, id, label, "")
|
||||
filehistorymenu:Append(item)
|
||||
frame:Connect(id, wx.wxEVT_COMMAND_MENU_SELECTED, loadRecent)
|
||||
end
|
||||
end
|
||||
for i=items, #list+1, -1 do -- delete the rest if the list got shorter
|
||||
filehistorymenu:Delete(filehistorymenu:FindItemByPosition(i-1))
|
||||
end
|
||||
|
||||
-- enable if there are any recent files
|
||||
fileMenu:Enable(ID_RECENTFILES, #list > 0)
|
||||
end
|
||||
|
||||
-- public methods
|
||||
function GetFileHistory() return filehistory end
|
||||
function SetFileHistory(fh)
|
||||
filehistory = fh
|
||||
filehistory[0] = 1
|
||||
updateRecentFiles(filehistory)
|
||||
end
|
||||
function AddToFileHistory(filename)
|
||||
addFileHistory(filename)
|
||||
updateRecentFiles(filehistory)
|
||||
end
|
||||
end
|
||||
|
||||
frame:Connect(ID_NEW, wx.wxEVT_COMMAND_MENU_SELECTED, NewFile)
|
||||
frame:Connect(ID_OPEN, wx.wxEVT_COMMAND_MENU_SELECTED, OpenFile)
|
||||
frame:Connect(ID_SAVE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
function ()
|
||||
local editor = GetEditor()
|
||||
local id = editor:GetId()
|
||||
local filePath = openDocuments[id].filePath
|
||||
if (filePath) then
|
||||
SaveFile(editor, filePath)
|
||||
else
|
||||
SaveFileAs(editor)
|
||||
end
|
||||
SaveFile(editor, openDocuments[editor:GetId()].filePath)
|
||||
end)
|
||||
frame:Connect(ID_SAVE, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
local enabled = false
|
||||
if editor then
|
||||
local id = editor:GetId()
|
||||
enabled = openDocuments[id]
|
||||
and (openDocuments[id].isModified or not openDocuments[id].filePath)
|
||||
end
|
||||
event:Enable(enabled)
|
||||
event:Enable(EditorIsModified(GetEditor()))
|
||||
end)
|
||||
|
||||
frame:Connect(ID_SAVEAS, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
SaveFileAs(editor)
|
||||
function ()
|
||||
SaveFileAs(GetEditor())
|
||||
end)
|
||||
frame:Connect(ID_SAVEAS, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
local editor = GetEditor()
|
||||
event:Enable(editor ~= nil)
|
||||
event:Enable(GetEditor() ~= nil)
|
||||
end)
|
||||
|
||||
frame:Connect(ID_SAVEALL, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
@@ -100,7 +193,7 @@ frame:Connect(ID_SAVEALL, wx.wxEVT_UPDATE_UI,
|
||||
|
||||
frame:Connect(ID_CLOSE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
ClosePage() -- this will find the current editor
|
||||
ClosePage() -- this will find the current editor tab
|
||||
end)
|
||||
frame:Connect(ID_CLOSE, wx.wxEVT_UPDATE_UI,
|
||||
function (event)
|
||||
|
||||
@@ -9,23 +9,26 @@ local menuBar = frame.menuBar
|
||||
local mobdebug = require "mobdebug"
|
||||
|
||||
local helpMenu = wx.wxMenu{
|
||||
{ ID_ABOUT, TR("&About")..KSC(ID_ABOUT), TR("About ZeroBrane Studio") },
|
||||
{ ID_ABOUT, TR("&About")..KSC(ID_ABOUT), TR("About %s"):format(GetIDEString("editor")) },
|
||||
}
|
||||
-- do not translate Help menu on Mac as it won't merge with "standard" menus
|
||||
menuBar:Append(helpMenu, ide.osname == 'Macintosh' and "&Help" or TR("&Help"))
|
||||
|
||||
local function DisplayAbout(event)
|
||||
local page = [[
|
||||
local logo = ide.config.path.app.."/"..GetIDEString("logo")
|
||||
local logoimg = wx.wxFileName(logo):FileExists() and
|
||||
([[<tr><td><img src="%s"></td></tr>]]):format(logo) or ""
|
||||
local page = ([[
|
||||
<html>
|
||||
<body text="#777777">
|
||||
<table border="0" width="100%">
|
||||
<tr><td><img src="zbstudio/res/zerobrane.png"></td></tr>
|
||||
<table border="0" width="100%%">
|
||||
%s
|
||||
<tr><td>
|
||||
<table cellspacing="3" cellpadding="3" width="100%">
|
||||
<table cellspacing="3" cellpadding="3" width="100%%">
|
||||
<tr>
|
||||
<td>
|
||||
<b>ZeroBrane Studio (]]..ide.VERSION..[[; MobDebug ]]..mobdebug._VERSION..[[)</b><br>
|
||||
<b>Copyright © 2011-2012 ZeroBrane LLC</b><br>
|
||||
<b>ZeroBrane Studio (%s; MobDebug %s)</b><br>
|
||||
<b>Copyright © 2011-2013 ZeroBrane LLC</b><br>
|
||||
Paul Kulchenko<br>
|
||||
Licensed under the MIT License.
|
||||
</td>
|
||||
@@ -41,7 +44,7 @@ local function DisplayAbout(event)
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b>Based on wxLua editor (]]..wxlua.wxLUA_VERSION_STRING..[[)</b><br>
|
||||
<b>Based on wxLua editor (%s)</b><br>
|
||||
<b>Copyright © 2002-2005 Lomtick Software</b><br>
|
||||
J. Winwood, John Labenski<br>
|
||||
Licensed under wxWindows Library License, v3.
|
||||
@@ -49,36 +52,43 @@ local function DisplayAbout(event)
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b>Built with ]]..wx.wxVERSION_STRING..[[</b>
|
||||
<b>Built with %s</b>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td></tr></table>
|
||||
</body>
|
||||
</html>]]
|
||||
</html>]])
|
||||
:format(logoimg, ide.VERSION, mobdebug._VERSION,
|
||||
wxlua.wxLUA_VERSION_STRING, wx.wxVERSION_STRING)
|
||||
|
||||
local dlg = wx.wxDialog(frame, wx.wxID_ANY, TR("About %s"):format(GetIDEString("editor")))
|
||||
|
||||
-- this is needed because wxLuaHtmlWindow only seems to take into account
|
||||
-- the initial size, but not the one set with SetSize using
|
||||
-- wxlua 2.8.12.2 and wxwidgets 2.9.5+.
|
||||
local tmp = wx.wxLuaHtmlWindow(dlg, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxSize(450, 260))
|
||||
tmp:SetPage(page)
|
||||
local w = tmp:GetInternalRepresentation():GetWidth()
|
||||
local h = tmp:GetInternalRepresentation():GetHeight()
|
||||
tmp:Destroy()
|
||||
|
||||
local dlg = wx.wxDialog(frame, wx.wxID_ANY, TR("About ZeroBrane Studio"))
|
||||
local html = wx.wxLuaHtmlWindow(dlg, wx.wxID_ANY,
|
||||
wx.wxDefaultPosition, wx.wxSize(440, 270),
|
||||
wx.wxHW_SCROLLBAR_NEVER)
|
||||
local line = wx.wxStaticLine(dlg, wx.wxID_ANY)
|
||||
local button = wx.wxButton(dlg, wx.wxID_OK, "OK")
|
||||
|
||||
button:SetDefault()
|
||||
wx.wxDefaultPosition, wx.wxSize(w, h), wx.wxHW_SCROLLBAR_NEVER)
|
||||
|
||||
html:SetBorders(0)
|
||||
html:SetPage(page)
|
||||
html:SetSize(html:GetInternalRepresentation():GetWidth(),
|
||||
html:GetInternalRepresentation():GetHeight())
|
||||
|
||||
local line = wx.wxStaticLine(dlg, wx.wxID_ANY)
|
||||
local button = wx.wxButton(dlg, wx.wxID_OK, "OK")
|
||||
button:SetDefault()
|
||||
|
||||
local topsizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||
topsizer:Add(html, 1, wx.wxALL, 10)
|
||||
topsizer:Add(html, 1, wx.wxEXPAND + wx.wxALL, 10)
|
||||
topsizer:Add(line, 0, wx.wxEXPAND + wx.wxLEFT + wx.wxRIGHT, 10)
|
||||
topsizer:Add(button, 0, wx.wxALL + wx.wxALIGN_RIGHT, 10)
|
||||
topsizer:Fit(dlg)
|
||||
|
||||
dlg:SetAutoLayout(true)
|
||||
dlg:SetSizer(topsizer)
|
||||
dlg:SetSizerAndFit(topsizer)
|
||||
dlg:ShowModal()
|
||||
dlg:Destroy()
|
||||
end
|
||||
|
||||
@@ -72,6 +72,19 @@ menuBar:Append(debugMenu, TR("&Project"))
|
||||
-- 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
|
||||
|
||||
projdir = dir:GetPath(wx.wxPATH_GET_VOLUME) -- no trailing slash
|
||||
|
||||
ide.config.path.projectdir = projdir ~= "" and projdir or nil
|
||||
frame:SetStatusText(projdir)
|
||||
if (not skiptree) then
|
||||
@@ -89,7 +102,7 @@ local function projChoose(event)
|
||||
local projectdir = ide.config.path.projectdir
|
||||
|
||||
local filePicker = wx.wxDirDialog(frame, TR("Choose a project directory"),
|
||||
projectdir ~= "" and projectdir or wx.wxGetCwd(),wx.wxFLP_USE_TEXTCTRL)
|
||||
projectdir ~= "" and projectdir or wx.wxGetCwd(), wx.wxDIRP_DIR_MUST_EXIST)
|
||||
if filePicker:ShowModal(true) == wx.wxID_OK then
|
||||
ProjectUpdateProjectDir(filePicker:GetPath())
|
||||
end
|
||||
@@ -126,7 +139,8 @@ local function selectInterpreter(id)
|
||||
|
||||
ide.interpreter = interpreters[id]
|
||||
|
||||
if DebuggerShutdown then DebuggerShutdown() end
|
||||
DebuggerShutdown()
|
||||
|
||||
ide.frame.statusBar:SetStatusText(ide.interpreter.name or "", 5)
|
||||
ReloadLuaAPI()
|
||||
end
|
||||
@@ -177,8 +191,10 @@ end
|
||||
function ActivateOutput()
|
||||
if not ide.config.activateoutput then return end
|
||||
-- show output/errorlog pane
|
||||
uimgr:GetPane("bottomnotebook"):Show(true)
|
||||
uimgr:Update()
|
||||
if not uimgr:GetPane("bottomnotebook"):IsShown() then
|
||||
uimgr:GetPane("bottomnotebook"):Show(true)
|
||||
uimgr:Update()
|
||||
end
|
||||
-- activate output/errorlog window
|
||||
local index = bottomnotebook:GetPageIndex(bottomnotebook.errorlog)
|
||||
if bottomnotebook:GetSelection() ~= index then
|
||||
|
||||
@@ -27,38 +27,34 @@ function OnUpdateUISearchMenu(event) event:Enable(GetEditor() ~= nil) end
|
||||
|
||||
frame:Connect(ID_FIND, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(false)
|
||||
end)
|
||||
frame:Connect(ID_FIND, wx.wxEVT_UPDATE_UI, OnUpdateUISearchMenu)
|
||||
|
||||
frame:Connect(ID_REPLACE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(true)
|
||||
end)
|
||||
frame:Connect(ID_REPLACE, wx.wxEVT_UPDATE_UI, OnUpdateUISearchMenu)
|
||||
|
||||
frame:Connect(ID_FINDINFILES, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(false,true)
|
||||
end)
|
||||
frame:Connect(ID_REPLACEINFILES, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
findReplace:GetSelectedString()
|
||||
findReplace:Show(true,true)
|
||||
end)
|
||||
|
||||
frame:Connect(ID_FINDNEXT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event) findReplace:GetSelectedString() findReplace:FindString() end)
|
||||
frame:Connect(ID_FINDNEXT, wx.wxEVT_UPDATE_UI,
|
||||
function (event) event:Enable(findReplace:GetSelectedString() and findReplace:HasText()) end)
|
||||
function (event) event:Enable(findReplace:GetSelectedString() or findReplace:HasText()) end)
|
||||
|
||||
frame:Connect(ID_FINDPREV, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event) findReplace:GetSelectedString() findReplace:FindString(true) end)
|
||||
frame:Connect(ID_FINDPREV, wx.wxEVT_UPDATE_UI,
|
||||
function (event) event:Enable(findReplace:GetSelectedString() and findReplace:HasText()) end)
|
||||
function (event) event:Enable(findReplace:GetSelectedString() or findReplace:HasText()) end)
|
||||
|
||||
-------------------- Find replace end
|
||||
|
||||
|
||||
@@ -7,42 +7,57 @@ local menuBar = frame.menuBar
|
||||
local uimgr = frame.uimgr
|
||||
|
||||
local viewMenu = wx.wxMenu {
|
||||
{ ID_VIEWFILETREE, TR("Project/&FileTree Window")..KSC(ID_VIEWFILETREE), TR("View the project/filetree window") },
|
||||
{ ID_VIEWOUTPUT, TR("&Output/Console Window")..KSC(ID_VIEWOUTPUT), TR("View the output/console window") },
|
||||
{ ID_VIEWWATCHWINDOW, TR("&Watch Window")..KSC(ID_VIEWWATCHWINDOW), TR("View the watch window") },
|
||||
{ ID_VIEWCALLSTACK, TR("&Stack Window")..KSC(ID_VIEWCALLSTACK), TR("View the stack window") },
|
||||
{ ID_VIEWFILETREE, TR("Project/&FileTree Window")..KSC(ID_VIEWFILETREE), TR("View the project/filetree window"), wx.wxITEM_CHECK },
|
||||
{ ID_VIEWOUTPUT, TR("&Output/Console Window")..KSC(ID_VIEWOUTPUT), TR("View the output/console window"), wx.wxITEM_CHECK },
|
||||
{ ID_VIEWWATCHWINDOW, TR("&Watch Window")..KSC(ID_VIEWWATCHWINDOW), TR("View the watch window"), wx.wxITEM_CHECK },
|
||||
{ ID_VIEWCALLSTACK, TR("&Stack Window")..KSC(ID_VIEWCALLSTACK), TR("View the stack window"), wx.wxITEM_CHECK },
|
||||
{ },
|
||||
{ ID_VIEWDEFAULTLAYOUT, TR("&Default Layout")..KSC(ID_VIEWDEFAULTLAYOUT), TR("Reset to default layout") },
|
||||
{ ID_VIEWFULLSCREEN, TR("Full &Screen")..KSC(ID_VIEWFULLSCREEN), TR("Switch to or from full screen mode") },
|
||||
}
|
||||
menuBar:Append(viewMenu, TR("&View"))
|
||||
|
||||
local panels = {
|
||||
[ID_VIEWOUTPUT] = "bottomnotebook",
|
||||
[ID_VIEWFILETREE] = "projpanel",
|
||||
[ID_VIEWWATCHWINDOW] = "watchpanel",
|
||||
[ID_VIEWCALLSTACK] = "stackpanel"
|
||||
}
|
||||
|
||||
local function togglePanel(event)
|
||||
local panel = panels[event:GetId()]
|
||||
local mgr = ide.frame.uimgr
|
||||
local shown = not mgr:GetPane(panel):IsShown()
|
||||
mgr:GetPane(panel):Show(shown)
|
||||
mgr:Update()
|
||||
|
||||
return shown
|
||||
end
|
||||
|
||||
local function checkPanel(event)
|
||||
local panel = panels[event:GetId()]
|
||||
local shown = ide.frame.uimgr:GetPane(panel):IsShown()
|
||||
if ide.frame.menuBar:IsChecked(event:GetId()) ~= shown then
|
||||
ide.frame.menuBar:Check(event:GetId(), shown)
|
||||
end
|
||||
end
|
||||
|
||||
frame:Connect(ID_VIEWDEFAULTLAYOUT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function (event)
|
||||
uimgr:LoadPerspective(uimgr.defaultPerspective)
|
||||
uimgr:Update()
|
||||
uimgr:LoadPerspective(uimgr.defaultPerspective, true)
|
||||
end)
|
||||
|
||||
frame:Connect(ID_VIEWOUTPUT, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function ()
|
||||
uimgr:GetPane("bottomnotebook"):Show(true)
|
||||
uimgr:Update()
|
||||
end)
|
||||
|
||||
frame:Connect(ID_VIEWFILETREE, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function ()
|
||||
uimgr:GetPane("projpanel"):Show(true)
|
||||
uimgr:Update()
|
||||
end)
|
||||
|
||||
frame:Connect(ID_VIEWFULLSCREEN, wx.wxEVT_COMMAND_MENU_SELECTED, function ()
|
||||
pcall(function() ShowFullScreen(not frame:IsFullScreen()) end)
|
||||
end)
|
||||
frame:Connect(ID_VIEWFULLSCREEN, wx.wxEVT_UPDATE_UI,
|
||||
function (event) event:Enable(GetEditor() ~= nil) end)
|
||||
|
||||
frame:Connect(ID_VIEWOUTPUT, wx.wxEVT_COMMAND_MENU_SELECTED, togglePanel)
|
||||
frame:Connect(ID_VIEWFILETREE, wx.wxEVT_COMMAND_MENU_SELECTED, togglePanel)
|
||||
frame:Connect(ID_VIEWWATCHWINDOW, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () DebuggerCreateWatchWindow() end)
|
||||
|
||||
function (event) if togglePanel(event) then DebuggerRefreshPanels() end end)
|
||||
frame:Connect(ID_VIEWCALLSTACK, wx.wxEVT_COMMAND_MENU_SELECTED,
|
||||
function () DebuggerCreateStackWindow() end)
|
||||
function (event) if togglePanel(event) then DebuggerRefreshPanels() end end)
|
||||
|
||||
for id in pairs(panels) do frame:Connect(id, wx.wxEVT_UPDATE_UI, checkPanel) end
|
||||
|
||||
@@ -60,9 +60,15 @@ local streamouts = {}
|
||||
local customprocs = {}
|
||||
local textout = '' -- this is a buffer for any text sent to external scripts
|
||||
|
||||
function DetachChildProcess()
|
||||
for _, custom in pairs(customprocs) do
|
||||
if (custom and custom.proc) then custom.proc:Detach() end
|
||||
end
|
||||
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
|
||||
if (custom.uid == uid and custom.proc and custom.proc.Exists(tonumber(tostring(pid)))) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
@@ -140,9 +146,9 @@ function CommandLineRun(cmd,wdir,tooutput,nohide,stringcallback,uid,endcallback)
|
||||
local proc = wx.wxProcess(errorlog)
|
||||
if (tooutput) then proc:Redirect() end -- redirect the output if requested
|
||||
|
||||
-- manipulate working directory
|
||||
-- set working directory if specified
|
||||
local oldcwd
|
||||
if (wdir) then
|
||||
if (wdir and #wdir > 0) then -- directory can be empty; ignore in this case
|
||||
oldcwd = wx.wxFileName.GetCwd()
|
||||
oldcwd = wx.wxFileName.SetCwd(wdir) and oldcwd
|
||||
end
|
||||
@@ -203,11 +209,17 @@ local function updateInputMarker()
|
||||
inputBound = #getInputText()
|
||||
end
|
||||
|
||||
local readonce = 4096
|
||||
local maxread = readonce * 10 -- maximum number of bytes to read before pausing
|
||||
local function getStreams()
|
||||
local function readStream(tab)
|
||||
for _,v in pairs(tab) do
|
||||
while(v.stream:CanRead()) do
|
||||
local str = v.stream:Read(4096)
|
||||
-- periodically stop reading to get a chance to process other events
|
||||
local processed = 0
|
||||
while (v.stream:CanRead() and processed <= maxread) do
|
||||
local str = v.stream:Read(readonce)
|
||||
processed = processed + #str
|
||||
|
||||
local pfn
|
||||
if (v.callback) then
|
||||
str,pfn = v.callback(str)
|
||||
|
||||
@@ -1,303 +0,0 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
local ide = ide
|
||||
-- the preferences dialog
|
||||
|
||||
preferencesDialog = {
|
||||
category = {};
|
||||
uifactory = {};
|
||||
}
|
||||
local cats = preferencesDialog.category
|
||||
|
||||
local function checkstring (v,m)
|
||||
if type(v)~="string" then
|
||||
error(m.." ("..type(v)..")")
|
||||
end
|
||||
end
|
||||
|
||||
function preferencesDialog.addCategory(category)
|
||||
checkstring(category.title,"Invalid category title")
|
||||
checkstring(category.category,"No category")
|
||||
assert(not cats[category.category],"Category already declared")
|
||||
cats[category.category] = category
|
||||
cats[#cats+1] = category
|
||||
category.order = category.order or #cats
|
||||
category.entry = {}
|
||||
end
|
||||
|
||||
function preferencesDialog.addPage(page)
|
||||
assert(page.category and cats[page.category],"Invalid category given")
|
||||
checkstring(page.title,"Invalid title")
|
||||
local c = cats[page.category]
|
||||
c.entry[#c.entry+1] = page
|
||||
page.order = page.order or #c.entry
|
||||
end
|
||||
|
||||
function preferencesDialog.uifactory.space(page,layout,element)
|
||||
layout.currentx = layout.currentx + element.space
|
||||
return layout
|
||||
end
|
||||
function preferencesDialog.uifactory.group(page,layout,element)
|
||||
local margin = element.margin or 6
|
||||
local nl = {
|
||||
currentx = margin;
|
||||
currenty = margin+ (element.title and 12 or 8);
|
||||
maxsizex = 0;
|
||||
maxsizey = 0;
|
||||
minwidth = element.minwidth or 0;
|
||||
minheight = element.minheight or 0;
|
||||
margin = margin;
|
||||
layout = layout;
|
||||
parent = wx.wxStaticBox(layout.parent,wx.wxID_ANY,element.title or "",
|
||||
wx.wxPoint(layout.currentx,layout.currenty),
|
||||
wx.wxDefaultSize, element.borderstyle and wx["wxBORDER_"..element.borderstyle:upper()] or 0);
|
||||
}
|
||||
return nl
|
||||
end
|
||||
function preferencesDialog.uifactory.finishgroup(page,layout,element)
|
||||
local l = layout.layout
|
||||
layout.maxsizex = math.max(layout.minwidth,layout.maxsizex + layout.margin)
|
||||
layout.maxsizey = math.max(layout.minheight,layout.maxsizey + layout.margin)
|
||||
l.maxsizey = math.max(l.maxsizey,layout.maxsizey+l.currenty)
|
||||
l.currentx = l.currentx + layout.maxsizex
|
||||
l.maxsizex = math.max(l.maxsizex,l.currentx)
|
||||
layout.parent:SetSize(wx.wxSize(layout.maxsizex,layout.maxsizey))
|
||||
return l
|
||||
end
|
||||
|
||||
local function pos(layout) return layout.currentx,layout.currenty end
|
||||
local function fitin(el,layout)
|
||||
local x,y = pos(layout)
|
||||
local sz = el:GetBestFittingSize()
|
||||
el:SetSize(sz)
|
||||
layout.maxsizex = math.max(x+sz:GetWidth(),layout.maxsizex)
|
||||
layout.maxsizey = math.max(y+sz:GetHeight(),layout.maxsizey)
|
||||
layout.currentx = x+sz:GetWidth()
|
||||
return layout
|
||||
end
|
||||
|
||||
function preferencesDialog.uifactory.combobox(page,layout,element,value)
|
||||
local x,y = pos(layout)
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local cbox = wx.wxComboBox(layout.parent,id,"",wx.wxPoint(x,y-4),wx.wxDefaultSize,
|
||||
wx.wxArrayString(),wx.wxCB_READONLY)
|
||||
|
||||
if value then
|
||||
for i=1,#value do
|
||||
cbox:Append(value[i])
|
||||
end
|
||||
end
|
||||
|
||||
return fitin(cbox,layout)
|
||||
end
|
||||
|
||||
function preferencesDialog.uifactory.dirpicker(page,layout,element,value)
|
||||
local x,y = pos(layout)
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local picker = wx.wxDirPickerCtrl(layout.parent,id,value or "",element.title or "",wx.wxPoint(x,y-4))
|
||||
return fitin(picker,layout)
|
||||
end
|
||||
|
||||
function preferencesDialog.uifactory.edit (page,layout,element,value)
|
||||
local x,y = pos(layout)
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local edit = wx.wxTextCtrl(layout.parent,id,value or (""..x..","..y), wx.wxPoint(x,y-4))
|
||||
return fitin(edit,layout)
|
||||
end
|
||||
|
||||
function preferencesDialog.uifactory.linebreak(page,layout,element)
|
||||
layout.currentx = layout.margin or 0
|
||||
layout.currenty = layout.maxsizey + (element.space or 0)
|
||||
return layout
|
||||
end
|
||||
function preferencesDialog.uifactory.checkbox (page,layout,element, value)
|
||||
local x,y = pos(layout)
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local cbox = wx.wxCheckBox(layout.parent,id,element.title,wx.wxPoint(x,y))
|
||||
if value then cbox:SetValue(value) end
|
||||
return fitin(cbox,layout)
|
||||
end
|
||||
function preferencesDialog.uifactory.static(page,layout,element)
|
||||
local x,y = pos(layout)
|
||||
local static = wx.wxStaticText(layout.parent,wx.wxID_ANY,element.title,wx.wxPoint(x,y))
|
||||
return fitin(static,layout)
|
||||
end
|
||||
|
||||
function preferencesDialog.uifactory.space(page,layout,element)
|
||||
layout.currentx = layout.currentx + element.space
|
||||
return layout
|
||||
end
|
||||
function preferencesDialog.uifactory.group(page,layout,element)
|
||||
local margin = element.margin or 6
|
||||
local nl = {
|
||||
currentx = margin;
|
||||
currenty = margin+ (element.title and 12 or 8);
|
||||
maxsizex = 0;
|
||||
maxsizey = 0;
|
||||
minwidth = element.minwidth or 0;
|
||||
minheight = element.minheight or 0;
|
||||
margin = margin;
|
||||
layout = layout;
|
||||
parent = wx.wxStaticBox(layout.parent,wx.wxID_ANY,element.title or "",
|
||||
wx.wxPoint(layout.currentx,layout.currenty),
|
||||
wx.wxDefaultSize, element.borderstyle and wx["wxBORDER_"..element.borderstyle:upper()] or 0);
|
||||
}
|
||||
return nl
|
||||
end
|
||||
function preferencesDialog.uifactory.finishgroup(page,layout,element)
|
||||
local l = layout.layout
|
||||
layout.maxsizex = math.max(layout.minwidth,layout.maxsizex + layout.margin)
|
||||
layout.maxsizey = math.max(layout.minheight,layout.maxsizey + layout.margin)
|
||||
l.maxsizey = math.max(l.maxsizey,layout.maxsizey+l.currenty)
|
||||
l.currentx = l.currentx + layout.maxsizex
|
||||
l.maxsizex = math.max(l.maxsizex,l.currentx)
|
||||
layout.parent:SetSize(wx.wxSize(layout.maxsizex,layout.maxsizey))
|
||||
return l
|
||||
end
|
||||
function preferencesDialog.uifactory.linebreak(page,layout,element)
|
||||
layout.currentx = layout.margin or 0
|
||||
layout.currenty = layout.maxsizey + (element.space or 0)
|
||||
return layout
|
||||
end
|
||||
function preferencesDialog.uifactory.checkbox (page,layout,element, value)
|
||||
local x,y = layout.currentx,layout.currenty
|
||||
local id = ID("view.preferences.dialog.page."..page.title.."."..element.name)
|
||||
local cbox = wx.wxCheckBox(layout.parent,id,element.title,wx.wxPoint(x,y))
|
||||
local sz = cbox:GetBestFittingSize()
|
||||
cbox:SetSize(sz)
|
||||
layout.maxsizex = math.max(x+sz:GetWidth(),layout.maxsizex)
|
||||
layout.maxsizey = math.max(y+sz:GetHeight(),layout.maxsizey)
|
||||
layout.currentx = layout.maxsizex
|
||||
if value then cbox:SetValue(value) end
|
||||
return layout
|
||||
end
|
||||
function preferencesDialog.uifactory.static(page,layout,element)
|
||||
local x,y = layout.currentx,layout.currenty
|
||||
local static = wx.wxStaticText(layout.parent,wx.wxID_ANY,element.title,wx.wxPoint(x,y))
|
||||
local sz = static:GetBestFittingSize()
|
||||
static:SetSize(sz)
|
||||
layout.maxsizex = math.max(x+sz:GetWidth(),layout.maxsizex)
|
||||
layout.maxsizey = math.max(y+sz:GetHeight(),layout.maxsizey)
|
||||
layout.currentx = layout.maxsizex
|
||||
|
||||
return layout
|
||||
end
|
||||
|
||||
local function showpage(panel,page)
|
||||
--TODO: layout the page, load values, etc
|
||||
local data = page.onload()
|
||||
local layout = page.layout
|
||||
local layoutdata = {
|
||||
currentx = 0;
|
||||
currenty = 0;
|
||||
maxsizex = 0;
|
||||
maxsizey = 0;
|
||||
parent = panel;
|
||||
}
|
||||
for i,el in ipairs(layout) do
|
||||
assert(preferencesDialog.uifactory[el.type],"Unknown ui type type")
|
||||
layoutdata = assert(
|
||||
preferencesDialog.uifactory[el.type](page,layoutdata,el,data[el.name])
|
||||
)
|
||||
end
|
||||
panel:SetSize(layoutdata.maxsizex,layoutdata.maxsizey)
|
||||
--print(layoutdata.maxsizex,layoutdata.maxsizey)
|
||||
end
|
||||
|
||||
function preferencesDialog.show(event)
|
||||
local dialog = wx.wxDialog(ide.frame, ID "view.preferences.dialog","Preferences")
|
||||
|
||||
local id_btn_ok = ID "view.preferences.dialog.button.ok"
|
||||
local id_btn_cancel = ID "view.preferences.dialog.button.cancel"
|
||||
local id_btn_apply = ID "view.preferences.dialog.button.apply"
|
||||
|
||||
local panel_buttons = wx.wxPanel(dialog,ID "view.preferences.dialog.buttonpanel")
|
||||
local btn_ok = wx.wxButton(panel_buttons,id_btn_ok, "OK")
|
||||
local btn_cancel = wx.wxButton(panel_buttons,id_btn_cancel, "Cancel")
|
||||
local btn_apply = wx.wxButton(panel_buttons,id_btn_apply, "Apply")
|
||||
|
||||
dialog:Connect(id_btn_cancel, wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
function (event)
|
||||
dialog:EndModal(0)
|
||||
end)
|
||||
dialog:Connect(id_btn_ok, wx.wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
function (event)
|
||||
dialog:EndModal(0)
|
||||
end)
|
||||
|
||||
local panel = wx.wxPanel(dialog,ID "view.preferences.dialog.panel",
|
||||
wx.wxDefaultPosition, wx.wxSize(600,400))
|
||||
|
||||
local projtree = wx.wxTreeCtrl(panel, ID "view.preferences.dialog.panel.tree",
|
||||
wx.wxDefaultPosition, wx.wxSize(180,400),
|
||||
wx.wxTR_HAS_BUTTONS + wx.wxTR_SINGLE + wx.wxTR_HIDE_ROOT)
|
||||
local preferencesPage = wx.wxPanel(panel,ID "view.preferences.dialog.page",
|
||||
wx.wxDefaultPosition, wx.wxSize(500,400))
|
||||
local panelsizer = wx.wxBoxSizer(wx.wxHORIZONTAL)
|
||||
panelsizer:Add(projtree,0,wx.wxALL + wx.wxALIGN_LEFT + wx.wxTOP + wx.wxBOTTOM,0)
|
||||
panelsizer:AddSpacer(5)
|
||||
panelsizer:Add(preferencesPage)
|
||||
panel:SetSizer(panelsizer)
|
||||
|
||||
local treecats = {}
|
||||
local catdata = {}
|
||||
table.sort(cats,function(a,b) return a.order < b.order end)
|
||||
local rootit = projtree:AddRoot("")
|
||||
|
||||
catdata[rootit:GetValue()] = {category = "root", children = treecats}
|
||||
for i=1,#cats do
|
||||
local it = projtree:AppendItem(rootit,cats[i].title)
|
||||
treecats[i] = it
|
||||
local c = cats[i]
|
||||
local children = {}
|
||||
catdata[it:GetValue()] = {category = c,children = children}
|
||||
for i=1,#c.entry do
|
||||
local e = c.entry[i]
|
||||
local it = projtree:AppendItem(it,e.title)
|
||||
catdata[it:GetValue()] = {page = e}
|
||||
children[i] = it
|
||||
end
|
||||
projtree:Expand(it)
|
||||
end
|
||||
|
||||
projtree:Expand(rootit)
|
||||
|
||||
local preferencesContent
|
||||
projtree:Connect( wx.wxEVT_COMMAND_TREE_SEL_CHANGED,
|
||||
function( event )
|
||||
local item_id = event:GetItem():GetValue()
|
||||
local data = catdata[item_id]
|
||||
if data.category then
|
||||
if data.children[1] then
|
||||
projtree:SelectItem(data.children[1])
|
||||
end
|
||||
else
|
||||
if preferencesContent then
|
||||
preferencesPage:RemoveChild(preferencesContent)
|
||||
end
|
||||
preferencesContent = wx.wxPanel(preferencesPage,wx.wxID_ANY)
|
||||
|
||||
showpage(preferencesContent,data.page)
|
||||
end
|
||||
end )
|
||||
|
||||
local topsizer = wx.wxBoxSizer(wx.wxVERTICAL)
|
||||
topsizer:Add(panel,0,wx.wxALL + wx.wxALIGN_CENTER,10)
|
||||
topsizer:Add(wx.wxStaticLine(dialog, wx.wxID_ANY), 0, wx.wxEXPAND + wx.wxLEFT + wx.wxRIGHT, 10)
|
||||
topsizer:Add(panel_buttons, 0, wx.wxALL + wx.wxALIGN_RIGHT, 10)
|
||||
|
||||
local buttonpanelsizer = wx.wxBoxSizer(wx.wxHORIZONTAL)
|
||||
buttonpanelsizer:Add(btn_cancel,0,wx.wxALL + wx.wxALIGN_RIGHT,0)
|
||||
buttonpanelsizer:AddSpacer(5)
|
||||
buttonpanelsizer:Add(btn_apply,0,wx.wxALL + wx.wxALIGN_RIGHT,0)
|
||||
buttonpanelsizer:AddSpacer(5)
|
||||
buttonpanelsizer:Add(btn_ok,0,wx.wxALL + wx.wxALIGN_RIGHT,0)
|
||||
panel_buttons:SetSizer(buttonpanelsizer)
|
||||
buttonpanelsizer:Fit(panel_buttons)
|
||||
|
||||
dialog:SetAutoLayout(true)
|
||||
dialog:SetSizer(topsizer)
|
||||
topsizer:Fit(dialog)
|
||||
dialog:Center()
|
||||
dialog:ShowModal()
|
||||
end
|
||||
@@ -100,30 +100,16 @@ function SettingsRestoreFileHistory(fntab)
|
||||
return outtab
|
||||
end
|
||||
|
||||
function SettingsAppendFileToHistory (filename)
|
||||
function SettingsSaveFileHistory (filehistory)
|
||||
local listname = "/filehistory"
|
||||
local oldlist = SettingsRestoreFileHistory(nil,listname)
|
||||
|
||||
-- if the file has been in the history before, remove it
|
||||
for i=#oldlist,1,-1 do
|
||||
if oldlist[i] == filename then table.remove(oldlist,i) end
|
||||
end
|
||||
|
||||
table.insert(oldlist,1,{filename=filename})
|
||||
|
||||
-- remove all entries that are no longer needed
|
||||
while #oldlist>ide.config.filehistorylength do table.remove(oldlist) end
|
||||
|
||||
local path = settings:GetPath()
|
||||
settings:DeleteGroup(listname)
|
||||
settings:SetPath(listname)
|
||||
|
||||
for i,doc in ipairs(oldlist) do
|
||||
for i,doc in ipairs(filehistory) do
|
||||
settings:Write(tostring(i), doc.filename)
|
||||
end
|
||||
|
||||
UpdateFileHistoryUI(oldlist)
|
||||
|
||||
settings:SetPath(path)
|
||||
end
|
||||
|
||||
@@ -371,13 +357,20 @@ function SettingsRestoreView()
|
||||
local layoutcur = uimgr:SavePerspective()
|
||||
local layout = settingsReadSafe(settings,"uimgrlayout",layoutcur)
|
||||
if (layout ~= layoutcur) then
|
||||
uimgr:LoadPerspective(layout)
|
||||
uimgr:LoadPerspective(layout, false)
|
||||
|
||||
-- check if debugging panes are not mentioned and float them
|
||||
local panes = frame.uimgr:GetAllPanes()
|
||||
for _, name in pairs({"stackpanel", "watchpanel"}) do
|
||||
local pane = frame.uimgr:GetPane(name)
|
||||
if not layout:find(name) then pane:Float() end
|
||||
end
|
||||
-- unfortunately need to explicitly (re-)assign the caption,
|
||||
-- as it's going to be restored from the config regardless of how
|
||||
-- it is set now (which affects its translation)
|
||||
uimgr:GetPane("projpanel"):Caption(TR("Project"))
|
||||
uimgr:Update()
|
||||
end
|
||||
uimgr:Update()
|
||||
|
||||
local layoutcur = saveNotebook(frame.notebook)
|
||||
local layout = settingsReadSafe(settings,"nblayout",layoutcur)
|
||||
@@ -443,6 +436,7 @@ function SettingsSaveAll()
|
||||
SettingsSaveProjectSession(FileTreeGetProjects())
|
||||
SettingsSaveFileSession(GetOpenFiles())
|
||||
SettingsSaveView()
|
||||
SettingsSaveFileHistory(GetFileHistory())
|
||||
SettingsSaveFramePosition(ide.frame, "MainFrame")
|
||||
SettingsSaveEditorSettings()
|
||||
end
|
||||
|
||||
@@ -233,6 +233,11 @@ local function createenv ()
|
||||
end
|
||||
end
|
||||
|
||||
local os = { exit = function()
|
||||
ide.frame:AddPendingEvent(wx.wxCommandEvent(
|
||||
wx.wxEVT_COMMAND_MENU_SELECTED, ID_EXIT))
|
||||
end }
|
||||
env.os = setmetatable(os, {__index = _G.os})
|
||||
env.print = DisplayShell
|
||||
env.dofile = dofile
|
||||
env.loadfile = loadfile
|
||||
@@ -261,7 +266,7 @@ local function executeShellCode(tx)
|
||||
tx = tx:gsub("^%s*=%s*","")
|
||||
fn, err = loadstring("return "..tx)
|
||||
if not forceexpression and err and
|
||||
(err:find("'<eof>' expected near '") or
|
||||
(err:find("'?<eof>'? expected near '") or
|
||||
err:find("'%(' expected near") or
|
||||
err:find("unexpected symbol near '")) then
|
||||
fn, err = loadstring(tx)
|
||||
@@ -275,8 +280,8 @@ local function executeShellCode(tx)
|
||||
|
||||
-- set the project dir as the current dir to allow "require" calls
|
||||
-- to work from shell
|
||||
local projectDir, cwd = FileTreeGetDir()
|
||||
if projectDir then
|
||||
local projectDir, cwd = FileTreeGetDir(), nil
|
||||
if projectDir and #projectDir > 0 then
|
||||
cwd = wx.wxFileName.GetCwd()
|
||||
wx.wxFileName.SetCwd(projectDir)
|
||||
end
|
||||
@@ -287,7 +292,7 @@ local function executeShellCode(tx)
|
||||
end))
|
||||
|
||||
-- restore the current dir
|
||||
if projectDir then wx.wxFileName.SetCwd(cwd) end
|
||||
if cwd then wx.wxFileName.SetCwd(cwd) end
|
||||
|
||||
if ok and (addedret or #res > 0) then
|
||||
if addedret then
|
||||
@@ -426,10 +431,37 @@ out:Connect(wx.wxEVT_KEY_DOWN,
|
||||
end)
|
||||
|
||||
local function inputEditable(line)
|
||||
return caretOnPromptLine(fale, line) and
|
||||
return caretOnPromptLine(false, line) and
|
||||
not (out:LineFromPosition(out:GetSelectionStart()) < getPromptLine())
|
||||
end
|
||||
|
||||
-- new Scintilla changed the way markers move when the text is updated
|
||||
-- ticket: http://sourceforge.net/p/scintilla/bugs/939/
|
||||
-- discussion: https://groups.google.com/forum/?hl=en&fromgroups#!topic/scintilla-interest/4giFiKG4VXo
|
||||
if ide.wxver >= "2.9.5" then
|
||||
-- this is a workaround that stores a position of the last prompt marker
|
||||
-- before insert and restores the same position after (as the marker)
|
||||
-- could have moved if the text is added at the beginning of the line.
|
||||
local promptAt
|
||||
out:Connect(wxstc.wxEVT_STC_MODIFIED,
|
||||
function (event)
|
||||
local evtype = event:GetModificationType()
|
||||
if bit.band(evtype, wxstc.wxSTC_MOD_BEFOREINSERT) ~= 0 then
|
||||
local promptLine = getPromptLine()
|
||||
if promptLine and event:GetPosition() == out:PositionFromLine(promptLine)
|
||||
then promptAt = promptLine end
|
||||
end
|
||||
if bit.band(evtype, wxstc.wxSTC_MOD_INSERTTEXT) ~= 0 then
|
||||
local promptLine = getPromptLine()
|
||||
if promptLine and promptAt then
|
||||
out:MarkerDelete(promptLine, PROMPT_MARKER)
|
||||
out:MarkerAdd(promptAt, PROMPT_MARKER)
|
||||
promptAt = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
out:Connect(wxstc.wxEVT_STC_UPDATEUI,
|
||||
function (event) out:SetReadOnly(not inputEditable()) end)
|
||||
|
||||
|
||||
@@ -50,13 +50,8 @@ if success then -- ok, server was started, we are solo
|
||||
svr:sendto(protocol.server.answerok,ip,port)
|
||||
local filename = msg:match(protocol.client.requestloading:gsub("%%s","(.+)$"))
|
||||
if filename then
|
||||
if LoadFile(filename, nil, true) then
|
||||
local frame = ide.frame
|
||||
frame:Iconize(false)
|
||||
frame:Raise()
|
||||
frame:Show(true)
|
||||
frame:SetFocus()
|
||||
frame:RequestUserAttention()
|
||||
if LoadFile(filename, nil, true)
|
||||
then RequestAttention()
|
||||
else DisplayOutput("Can't open requested file '"..filename.."'.\n") end
|
||||
end
|
||||
end
|
||||
@@ -74,14 +69,15 @@ else -- something different is running on our port
|
||||
local failed = false
|
||||
for index = 2, #arg do
|
||||
local fileName = arg[index]
|
||||
if fileName ~= "--" then
|
||||
if fileName ~= "--"
|
||||
-- on OSX, the command line includes -psn parameter, so ignore it
|
||||
and (ide.osname ~= 'Macintosh' or not fileName:find("^-psn")) then
|
||||
cln:send(protocol.client.requestloading:format(fileName))
|
||||
|
||||
local msg,err = cln:receive()
|
||||
if msg ~= protocol.server.answerok then
|
||||
failed = true
|
||||
print(err,msg)
|
||||
else
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,7 +42,7 @@ function StylesGetDefault()
|
||||
bracematch = {fg = {0, 0, 255}, b = true},
|
||||
bracemiss = {fg = {255, 0, 0 }, b = true},
|
||||
ctrlchar = nil,
|
||||
indent = {fg = {192, 192, 192}, bg = {255, 255, 255}},
|
||||
indent = {fg = {192, 192, 230}, bg = {255, 255, 255}},
|
||||
calltip = nil,
|
||||
|
||||
-- common special (need custom fg & bg)
|
||||
@@ -53,7 +53,8 @@ function StylesGetDefault()
|
||||
fold = {fg = {90, 90, 80}, bg = {250, 250, 250}},
|
||||
whitespace = nil,
|
||||
|
||||
fncall = {fg = {175, 175, 255}, st = wxstc.wxSTC_INDIC_TT},
|
||||
fncall = {fg = {128, 128, 255},
|
||||
st = ide.wxver >= "2.9.5" and wxstc.wxSTC_INDIC_ROUNDBOX or wxstc.wxSTC_INDIC_TT},
|
||||
|
||||
-- markup
|
||||
['|'] = {fg = {127, 0, 127}},
|
||||
|
||||
159
src/main.lua
159
src/main.lua
@@ -3,33 +3,34 @@
|
||||
|
||||
-- put bin/ and lualibs/ first to avoid conflicts with included modules
|
||||
-- that may have other versions present somewhere else in path/cpath.
|
||||
-- don't need to do this on Linux where we expect all the libraries
|
||||
-- and binaries to be installed in *regular* places.
|
||||
local iswindows = os.getenv('WINDIR') or (os.getenv('OS') or ''):match('[Ww]indows')
|
||||
local islinux = not iswindows and not os.getenv('DYLD_LIBRARY_PATH') and io.open("/proc")
|
||||
local arch = "x86" -- use 32bit by default
|
||||
|
||||
if iswindows or not pcall(require, "wx")
|
||||
or wx.wxPlatformInfo.Get():GetOperatingSystemFamilyName() == 'Macintosh' then
|
||||
package.cpath = (iswindows
|
||||
and 'bin/?.dll;bin/clibs/?.dll;'
|
||||
or 'bin/clibs/?.dylib;bin/lib?.dylib;')
|
||||
.. package.cpath
|
||||
if islinux then
|
||||
local file = io.popen("uname -m")
|
||||
if file then
|
||||
arch = file:read("*a"):find("x86_64") and "x64" or "x86"
|
||||
file:close()
|
||||
end
|
||||
end
|
||||
|
||||
package.cpath = (
|
||||
iswindows and 'bin/?.dll;bin/clibs/?.dll;' or
|
||||
islinux and ('bin/linux/%s/lib?.so;bin/linux/%s/clibs/?.so;'):format(arch,arch) or
|
||||
--[[isosx]] 'bin/lib?.dylib;bin/clibs/?.dylib;')
|
||||
.. package.cpath
|
||||
package.path = 'lualibs/?.lua;lualibs/?/?.lua;lualibs/?/init.lua;lualibs/?/?/?.lua;lualibs/?/?/init.lua;'
|
||||
.. package.path
|
||||
|
||||
require("wx")
|
||||
require("bit")
|
||||
|
||||
dofile "src/misc/util.lua"
|
||||
dofile "src/util.lua"
|
||||
|
||||
-----------
|
||||
-- IDE
|
||||
--
|
||||
-- Setup important defaults
|
||||
dofile "src/editor/ids.lua"
|
||||
dofile "src/editor/style.lua"
|
||||
|
||||
ide = {
|
||||
config = {
|
||||
path = {
|
||||
@@ -37,8 +38,8 @@ ide = {
|
||||
app = nil,
|
||||
},
|
||||
editor = {
|
||||
usetabs = true,
|
||||
autotabs = true,
|
||||
foldcompact = true,
|
||||
checkeol = true,
|
||||
},
|
||||
debugger = {
|
||||
verbose = false,
|
||||
@@ -51,13 +52,14 @@ ide = {
|
||||
},
|
||||
outputshell = {},
|
||||
filetree = {},
|
||||
funclist = {},
|
||||
|
||||
keymap = {},
|
||||
messages = {},
|
||||
language = "en",
|
||||
|
||||
styles = StylesGetDefault(),
|
||||
stylesoutshell = StylesGetDefault(),
|
||||
styles = nil,
|
||||
stylesoutshell = nil,
|
||||
interpreter = "_undefined_",
|
||||
|
||||
autocomplete = true,
|
||||
@@ -121,12 +123,30 @@ ide = {
|
||||
oNormal = nil,
|
||||
oItalic = nil,
|
||||
fNormal = nil,
|
||||
}
|
||||
dNormal = nil,
|
||||
},
|
||||
|
||||
osname = wx.wxPlatformInfo.Get():GetOperatingSystemFamilyName(),
|
||||
osarch = arch,
|
||||
wxver = string.match(wx.wxVERSION_STRING, "[%d%.]+"),
|
||||
}
|
||||
|
||||
-- add wx.wxMOD_RAW_CONTROL as it's missing in wxlua 2.8.12.3;
|
||||
-- provide default for wx.wxMOD_CONTROL as it's missing in wxlua 2.8 that
|
||||
-- is available through Linux package managers
|
||||
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
|
||||
|
||||
dofile "src/editor/ids.lua"
|
||||
dofile "src/editor/style.lua"
|
||||
dofile "src/editor/keymap.lua"
|
||||
|
||||
function setLuaPaths(mainpath, osname)
|
||||
ide.config.styles = StylesGetDefault()
|
||||
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
|
||||
@@ -152,7 +172,9 @@ function setLuaPaths(mainpath, osname)
|
||||
local clibs =
|
||||
osname == "Windows" and mainpath.."bin/?.dll;"..mainpath.."bin/clibs/?.dll" or
|
||||
osname == "Macintosh" and mainpath.."bin/lib?.dylib;"..mainpath.."bin/clibs/?.dylib" or
|
||||
osname == "Unix" and mainpath.."bin/?.so;"..mainpath.."bin/clibs/?.so" or nil
|
||||
osname == "Unix" and mainpath..("bin/linux/%s/lib?.so;"):format(arch)
|
||||
..mainpath..("bin/linux/%s/clibs/?.so"):format(arch) or
|
||||
nil
|
||||
if clibs then wx.wxSetEnv("LUA_CPATH",
|
||||
package.cpath .. ';' .. clibs .. ';' .. luadev_cpath) end
|
||||
end
|
||||
@@ -163,11 +185,10 @@ local filenames = {}
|
||||
local configs = {}
|
||||
do
|
||||
local arg = {...}
|
||||
local fullPath = arg[1] -- first argument must be the application name
|
||||
assert(type(fullPath) == "string", "first argument must be application name")
|
||||
-- application name is expected as the first argument
|
||||
local fullPath = arg[1] or "zbstudio"
|
||||
|
||||
ide.arg = arg
|
||||
ide.osname = wx.wxPlatformInfo.Get():GetOperatingSystemFamilyName()
|
||||
|
||||
-- on Windows use GetExecutablePath, which is Unicode friendly,
|
||||
-- whereas wxGetCwd() is not (at least in wxlua 2.8.12.2).
|
||||
@@ -185,12 +206,7 @@ do
|
||||
|
||||
for index = 2, #arg do
|
||||
if (arg[index] == "-cfg" and index+1 <= #arg) then
|
||||
local str = arg[index+1]
|
||||
if #str < 4 then
|
||||
print("Comandline: -cfg arg data not passed as string")
|
||||
else
|
||||
table.insert(configs,str)
|
||||
end
|
||||
table.insert(configs,arg[index+1])
|
||||
elseif arg[index-1] ~= "-cfg" then
|
||||
table.insert(filenames,arg[index])
|
||||
end
|
||||
@@ -203,18 +219,17 @@ end
|
||||
-- process application
|
||||
|
||||
ide.app = dofile(ide.config.path.app.."/app.lua")
|
||||
local app = ide.app
|
||||
assert(app)
|
||||
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))
|
||||
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))
|
||||
print(("Error while processing configuration file: '%s'."):format(result))
|
||||
elseif name then
|
||||
if (tab[name]) then
|
||||
local out = tab[name]
|
||||
@@ -230,8 +245,8 @@ end
|
||||
|
||||
-- load interpreters
|
||||
local function loadInterpreters(filter)
|
||||
for _, file in ipairs(FileSysGet("interpreters/*.*", wx.wxFILE)) do
|
||||
if file:match "%.lua$" and (filter or app.loadfilters.interpreters)(file) then
|
||||
for _, file in ipairs(FileSysGetRecursive("interpreters", true, "*.lua")) do
|
||||
if (filter or app.loadfilters.interpreters)(file) then
|
||||
addToTab(ide.interpreters,file)
|
||||
end
|
||||
end
|
||||
@@ -239,14 +254,14 @@ end
|
||||
|
||||
-- load specs
|
||||
local function loadSpecs(filter)
|
||||
for _, file in ipairs(FileSysGet("spec/*.*", wx.wxFILE)) do
|
||||
if file:match "%.lua$" and (filter or app.loadfilters.specs)(file) then
|
||||
for _, file in ipairs(FileSysGetRecursive("spec", true, "*.lua")) do
|
||||
if (filter or app.loadfilters.specs)(file) then
|
||||
addToTab(ide.specs,file)
|
||||
end
|
||||
end
|
||||
|
||||
for _, spec in pairs(ide.specs) do
|
||||
spec.sep = spec.sep or ""
|
||||
spec.sep = spec.sep or "\1" -- default separator doesn't match anything
|
||||
spec.iscomment = {}
|
||||
spec.iskeyword0 = {}
|
||||
spec.isstring = {}
|
||||
@@ -272,8 +287,8 @@ end
|
||||
|
||||
-- load tools
|
||||
local function loadTools(filter)
|
||||
for _, file in ipairs(FileSysGet("tools/*.*", wx.wxFILE)) do
|
||||
if file:match "%.lua$" and (filter or app.loadfilters.tools)(file) then
|
||||
for _, file in ipairs(FileSysGetRecursive("tools", false, "*.lua")) do
|
||||
if (filter or app.loadfilters.tools)(file) then
|
||||
addToTab(ide.tools,file)
|
||||
end
|
||||
end
|
||||
@@ -287,13 +302,14 @@ local resumePrint do
|
||||
print = function(...) errors[#errors+1] = {...} end
|
||||
resumePrint = function()
|
||||
print = origprint
|
||||
for _, e in ipairs(errors) do DisplayOutput(unpack(e), "\n") end
|
||||
for _, e in ipairs(errors) do DisplayOutputLn(unpack(e)) end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------
|
||||
-- load config
|
||||
local function addConfig(filename,isstring)
|
||||
if not filename then return end
|
||||
-- skip those files that don't exist
|
||||
if not isstring and not wx.wxFileName(filename):FileExists() then return end
|
||||
-- if it's marked as command, but exists as a file, load it as a file
|
||||
@@ -305,7 +321,7 @@ local function addConfig(filename,isstring)
|
||||
else msg, cfgfn, err = "file", loadfile(filename) end
|
||||
|
||||
if not cfgfn then
|
||||
print(("Error while loading configuration %s: %s"):format(msg, err))
|
||||
print(("Error while loading configuration %s: '%s'."):format(msg, err))
|
||||
else
|
||||
ide.config.os = os
|
||||
ide.config.wxstc = wxstc
|
||||
@@ -314,7 +330,7 @@ local function addConfig(filename,isstring)
|
||||
setfenv(cfgfn,ide.config)
|
||||
local _, err = pcall(function()cfgfn(assert(_G or _ENV))end)
|
||||
if err then
|
||||
print(("Error while processing configuration %s: %s"):format(msg, err))
|
||||
print(("Error while processing configuration %s: '%s'."):format(msg, err))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -328,6 +344,22 @@ end
|
||||
|
||||
addConfig(ide.config.path.app.."/config.lua")
|
||||
|
||||
ide.editorApp:SetAppName(GetIDEString("settingsapp"))
|
||||
|
||||
-- check if the .ini file needs to be migrated on Windows
|
||||
if ide.osname == 'Windows' and ide.wxver >= "2.9.5" then
|
||||
-- Windows used to have local ini file kept in wx.wxGetHomeDir (before 2.9),
|
||||
-- but since 2.9 it's in GetUserConfigDir(), so migrate it.
|
||||
local ini = ide.editorApp:GetAppName() .. ".ini"
|
||||
local old = wx.wxFileName(wx.wxGetHomeDir(), ini)
|
||||
local new = wx.wxFileName(wx.wxStandardPaths.Get():GetUserConfigDir(), ini)
|
||||
if old:FileExists() and not new:FileExists() then
|
||||
FileCopy(old:GetFullPath(), new:GetFullPath())
|
||||
print(("Migrated configuration file from '%s' to '%s'.")
|
||||
:format(old:GetFullPath(), new:GetFullPath()))
|
||||
end
|
||||
end
|
||||
|
||||
----------------------
|
||||
-- process plugins
|
||||
|
||||
@@ -338,20 +370,19 @@ loadSpecs()
|
||||
loadTools()
|
||||
|
||||
do
|
||||
-- process user config
|
||||
for _, file in ipairs(FileSysGet("cfg/user.lua", wx.wxFILE)) do
|
||||
addConfig(file)
|
||||
end
|
||||
local home = os.getenv("HOME")
|
||||
if home then
|
||||
for _, file in ipairs(FileSysGet(home .. "/.zbstudio/user.lua", wx.wxFILE)) do
|
||||
addConfig(file)
|
||||
end
|
||||
end
|
||||
ide.configs = {
|
||||
system = MergeFullPath("cfg", "user.lua"),
|
||||
user = home and MergeFullPath(home, ".zbstudio/user.lua"),
|
||||
}
|
||||
|
||||
-- process configs
|
||||
addConfig(ide.configs.system)
|
||||
addConfig(ide.configs.user)
|
||||
|
||||
-- process all other configs (if any)
|
||||
for _, v in ipairs(configs) do
|
||||
addConfig(v, true)
|
||||
end
|
||||
for _, v in ipairs(configs) do addConfig(v, true) end
|
||||
|
||||
configs = nil
|
||||
local sep = string_Pathsep
|
||||
if ide.config.language then
|
||||
@@ -359,15 +390,12 @@ do
|
||||
end
|
||||
end
|
||||
|
||||
-- load this after preinit and processing configs to allow
|
||||
-- each of the lists to be modified
|
||||
|
||||
---------------
|
||||
-- Load App
|
||||
|
||||
for _, file in ipairs({
|
||||
"markup", "settings", "singleinstance", "iofilters",
|
||||
"gui", "filetree", "output", "debugger", "preferences",
|
||||
"gui", "filetree", "output", "debugger",
|
||||
"editor", "findreplace", "commands", "autocomplete", "shellbox",
|
||||
"menu_file", "menu_edit", "menu_search",
|
||||
"menu_view", "menu_project", "menu_tools", "menu_help",
|
||||
@@ -375,19 +403,17 @@ for _, file in ipairs({
|
||||
dofile("src/editor/"..file..".lua")
|
||||
end
|
||||
|
||||
dofile "src/preferences/editor.lua"
|
||||
dofile "src/preferences/project.lua"
|
||||
dofile "src/version.lua"
|
||||
|
||||
-- load rest of settings
|
||||
SettingsRestoreEditorSettings()
|
||||
SettingsRestoreFramePosition(ide.frame, "MainFrame")
|
||||
SettingsRestoreFileHistory(SetFileHistory)
|
||||
SettingsRestoreFileSession(function(tabs, params)
|
||||
if params and params.recovery
|
||||
then return SetOpenTabs(params)
|
||||
else return SetOpenFiles(tabs, params) end
|
||||
end)
|
||||
SettingsRestoreFileHistory(UpdateFileHistoryUI)
|
||||
SettingsRestoreProjectSession(FileTreeSetProjects)
|
||||
SettingsRestoreView()
|
||||
|
||||
@@ -411,7 +437,7 @@ if app.postinit then app.postinit() end
|
||||
-- app-specific menus (Help/About), which are not recognized by MacOS
|
||||
-- as special items unless SetMenuBar is done after menus are populated.
|
||||
ide.frame:SetMenuBar(ide.frame.menuBar)
|
||||
if ide.osname == 'Macintosh' then -- force refresh to fix the filetree
|
||||
if ide.wxver < "2.9.5" and ide.osname == 'Macintosh' then -- force refresh to fix the filetree
|
||||
pcall(function() ide.frame:ShowFullScreen(true) ide.frame:ShowFullScreen(false) end)
|
||||
end
|
||||
|
||||
@@ -419,3 +445,10 @@ resumePrint()
|
||||
|
||||
ide.frame:Show(true)
|
||||
wx.wxGetApp():MainLoop()
|
||||
|
||||
-- There are several reasons for this call:
|
||||
-- (1) to fix a crash on OSX when closing with debugging in progress.
|
||||
-- (2) to fix a crash on Linux 32/64bit during GC cleanup in wxlua
|
||||
-- after an external process has been started from the IDE.
|
||||
-- (3) to fix exit on Windows when started as "bin\lua src\main.lua".
|
||||
os.exit()
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
preferencesDialog.addCategory {
|
||||
category = "editor";
|
||||
title = "Editor";
|
||||
}
|
||||
|
||||
preferencesDialog.addPage {
|
||||
title = "Basic preferences";
|
||||
category = "editor";
|
||||
layout = {
|
||||
{type = 'group',title="Sessions"; minheight = 100; minwidth = 100};
|
||||
{type = "checkbox"; title = "Reopen files";name = 'session_restore'};
|
||||
{type = 'finishgroup'};
|
||||
{type = 'space'; space = 4};
|
||||
};
|
||||
onload = function ()
|
||||
return {testbox = true}
|
||||
end;
|
||||
onsave = function (values)
|
||||
end
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
||||
---------------------------------------------------------
|
||||
|
||||
preferencesDialog.addCategory {
|
||||
category = "project";
|
||||
title = "Project";
|
||||
}
|
||||
|
||||
preferencesDialog.addPage {
|
||||
title = "Project settings";
|
||||
category = "project";
|
||||
layout = {
|
||||
{type = 'group',title="Visible menus"; minheight = 100; minwidth = 100};
|
||||
{type = "checkbox"; title = "Tools";name = 'tools'};
|
||||
{type = 'linebreak'; space = 4};
|
||||
{type = "checkbox"; title = "Help";name = 'help'};
|
||||
{type = 'linebreak'; space = 4};
|
||||
--{type='static'; title = "foo"};
|
||||
{type = 'finishgroup'};
|
||||
{type = "space"; space = 4};
|
||||
{type = 'group',title="Interpreter"; minheight = 100; minwidth = 100};
|
||||
{type = "static"; title = "Interpreter"};
|
||||
{type = "space"; space = 4};
|
||||
{type = "combobox"; name = "interpreterlist"};
|
||||
{type = 'linebreak'; space = 4};
|
||||
{type = "static";title = "Working directory"};
|
||||
{type = "dirpicker"; name = "workingdir", title='Working directory'};
|
||||
{type = 'linebreak'; space = 4};
|
||||
{type = "static"; title = "Argument"};
|
||||
{type = "edit"; name = "argument"};
|
||||
{type = 'finishgroup'};
|
||||
};
|
||||
onload = function () return {
|
||||
interpreterlist = {"1","2"}
|
||||
} end;
|
||||
onsave = function (values) end;
|
||||
}
|
||||
@@ -161,18 +161,39 @@ function FileSysHasContent(dir)
|
||||
return #f>0
|
||||
end
|
||||
|
||||
function FileSysGet(dir,spec)
|
||||
function FileSysGetRecursive(path, recursive, spec, skip)
|
||||
spec = spec or "*"
|
||||
local content = {}
|
||||
local browse = wx.wxFileSystem()
|
||||
if not wx.wxFileName(dir):DirExists() then
|
||||
return content
|
||||
local sep = string.char(wx.wxFileName.GetPathSeparator())
|
||||
|
||||
-- recursion is done in all folders but only those folders that match
|
||||
-- the spec are returned. This is the pattern that matches the spec.
|
||||
local specmask = spec:gsub("%.", "%%."):gsub("%*", ".*").."$"
|
||||
|
||||
local function getDir(path, spec)
|
||||
local dir = wx.wxDir(path)
|
||||
if not dir:IsOpened() then return end
|
||||
|
||||
local found, file = dir:GetFirst("*", wx.wxDIR_DIRS)
|
||||
while found do
|
||||
if not skip or not file:find(skip) then
|
||||
local fname = wx.wxFileName(path, file):GetFullPath()
|
||||
if fname:find(specmask) then table.insert(content, fname..sep) end
|
||||
if recursive then getDir(fname, spec) end
|
||||
end
|
||||
found, file = dir:GetNext()
|
||||
end
|
||||
local found, file = dir:GetFirst(spec, wx.wxDIR_FILES)
|
||||
while found do
|
||||
if not skip or not file:find(skip) then
|
||||
local fname = wx.wxFileName(path, file):GetFullPath()
|
||||
table.insert(content, fname)
|
||||
end
|
||||
found, file = dir:GetNext()
|
||||
end
|
||||
end
|
||||
local f = browse:FindFirst(dir,spec)
|
||||
while #f>0 do
|
||||
table.insert(content,(f:gsub("^file:",""))) -- remove file: protocol (wx2.9+)
|
||||
f = browse:FindNext()
|
||||
end
|
||||
if ide.osname == 'Unix' then table.sort(content) end
|
||||
getDir(path, spec)
|
||||
|
||||
return content
|
||||
end
|
||||
|
||||
@@ -183,7 +204,8 @@ function GetFullPathIfExists(p, f)
|
||||
-- f = 'xyz/main.lua' work correctly. Normalize() returns true if done.
|
||||
return (file:Normalize(wx.wxPATH_NORM_ALL, p)
|
||||
and file:FileExists()
|
||||
and file:GetFullPath())
|
||||
and file:GetFullPath()
|
||||
or nil)
|
||||
end
|
||||
|
||||
function MergeFullPath(p, f)
|
||||
@@ -192,7 +214,8 @@ function MergeFullPath(p, f)
|
||||
-- Normalize call is needed to make the case of p = '/abc/def' and
|
||||
-- f = 'xyz/main.lua' work correctly. Normalize() returns true if done.
|
||||
return (file:Normalize(wx.wxPATH_NORM_ALL, p)
|
||||
and file:GetFullPath())
|
||||
and file:GetFullPath()
|
||||
or nil)
|
||||
end
|
||||
|
||||
function FileWrite(file,content)
|
||||
@@ -221,6 +244,8 @@ function FileCopy(file1, file2) return wx.wxCopyFile(file1, file2) end
|
||||
|
||||
TimeGet = pcall(require, "socket") and socket.gettime or os.clock
|
||||
|
||||
function isBinary(text) return text:find("[^\7\8\9\10\12\13\27\32-\255]") end
|
||||
|
||||
function pairsSorted(t, f)
|
||||
local a = {}
|
||||
for n in pairs(t) do table.insert(a, n) end
|
||||
@@ -235,6 +260,31 @@ function pairsSorted(t, f)
|
||||
return iter
|
||||
end
|
||||
|
||||
function fixUTF8(s, replacement)
|
||||
local p, len, invalid = 1, #s, {}
|
||||
while p <= len do
|
||||
if p == s:find("[%z\1-\127]", p) then p = p + 1
|
||||
elseif p == s:find("[\194-\223][\123-\191]", p) then p = p + 2
|
||||
elseif p == s:find( "\224[\160-\191][\128-\191]", p)
|
||||
or p == s:find("[\225-\236][\128-\191][\128-\191]", p)
|
||||
or p == s:find( "\237[\128-\159][\128-\191]", p)
|
||||
or p == s:find("[\238-\239][\128-\191][\128-\191]", p)
|
||||
or p == s:find( "\240[\144-\191][\128-\191]", p) then p = p + 3
|
||||
elseif p == s:find("[\241-\243][\128-\191][\128-\191][\128-\191]", p)
|
||||
or p == s:find( "\244[\128-\143][\128-\191][\128-\191]", p) then p = p + 4
|
||||
else
|
||||
s = s:sub(1, p-1)..replacement..s:sub(p+1)
|
||||
table.insert(invalid, p)
|
||||
end
|
||||
end
|
||||
return s, invalid
|
||||
end
|
||||
|
||||
function RequestAttention()
|
||||
local frame = ide.frame
|
||||
if not frame:IsActive() then frame:RequestUserAttention() end
|
||||
end
|
||||
|
||||
local messages, lang, counter
|
||||
function TR(msg, count)
|
||||
lang = lang or ide.config.language
|
||||
63
t/1-findreplace.lua
Normal file
63
t/1-findreplace.lua
Normal file
@@ -0,0 +1,63 @@
|
||||
local findReplace = ide.findReplace
|
||||
|
||||
local editor = NewFile()
|
||||
ok(editor, "Open New file.")
|
||||
|
||||
local search = "123"
|
||||
local replace = "4"
|
||||
editor:AppendText(search..search.."\n"..search..search)
|
||||
|
||||
ide.frame:ProcessEvent(wx.wxCommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, ID_FIND))
|
||||
ok(findReplace.dialog, "Open Find/Replace dialog.")
|
||||
|
||||
findReplace.findText = search
|
||||
ok(findReplace:HasText(), "Update text to search.")
|
||||
|
||||
findReplace:FindString()
|
||||
ok(editor:GetSelectionStart() ~= editor:GetSelectionEnd(), "Find text with Find Next.")
|
||||
|
||||
local selend = editor:GetSelectionEnd()
|
||||
findReplace:FindString()
|
||||
is(editor:GetSelectionStart(), selend, "Find Next doesn't skip consecutive matches.")
|
||||
|
||||
editor:GotoPos(0) -- reset current selection
|
||||
local findnext = wx.wxUpdateUIEvent(ID_FINDNEXT)
|
||||
ide.frame:ProcessEvent(findnext)
|
||||
ok(findnext:GetEnabled(), "Quick find is enabled without current selection.")
|
||||
|
||||
ide.frame:ProcessEvent(wx.wxCommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, ID_FINDNEXT))
|
||||
is(editor:GetSelectionEnd(), selend, "Quick Find works based on previous search.")
|
||||
|
||||
ide.frame:ProcessEvent(wx.wxCommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, ID_FINDNEXT))
|
||||
is(editor:GetSelectionStart(), selend, "Quick Find finds next match.")
|
||||
|
||||
-- replace the text once
|
||||
findReplace.replaceText = replace
|
||||
findReplace:ReplaceString()
|
||||
local _, replacements = editor:GetText():gsub(replace, replace)
|
||||
is(replacements, 1, "Replace replaces once.")
|
||||
|
||||
-- replace the current text and to the end of file
|
||||
editor:GotoPos(3)
|
||||
findReplace.fWrap = false
|
||||
findReplace:ReplaceString(true)
|
||||
local _, replacements = editor:GetText():gsub(replace, replace)
|
||||
is(replacements, 3, "Replace All without wrapping replaces to the end of file.")
|
||||
|
||||
local expected = search..replace.."\n"..replace..replace
|
||||
is(editor:GetText(), expected, "Replace All with Wrap Around result is as expected.")
|
||||
|
||||
-- start after the match to test wrapping
|
||||
editor:AppendText("\n"..search..search)
|
||||
editor:GotoPos(3)
|
||||
findReplace.fWrap = true
|
||||
findReplace:ReplaceString(true)
|
||||
ok(not editor:GetText():find(search), "Replace All with Wrap Around replaces everything.")
|
||||
|
||||
local expected = replace..replace.."\n"..replace..replace.."\n"..replace..replace
|
||||
is(editor:GetText(), expected, "Replace All without Wrap Around result is as expected.")
|
||||
|
||||
-- cleanup
|
||||
ide.findReplace.dialog:Hide()
|
||||
while editor:CanUndo() do editor:Undo() end
|
||||
ClosePage()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user