diff options
Diffstat (limited to 'shell/data')
25 files changed, 4512 insertions, 0 deletions
diff --git a/shell/data/.gitignore b/shell/data/.gitignore new file mode 100644 index 0000000..8263f12 --- /dev/null +++ b/shell/data/.gitignore @@ -0,0 +1,2 @@ +*.gtkrc +sugar.schemas diff --git a/shell/data/GPLv2 b/shell/data/GPLv2 new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/shell/data/GPLv2 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/shell/data/Makefile.am b/shell/data/Makefile.am new file mode 100644 index 0000000..6a62d23 --- /dev/null +++ b/shell/data/Makefile.am @@ -0,0 +1,68 @@ +SUBDIRS = icons + +sugar-72.gtkrc: gtkrc.em + $(srcdir)/em.py -D scaling=\'72\' $(srcdir)/gtkrc.em > \ + $(top_builddir)/data/sugar-72.gtkrc + +sugar-100.gtkrc: gtkrc.em + $(srcdir)/em.py -D scaling=\'100\' $(srcdir)/gtkrc.em > \ + $(top_builddir)/data/sugar-100.gtkrc + +sugardir = $(pkgdatadir)/data +sugar_DATA = \ + activities.defaults \ + kbdconfig \ + mime.defaults \ + GPLv2 \ + $(GTKRC_FILES) + +GTKRC_FILES = \ + sugar-72.gtkrc \ + sugar-100.gtkrc + +xsessionsdir = $(datadir)/xsessions +xsessions_DATA = sugar.desktop + +applicationsdir = $(datadir)/applications +applications_DATA = sugar-emulator.desktop + +mime_xml_in_files = sugar.xml.in +mime_xml_files = $(mime_xml_in_files:.xml.in=.xml) +@INTLTOOL_XML_RULE@ + +mimedir = $(datadir)/mime/packages +mime_DATA = $(mime_xml_files) + +nmservicedir = $(sysconfdir)/dbus-1/system.d/ +nmservice_DATA = nm-user-settings.conf + +install-data-hook: +if ENABLE_UPDATE_MIMEDB + if [ -z "$$DESTDIR" ]; then \ + update-mime-database "$(datadir)/mime"; \ + fi +endif + +uninstall-hook: +if ENABLE_UPDATE_MIMEDB + if [ -z "$$DESTDIR" ]; then \ + update-mime-database "$(datadir)/mime"; \ + fi +endif + +@INTLTOOL_SCHEMAS_RULE@ + +schemadir = $(GCONF_SCHEMA_FILE_DIR) +schema_in_files = sugar.schemas.in +schema_DATA = $(schema_in_files:.schemas.in=.schemas) + +install-data-local: $(schema_DATA) +if GCONF_SCHEMAS_INSTALL + GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule sugar.schemas 2>&1 > /dev/null +endif + +icondir = $(datadir)/icons/hicolor/scalable/apps +icon_DATA = sugar-xo.svg + +EXTRA_DIST = $(sugar_DATA) $(xsessions_DATA) $(nmservice_DATA) $(mime_xml_in_files) em.py gtkrc.em $(schema_in_files) $(icon_DATA) +CLEANFILES = $(GTKRC_FILES) $(mime_xml_files) $(schema_DATA) diff --git a/shell/data/activities.defaults b/shell/data/activities.defaults new file mode 100644 index 0000000..c294b99 --- /dev/null +++ b/shell/data/activities.defaults @@ -0,0 +1,28 @@ +# Activities to be automatically added to the ring after an upgrade + +com.garycmartin.Moon +com.jotaro.ImplodeActivity +com.laptop.Ruler +edu.mit.media.ScratchActivity +org.laptop.AbiWordActivity +org.laptop.AcousticMeasure +org.laptop.Analyze +org.laptop.Calculate +org.laptop.Chat +org.laptop.HelpActivity +org.laptop.MeasureActivity +org.laptop.Memorize +org.laptop.Oficina +org.laptop.Pippy +org.laptop.RecordActivity +org.laptop.TamTamEdit +org.laptop.TamTamJam +org.laptop.TamTamMini +org.laptop.TamTamSynthLab +org.laptop.TurtleArtActivity +org.laptop.WebActivity +org.laptop.WikipediaActivityEN +org.laptop.sugar.ReadActivity +org.vpri.EtoysActivity +vu.lux.olpc.Maze +vu.lux.olpc.Speak diff --git a/shell/data/em.py b/shell/data/em.py new file mode 100755 index 0000000..165d29e --- /dev/null +++ b/shell/data/em.py @@ -0,0 +1,3302 @@ +#!/usr/bin/env python +# +# $Id: //projects/empy/em.py#146 $ $Date: 2003/10/27 $ + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +""" +A system for processing Python as markup embedded in text. +""" + + +__program__ = 'empy' +__version__ = '3.3' +__url__ = 'http://www.alcyone.com/software/empy/' +__author__ = 'Erik Max Francis <max@alcyone.com>' +__copyright__ = 'Copyright (C) 2002-2003 Erik Max Francis' +__license__ = 'LGPL' + + +import copy +import getopt +import os +import re +import string +import sys +import types + +try: + # The equivalent of import cStringIO as StringIO. + import cStringIO + StringIO = cStringIO + del cStringIO +except ImportError: + import StringIO + +# For backward compatibility, we can't assume these are defined. +False, True = 0, 1 + +# Some basic defaults. +FAILURE_CODE = 1 +DEFAULT_PREFIX = '@' +DEFAULT_PSEUDOMODULE_NAME = 'empy' +DEFAULT_SCRIPT_NAME = '?' +SIGNIFICATOR_RE_SUFFIX = r"%(\S+)\s*(.*)\s*$" +SIGNIFICATOR_RE_STRING = DEFAULT_PREFIX + SIGNIFICATOR_RE_SUFFIX +BANGPATH = '#!' +DEFAULT_CHUNK_SIZE = 8192 +DEFAULT_ERRORS = 'strict' + +# Character information. +IDENTIFIER_FIRST_CHARS = '_abcdefghijklmnopqrstuvwxyz' \ + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +IDENTIFIER_CHARS = IDENTIFIER_FIRST_CHARS + '0123456789.' +ENDING_CHARS = {'(': ')', '[': ']', '{': '}'} + +# Environment variable names. +OPTIONS_ENV = 'EMPY_OPTIONS' +PREFIX_ENV = 'EMPY_PREFIX' +PSEUDO_ENV = 'EMPY_PSEUDO' +FLATTEN_ENV = 'EMPY_FLATTEN' +RAW_ENV = 'EMPY_RAW_ERRORS' +INTERACTIVE_ENV = 'EMPY_INTERACTIVE' +BUFFERED_ENV = 'EMPY_BUFFERED_OUTPUT' +NO_OVERRIDE_ENV = 'EMPY_NO_OVERRIDE' +UNICODE_ENV = 'EMPY_UNICODE' +INPUT_ENCODING_ENV = 'EMPY_UNICODE_INPUT_ENCODING' +OUTPUT_ENCODING_ENV = 'EMPY_UNICODE_OUTPUT_ENCODING' +INPUT_ERRORS_ENV = 'EMPY_UNICODE_INPUT_ERRORS' +OUTPUT_ERRORS_ENV = 'EMPY_UNICODE_OUTPUT_ERRORS' + +# Interpreter options. +BANGPATH_OPT = 'processBangpaths' # process bangpaths as comments? +BUFFERED_OPT = 'bufferedOutput' # fully buffered output? +RAW_OPT = 'rawErrors' # raw errors? +EXIT_OPT = 'exitOnError' # exit on error? +FLATTEN_OPT = 'flatten' # flatten pseudomodule namespace? +OVERRIDE_OPT = 'override' # override sys.stdout with proxy? +CALLBACK_OPT = 'noCallbackError' # is no custom callback an error? + +# Usage info. +OPTION_INFO = [ +("-V --version", "Print version and exit"), +("-h --help", "Print usage and exit"), +("-H --extended-help", "Print extended usage and exit"), +("-k --suppress-errors", "Do not exit on errors; go interactive"), +("-p --prefix=<char>", "Change prefix to something other than @"), +(" --no-prefix", "Do not do any markup processing at all"), +("-m --module=<name>", "Change the internal pseudomodule name"), +("-f --flatten", "Flatten the members of pseudmodule to start"), +("-r --raw-errors", "Show raw Python errors"), +("-i --interactive", "Go into interactive mode after processing"), +("-n --no-override-stdout", "Do not override sys.stdout with proxy"), +("-o --output=<filename>", "Specify file for output as write"), +("-a --append=<filename>", "Specify file for output as append"), +("-b --buffered-output", "Fully buffer output including open"), +(" --binary", "Treat the file as a binary"), +(" --chunk-size=<chunk>", "Use this chunk size for reading binaries"), +("-P --preprocess=<filename>", "Interpret EmPy file before main processing"), +("-I --import=<modules>", "Import Python modules before processing"), +("-D --define=<definition>", "Execute Python assignment statement"), +("-E --execute=<statement>", "Execute Python statement before processing"), +("-F --execute-file=<filename>", "Execute Python file before processing"), +(" --pause-at-end", "Prompt at the ending of processing"), +(" --relative-path", "Add path of EmPy script to sys.path"), +(" --no-callback-error", "Custom markup without callback is error"), +(" --no-bangpath-processing", "Suppress bangpaths as comments"), +("-u --unicode", "Enable Unicode subsystem (Python 2+ only)"), +(" --unicode-encoding=<e>", "Set both input and output encodings"), +(" --unicode-input-encoding=<e>", "Set input encoding"), +(" --unicode-output-encoding=<e>", "Set output encoding"), +(" --unicode-errors=<E>", "Set both input and output error handler"), +(" --unicode-input-errors=<E>", "Set input error handler"), +(" --unicode-output-errors=<E>", "Set output error handler"), +] + +USAGE_NOTES = """\ +Notes: Whitespace immediately inside parentheses of @(...) are +ignored. Whitespace immediately inside braces of @{...} are ignored, +unless ... spans multiple lines. Use @{ ... }@ to suppress newline +following expansion. Simple expressions ignore trailing dots; `@x.' +means `@(x).'. A #! at the start of a file is treated as a @# +comment.""" + +MARKUP_INFO = [ +("@# ... NL", "Comment; remove everything up to newline"), +("@? NAME NL", "Set the current context name"), +("@! INTEGER NL", "Set the current context line number"), +("@ WHITESPACE", "Remove following whitespace; line continuation"), +("@\\ ESCAPE_CODE", "A C-style escape sequence"), +("@@", "Literal @; @ is escaped (duplicated prefix)"), +("@), @], @}", "Literal close parenthesis, bracket, brace"), +("@ STRING_LITERAL", "Replace with string literal contents"), +("@( EXPRESSION )", "Evaluate expression and substitute with str"), +("@( TEST [? THEN [! ELSE]] )", "If test is true, evaluate then, otherwise else"), +("@( TRY $ CATCH )", "Expand try expression, or catch if it raises"), +("@ SIMPLE_EXPRESSION", "Evaluate simple expression and substitute;\n" + "e.g., @x, @x.y, @f(a, b), @l[i], etc."), +("@` EXPRESSION `", "Evaluate expression and substitute with repr"), +("@: EXPRESSION : [DUMMY] :", "Evaluates to @:...:expansion:"), +("@{ STATEMENTS }", "Statements are executed for side effects"), +("@[ CONTROL ]", "Control markups: if E; elif E; for N in E;\n" + "while E; try; except E, N; finally; continue;\n" + "break; end X"), +("@%% KEY WHITESPACE VALUE NL", "Significator form of __KEY__ = VALUE"), +("@< CONTENTS >", "Custom markup; meaning provided by user"), +] + +ESCAPE_INFO = [ +("@\\0", "NUL, null"), +("@\\a", "BEL, bell"), +("@\\b", "BS, backspace"), +("@\\dDDD", "three-digit decimal code DDD"), +("@\\e", "ESC, escape"), +("@\\f", "FF, form feed"), +("@\\h", "DEL, delete"), +("@\\n", "LF, linefeed, newline"), +("@\\N{NAME}", "Unicode character named NAME"), +("@\\oOOO", "three-digit octal code OOO"), +("@\\qQQQQ", "four-digit quaternary code QQQQ"), +("@\\r", "CR, carriage return"), +("@\\s", "SP, space"), +("@\\t", "HT, horizontal tab"), +("@\\uHHHH", "16-bit hexadecimal Unicode HHHH"), +("@\\UHHHHHHHH", "32-bit hexadecimal Unicode HHHHHHHH"), +("@\\v", "VT, vertical tab"), +("@\\xHH", "two-digit hexadecimal code HH"), +("@\\z", "EOT, end of transmission"), +] + +PSEUDOMODULE_INFO = [ +("VERSION", "String representing EmPy version"), +("SIGNIFICATOR_RE_STRING", "Regular expression matching significators"), +("SIGNIFICATOR_RE_SUFFIX", "The above stub, lacking the prefix"), +("interpreter", "Currently-executing interpreter instance"), +("argv", "The EmPy script name and command line arguments"), +("args", "The command line arguments only"), +("identify()", "Identify top context as name, line"), +("setContextName(name)", "Set the name of the current context"), +("setContextLine(line)", "Set the line number of the current context"), +("atExit(callable)", "Invoke no-argument function at shutdown"), +("getGlobals()", "Retrieve this interpreter's globals"), +("setGlobals(dict)", "Set this interpreter's globals"), +("updateGlobals(dict)", "Merge dictionary into interpreter's globals"), +("clearGlobals()", "Start globals over anew"), +("saveGlobals([deep])", "Save a copy of the globals"), +("restoreGlobals([pop])", "Restore the most recently saved globals"), +("defined(name, [loc])", "Find if the name is defined"), +("evaluate(expression, [loc])", "Evaluate the expression"), +("serialize(expression, [loc])", "Evaluate and serialize the expression"), +("execute(statements, [loc])", "Execute the statements"), +("single(source, [loc])", "Execute the 'single' object"), +("atomic(name, value, [loc])", "Perform an atomic assignment"), +("assign(name, value, [loc])", "Perform an arbitrary assignment"), +("significate(key, [value])", "Significate the given key, value pair"), +("include(file, [loc])", "Include filename or file-like object"), +("expand(string, [loc])", "Explicitly expand string and return"), +("string(data, [name], [loc])", "Process string-like object"), +("quote(string)", "Quote prefixes in provided string and return"), +("flatten([keys])", "Flatten module contents into globals namespace"), +("getPrefix()", "Get current prefix"), +("setPrefix(char)", "Set new prefix"), +("stopDiverting()", "Stop diverting; data sent directly to output"), +("createDiversion(name)", "Create a diversion but do not divert to it"), +("retrieveDiversion(name)", "Retrieve the actual named diversion object"), +("startDiversion(name)", "Start diverting to given diversion"), +("playDiversion(name)", "Recall diversion and then eliminate it"), +("replayDiversion(name)", "Recall diversion but retain it"), +("purgeDiversion(name)", "Erase diversion"), +("playAllDiversions()", "Stop diverting and play all diversions in order"), +("replayAllDiversions()", "Stop diverting and replay all diversions"), +("purgeAllDiversions()", "Stop diverting and purge all diversions"), +("getFilter()", "Get current filter"), +("resetFilter()", "Reset filter; no filtering"), +("nullFilter()", "Install null filter"), +("setFilter(shortcut)", "Install new filter or filter chain"), +("attachFilter(shortcut)", "Attach single filter to end of current chain"), +("areHooksEnabled()", "Return whether or not hooks are enabled"), +("enableHooks()", "Enable hooks (default)"), +("disableHooks()", "Disable hook invocation"), +("getHooks()", "Get all the hooks"), +("clearHooks()", "Clear all hooks"), +("addHook(hook, [i])", "Register the hook (optionally insert)"), +("removeHook(hook)", "Remove an already-registered hook from name"), +("invokeHook(name_, ...)", "Manually invoke hook"), +("getCallback()", "Get interpreter callback"), +("registerCallback(callback)", "Register callback with interpreter"), +("deregisterCallback()", "Deregister callback from interpreter"), +("invokeCallback(contents)", "Invoke the callback directly"), +("Interpreter", "The interpreter class"), +] + +ENVIRONMENT_INFO = [ +(OPTIONS_ENV, "Specified options will be included"), +(PREFIX_ENV, "Specify the default prefix: -p <value>"), +(PSEUDO_ENV, "Specify name of pseudomodule: -m <value>"), +(FLATTEN_ENV, "Flatten empy pseudomodule if defined: -f"), +(RAW_ENV, "Show raw errors if defined: -r"), +(INTERACTIVE_ENV, "Enter interactive mode if defined: -i"), +(BUFFERED_ENV, "Fully buffered output if defined: -b"), +(NO_OVERRIDE_ENV, "Do not override sys.stdout if defined: -n"), +(UNICODE_ENV, "Enable Unicode subsystem: -n"), +(INPUT_ENCODING_ENV, "Unicode input encoding"), +(OUTPUT_ENCODING_ENV, "Unicode output encoding"), +(INPUT_ERRORS_ENV, "Unicode input error handler"), +(OUTPUT_ERRORS_ENV, "Unicode output error handler"), +] + +class Error(Exception): + """The base class for all EmPy errors.""" + pass + +EmpyError = EmPyError = Error # DEPRECATED + +class DiversionError(Error): + """An error related to diversions.""" + pass + +class FilterError(Error): + """An error related to filters.""" + pass + +class StackUnderflowError(Error): + """A stack underflow.""" + pass + +class SubsystemError(Error): + """An error associated with the Unicode subsystem.""" + pass + +class FlowError(Error): + """An exception related to control flow.""" + pass + +class ContinueFlow(FlowError): + """A continue control flow.""" + pass + +class BreakFlow(FlowError): + """A break control flow.""" + pass + +class ParseError(Error): + """A parse error occurred.""" + pass + +class TransientParseError(ParseError): + """A parse error occurred which may be resolved by feeding more data. + Such an error reaching the toplevel is an unexpected EOF error.""" + pass + + +class MetaError(Exception): + + """A wrapper around a real Python exception for including a copy of + the context.""" + + def __init__(self, contexts, exc): + Exception.__init__(self, exc) + self.contexts = contexts + self.exc = exc + + def __str__(self): + backtrace = map(lambda x: str(x), self.contexts) + return "%s: %s (%s)" % (self.exc.__class__, self.exc, \ + (string.join(backtrace, ', '))) + + +class Subsystem: + + """The subsystem class defers file creation so that it can create + Unicode-wrapped files if desired (and possible).""" + + def __init__(self): + self.useUnicode = False + self.inputEncoding = None + self.outputEncoding = None + self.errors = None + + def initialize(self, inputEncoding=None, outputEncoding=None, \ + inputErrors=None, outputErrors=None): + self.useUnicode = True + try: + unicode + import codecs + except (NameError, ImportError): + raise SubsystemError, "Unicode subsystem unavailable" + defaultEncoding = sys.getdefaultencoding() + if inputEncoding is None: + inputEncoding = defaultEncoding + self.inputEncoding = inputEncoding + if outputEncoding is None: + outputEncoding = defaultEncoding + self.outputEncoding = outputEncoding + if inputErrors is None: + inputErrors = DEFAULT_ERRORS + self.inputErrors = inputErrors + if outputErrors is None: + outputErrors = DEFAULT_ERRORS + self.outputErrors = outputErrors + + def assertUnicode(self): + if not self.useUnicode: + raise SubsystemError, "Unicode subsystem unavailable" + + def open(self, name, mode=None): + if self.useUnicode: + return self.unicodeOpen(name, mode) + else: + return self.defaultOpen(name, mode) + + def defaultOpen(self, name, mode=None): + if mode is None: + mode = 'r' + return open(name, mode) + + def unicodeOpen(self, name, mode=None): + import codecs + if mode is None: + mode = 'rb' + if mode.find('w') >= 0 or mode.find('a') >= 0: + encoding = self.outputEncoding + errors = self.outputErrors + else: + encoding = self.inputEncoding + errors = self.inputErrors + return codecs.open(name, mode, encoding, errors) + +theSubsystem = Subsystem() + + +class Stack: + + """A simple stack that behaves as a sequence (with 0 being the top + of the stack, not the bottom).""" + + def __init__(self, seq=None): + if seq is None: + seq = [] + self.data = seq + + def top(self): + """Access the top element on the stack.""" + try: + return self.data[-1] + except IndexError: + raise StackUnderflowError, "stack is empty for top" + + def pop(self): + """Pop the top element off the stack and return it.""" + try: + return self.data.pop() + except IndexError: + raise StackUnderflowError, "stack is empty for pop" + + def push(self, object): + """Push an element onto the top of the stack.""" + self.data.append(object) + + def filter(self, function): + """Filter the elements of the stack through the function.""" + self.data = filter(function, self.data) + + def purge(self): + """Purge the stack.""" + self.data = [] + + def clone(self): + """Create a duplicate of this stack.""" + return self.__class__(self.data[:]) + + def __nonzero__(self): return len(self.data) != 0 + def __len__(self): return len(self.data) + def __getitem__(self, index): return self.data[-(index + 1)] + + def __repr__(self): + return '<%s instance at 0x%x [%s]>' % \ + (self.__class__, id(self), \ + string.join(map(repr, self.data), ', ')) + + +class AbstractFile: + + """An abstracted file that, when buffered, will totally buffer the + file, including even the file open.""" + + def __init__(self, filename, mode='w', buffered=False): + # The calls below might throw, so start off by marking this + # file as "done." This way destruction of a not-completely- + # initialized AbstractFile will generate no further errors. + self.done = True + self.filename = filename + self.mode = mode + self.buffered = buffered + if buffered: + self.bufferFile = StringIO.StringIO() + else: + self.bufferFile = theSubsystem.open(filename, mode) + # Okay, we got this far, so the AbstractFile is initialized. + # Flag it as "not done." + self.done = False + + def __del__(self): + self.close() + + def write(self, data): + self.bufferFile.write(data) + + def writelines(self, data): + self.bufferFile.writelines(data) + + def flush(self): + self.bufferFile.flush() + + def close(self): + if not self.done: + self.commit() + self.done = True + + def commit(self): + if self.buffered: + file = theSubsystem.open(self.filename, self.mode) + file.write(self.bufferFile.getvalue()) + file.close() + else: + self.bufferFile.close() + + def abort(self): + if self.buffered: + self.bufferFile = None + else: + self.bufferFile.close() + self.bufferFile = None + self.done = True + + +class Diversion: + + """The representation of an active diversion. Diversions act as + (writable) file objects, and then can be recalled either as pure + strings or (readable) file objects.""" + + def __init__(self): + self.file = StringIO.StringIO() + + # These methods define the writable file-like interface for the + # diversion. + + def write(self, data): + self.file.write(data) + + def writelines(self, lines): + for line in lines: + self.write(line) + + def flush(self): + self.file.flush() + + def close(self): + self.file.close() + + # These methods are specific to diversions. + + def asString(self): + """Return the diversion as a string.""" + return self.file.getvalue() + + def asFile(self): + """Return the diversion as a file.""" + return StringIO.StringIO(self.file.getvalue()) + + +class Stream: + + """A wrapper around an (output) file object which supports + diversions and filtering.""" + + def __init__(self, file): + self.file = file + self.currentDiversion = None + self.diversions = {} + self.filter = file + self.done = False + + def write(self, data): + if self.currentDiversion is None: + self.filter.write(data) + else: + self.diversions[self.currentDiversion].write(data) + + def writelines(self, lines): + for line in lines: + self.write(line) + + def flush(self): + self.filter.flush() + + def close(self): + if not self.done: + self.undivertAll(True) + self.filter.close() + self.done = True + + def shortcut(self, shortcut): + """Take a filter shortcut and translate it into a filter, returning + it. Sequences don't count here; these should be detected + independently.""" + if shortcut == 0: + return NullFilter() + elif type(shortcut) is types.FunctionType or \ + type(shortcut) is types.BuiltinFunctionType or \ + type(shortcut) is types.BuiltinMethodType or \ + type(shortcut) is types.LambdaType: + return FunctionFilter(shortcut) + elif type(shortcut) is types.StringType: + return StringFilter(filter) + elif type(shortcut) is types.DictType: + raise NotImplementedError, "mapping filters not yet supported" + else: + # Presume it's a plain old filter. + return shortcut + + def last(self): + """Find the last filter in the current filter chain, or None if + there are no filters installed.""" + if self.filter is None: + return None + thisFilter, lastFilter = self.filter, None + while thisFilter is not None and thisFilter is not self.file: + lastFilter = thisFilter + thisFilter = thisFilter.next() + return lastFilter + + def install(self, shortcut=None): + """Install a new filter; None means no filter. Handle all the + special shortcuts for filters here.""" + # Before starting, execute a flush. + self.filter.flush() + if shortcut is None or shortcut == [] or shortcut == (): + # Shortcuts for "no filter." + self.filter = self.file + else: + if type(shortcut) in (types.ListType, types.TupleType): + shortcuts = list(shortcut) + else: + shortcuts = [shortcut] + # Run through the shortcut filter names, replacing them with + # full-fledged instances of Filter. + filters = [] + for shortcut in shortcuts: + filters.append(self.shortcut(shortcut)) + if len(filters) > 1: + # If there's more than one filter provided, chain them + # together. + lastFilter = None + for filter in filters: + if lastFilter is not None: + lastFilter.attach(filter) + lastFilter = filter + lastFilter.attach(self.file) + self.filter = filters[0] + else: + # If there's only one filter, assume that it's alone or it's + # part of a chain that has already been manually chained; + # just find the end. + filter = filters[0] + lastFilter = filter.last() + lastFilter.attach(self.file) + self.filter = filter + + def attach(self, shortcut): + """Attached a solitary filter (no sequences allowed here) at the + end of the current filter chain.""" + lastFilter = self.last() + if lastFilter is None: + # Just install it from scratch if there is no active filter. + self.install(shortcut) + else: + # Attach the last filter to this one, and this one to the file. + filter = self.shortcut(shortcut) + lastFilter.attach(filter) + filter.attach(self.file) + + def revert(self): + """Reset any current diversions.""" + self.currentDiversion = None + + def create(self, name): + """Create a diversion if one does not already exist, but do not + divert to it yet.""" + if name is None: + raise DiversionError, "diversion name must be non-None" + if not self.diversions.has_key(name): + self.diversions[name] = Diversion() + + def retrieve(self, name): + """Retrieve the given diversion.""" + if name is None: + raise DiversionError, "diversion name must be non-None" + if self.diversions.has_key(name): + return self.diversions[name] + else: + raise DiversionError, "nonexistent diversion: %s" % name + + def divert(self, name): + """Start diverting.""" + if name is None: + raise DiversionError, "diversion name must be non-None" + self.create(name) + self.currentDiversion = name + + def undivert(self, name, purgeAfterwards=False): + """Undivert a particular diversion.""" + if name is None: + raise DiversionError, "diversion name must be non-None" + if self.diversions.has_key(name): + diversion = self.diversions[name] + self.filter.write(diversion.asString()) + if purgeAfterwards: + self.purge(name) + else: + raise DiversionError, "nonexistent diversion: %s" % name + + def purge(self, name): + """Purge the specified diversion.""" + if name is None: + raise DiversionError, "diversion name must be non-None" + if self.diversions.has_key(name): + del self.diversions[name] + if self.currentDiversion == name: + self.currentDiversion = None + + def undivertAll(self, purgeAfterwards=True): + """Undivert all pending diversions.""" + if self.diversions: + self.revert() # revert before undiverting! + names = self.diversions.keys() + names.sort() + for name in names: + self.undivert(name) + if purgeAfterwards: + self.purge(name) + + def purgeAll(self): + """Eliminate all existing diversions.""" + if self.diversions: + self.diversions = {} + self.currentDiversion = None + + +class NullFile: + + """A simple class that supports all the file-like object methods + but simply does nothing at all.""" + + def __init__(self): pass + def write(self, data): pass + def writelines(self, lines): pass + def flush(self): pass + def close(self): pass + + +class UncloseableFile: + + """A simple class which wraps around a delegate file-like object + and lets everything through except close calls.""" + + def __init__(self, delegate): + self.delegate = delegate + + def write(self, data): + self.delegate.write(data) + + def writelines(self, lines): + self.delegate.writelines(data) + + def flush(self): + self.delegate.flush() + + def close(self): + """Eat this one.""" + pass + + +class ProxyFile: + + """The proxy file object that is intended to take the place of + sys.stdout. The proxy can manage a stack of file objects it is + writing to, and an underlying raw file object.""" + + def __init__(self, bottom): + self.stack = Stack() + self.bottom = bottom + + def current(self): + """Get the current stream to write to.""" + if self.stack: + return self.stack[-1][1] + else: + return self.bottom + + def push(self, interpreter): + self.stack.push((interpreter, interpreter.stream())) + + def pop(self, interpreter): + result = self.stack.pop() + assert interpreter is result[0] + + def clear(self, interpreter): + self.stack.filter(lambda x, i=interpreter: x[0] is not i) + + def write(self, data): + self.current().write(data) + + def writelines(self, lines): + self.current().writelines(lines) + + def flush(self): + self.current().flush() + + def close(self): + """Close the current file. If the current file is the bottom, then + close it and dispose of it.""" + current = self.current() + if current is self.bottom: + self.bottom = None + current.close() + + def _testProxy(self): pass + + +class Filter: + + """An abstract filter.""" + + def __init__(self): + if self.__class__ is Filter: + raise NotImplementedError + self.sink = None + + def next(self): + """Return the next filter/file-like object in the sequence, or None.""" + return self.sink + + def write(self, data): + """The standard write method; this must be overridden in subclasses.""" + raise NotImplementedError + + def writelines(self, lines): + """Standard writelines wrapper.""" + for line in lines: + self.write(line) + + def _flush(self): + """The _flush method should always flush the sink and should not + be overridden.""" + self.sink.flush() + + def flush(self): + """The flush method can be overridden.""" + self._flush() + + def close(self): + """Close the filter. Do an explicit flush first, then close the + sink.""" + self.flush() + self.sink.close() + + def attach(self, filter): + """Attach a filter to this one.""" + if self.sink is not None: + # If it's already attached, detach it first. + self.detach() + self.sink = filter + + def detach(self): + """Detach a filter from its sink.""" + self.flush() + self._flush() # do a guaranteed flush to just to be safe + self.sink = None + + def last(self): + """Find the last filter in this chain.""" + this, last = self, self + while this is not None: + last = this + this = this.next() + return last + +class NullFilter(Filter): + + """A filter that never sends any output to its sink.""" + + def write(self, data): pass + +class FunctionFilter(Filter): + + """A filter that works simply by pumping its input through a + function which maps strings into strings.""" + + def __init__(self, function): + Filter.__init__(self) + self.function = function + + def write(self, data): + self.sink.write(self.function(data)) + +class StringFilter(Filter): + + """A filter that takes a translation string (256 characters) and + filters any incoming data through it.""" + + def __init__(self, table): + if not (type(table) == types.StringType and len(table) == 256): + raise FilterError, "table must be 256-character string" + Filter.__init__(self) + self.table = table + + def write(self, data): + self.sink.write(string.translate(data, self.table)) + +class BufferedFilter(Filter): + + """A buffered filter is one that doesn't modify the source data + sent to the sink, but instead holds it for a time. The standard + variety only sends the data along when it receives a flush + command.""" + + def __init__(self): + Filter.__init__(self) + self.buffer = '' + + def write(self, data): + self.buffer = self.buffer + data + + def flush(self): + if self.buffer: + self.sink.write(self.buffer) + self._flush() + +class SizeBufferedFilter(BufferedFilter): + + """A size-buffered filter only in fixed size chunks (excepting the + final chunk).""" + + def __init__(self, bufferSize): + BufferedFilter.__init__(self) + self.bufferSize = bufferSize + + def write(self, data): + BufferedFilter.write(self, data) + while len(self.buffer) > self.bufferSize: + chunk, self.buffer = \ + self.buffer[:self.bufferSize], self.buffer[self.bufferSize:] + self.sink.write(chunk) + +class LineBufferedFilter(BufferedFilter): + + """A line-buffered filter only lets data through when it sees + whole lines.""" + + def __init__(self): + BufferedFilter.__init__(self) + + def write(self, data): + BufferedFilter.write(self, data) + chunks = string.split(self.buffer, '\n') + for chunk in chunks[:-1]: + self.sink.write(chunk + '\n') + self.buffer = chunks[-1] + +class MaximallyBufferedFilter(BufferedFilter): + + """A maximally-buffered filter only lets its data through on the final + close. It ignores flushes.""" + + def __init__(self): + BufferedFilter.__init__(self) + + def flush(self): pass + + def close(self): + if self.buffer: + BufferedFilter.flush(self) + self.sink.close() + + +class Context: + + """An interpreter context, which encapsulates a name, an input + file object, and a parser object.""" + + DEFAULT_UNIT = 'lines' + + def __init__(self, name, line=0, units=DEFAULT_UNIT): + self.name = name + self.line = line + self.units = units + self.pause = False + + def bump(self, quantity=1): + if self.pause: + self.pause = False + else: + self.line = self.line + quantity + + def identify(self): + return self.name, self.line + + def __str__(self): + if self.units == self.DEFAULT_UNIT: + return "%s:%s" % (self.name, self.line) + else: + return "%s:%s[%s]" % (self.name, self.line, self.units) + + +class Hook: + + """The base class for implementing hooks.""" + + def __init__(self): + self.interpreter = None + + def register(self, interpreter): + self.interpreter = interpreter + + def deregister(self, interpreter): + if interpreter is not self.interpreter: + raise Error, "hook not associated with this interpreter" + self.interpreter = None + + def push(self): + self.interpreter.push() + + def pop(self): + self.interpreter.pop() + + def null(self): pass + + def atStartup(self): pass + def atReady(self): pass + def atFinalize(self): pass + def atShutdown(self): pass + def atParse(self, scanner, locals): pass + def atToken(self, token): pass + def atHandle(self, meta): pass + def atInteract(self): pass + + def beforeInclude(self, name, file, locals): pass + def afterInclude(self): pass + + def beforeExpand(self, string, locals): pass + def afterExpand(self, result): pass + + def beforeFile(self, name, file, locals): pass + def afterFile(self): pass + + def beforeBinary(self, name, file, chunkSize, locals): pass + def afterBinary(self): pass + + def beforeString(self, name, string, locals): pass + def afterString(self): pass + + def beforeQuote(self, string): pass + def afterQuote(self, result): pass + + def beforeEscape(self, string, more): pass + def afterEscape(self, result): pass + + def beforeControl(self, type, rest, locals): pass + def afterControl(self): pass + + def beforeSignificate(self, key, value, locals): pass + def afterSignificate(self): pass + + def beforeAtomic(self, name, value, locals): pass + def afterAtomic(self): pass + + def beforeMulti(self, name, values, locals): pass + def afterMulti(self): pass + + def beforeImport(self, name, locals): pass + def afterImport(self): pass + + def beforeClause(self, catch, locals): pass + def afterClause(self, exception, variable): pass + + def beforeSerialize(self, expression, locals): pass + def afterSerialize(self): pass + + def beforeDefined(self, name, locals): pass + def afterDefined(self, result): pass + + def beforeLiteral(self, text): pass + def afterLiteral(self): pass + + def beforeEvaluate(self, expression, locals): pass + def afterEvaluate(self, result): pass + + def beforeExecute(self, statements, locals): pass + def afterExecute(self): pass + + def beforeSingle(self, source, locals): pass + def afterSingle(self): pass + +class VerboseHook(Hook): + + """A verbose hook that reports all information received by the + hook interface. This class dynamically scans the Hook base class + to ensure that all hook methods are properly represented.""" + + EXEMPT_ATTRIBUTES = ['register', 'deregister', 'push', 'pop'] + + def __init__(self, output=sys.stderr): + Hook.__init__(self) + self.output = output + self.indent = 0 + + class FakeMethod: + """This is a proxy method-like object.""" + def __init__(self, hook, name): + self.hook = hook + self.name = name + + def __call__(self, **keywords): + self.hook.output.write("%s%s: %s\n" % \ + (' ' * self.hook.indent, \ + self.name, repr(keywords))) + + for attribute in dir(Hook): + if attribute[:1] != '_' and \ + attribute not in self.EXEMPT_ATTRIBUTES: + self.__dict__[attribute] = FakeMethod(self, attribute) + + +class Token: + + """An element of expansion.""" + + def run(self, interpreter, locals): + raise NotImplementedError + + def string(self): + raise NotImplementedError + + def __str__(self): return self.string() + +class NullToken(Token): + """A chunk of data not containing markups.""" + def __init__(self, data): + self.data = data + + def run(self, interpreter, locals): + interpreter.write(self.data) + + def string(self): + return self.data + +class ExpansionToken(Token): + """A token that involves an expansion.""" + def __init__(self, prefix, first): + self.prefix = prefix + self.first = first + + def scan(self, scanner): + pass + + def run(self, interpreter, locals): + pass + +class WhitespaceToken(ExpansionToken): + """A whitespace markup.""" + def string(self): + return '%s%s' % (self.prefix, self.first) + +class LiteralToken(ExpansionToken): + """A literal markup.""" + def run(self, interpreter, locals): + interpreter.write(self.first) + + def string(self): + return '%s%s' % (self.prefix, self.first) + +class PrefixToken(ExpansionToken): + """A prefix markup.""" + def run(self, interpreter, locals): + interpreter.write(interpreter.prefix) + + def string(self): + return self.prefix * 2 + +class CommentToken(ExpansionToken): + """A comment markup.""" + def scan(self, scanner): + loc = scanner.find('\n') + if loc >= 0: + self.comment = scanner.chop(loc, 1) + else: + raise TransientParseError, "comment expects newline" + + def string(self): + return '%s#%s\n' % (self.prefix, self.comment) + +class ContextNameToken(ExpansionToken): + """A context name change markup.""" + def scan(self, scanner): + loc = scanner.find('\n') + if loc >= 0: + self.name = string.strip(scanner.chop(loc, 1)) + else: + raise TransientParseError, "context name expects newline" + + def run(self, interpreter, locals): + context = interpreter.context() + context.name = self.name + +class ContextLineToken(ExpansionToken): + """A context line change markup.""" + def scan(self, scanner): + loc = scanner.find('\n') + if loc >= 0: + try: + self.line = int(scanner.chop(loc, 1)) + except ValueError: + raise ParseError, "context line requires integer" + else: + raise TransientParseError, "context line expects newline" + + def run(self, interpreter, locals): + context = interpreter.context() + context.line = self.line + context.pause = True + +class EscapeToken(ExpansionToken): + """An escape markup.""" + def scan(self, scanner): + try: + code = scanner.chop(1) + result = None + if code in '()[]{}\'\"\\': # literals + result = code + elif code == '0': # NUL + result = '\x00' + elif code == 'a': # BEL + result = '\x07' + elif code == 'b': # BS + result = '\x08' + elif code == 'd': # decimal code + decimalCode = scanner.chop(3) + result = chr(string.atoi(decimalCode, 10)) + elif code == 'e': # ESC + result = '\x1b' + elif code == 'f': # FF + result = '\x0c' + elif code == 'h': # DEL + result = '\x7f' + elif code == 'n': # LF (newline) + result = '\x0a' + elif code == 'N': # Unicode character name + theSubsystem.assertUnicode() + import unicodedata + if scanner.chop(1) != '{': + raise ParseError, r"Unicode name escape should be \N{...}" + i = scanner.find('}') + name = scanner.chop(i, 1) + try: + result = unicodedata.lookup(name) + except KeyError: + raise SubsystemError, \ + "unknown Unicode character name: %s" % name + elif code == 'o': # octal code + octalCode = scanner.chop(3) + result = chr(string.atoi(octalCode, 8)) + elif code == 'q': # quaternary code + quaternaryCode = scanner.chop(4) + result = chr(string.atoi(quaternaryCode, 4)) + elif code == 'r': # CR + result = '\x0d' + elif code in 's ': # SP + result = ' ' + elif code == 't': # HT + result = '\x09' + elif code in 'u': # Unicode 16-bit hex literal + theSubsystem.assertUnicode() + hexCode = scanner.chop(4) + result = unichr(string.atoi(hexCode, 16)) + elif code in 'U': # Unicode 32-bit hex literal + theSubsystem.assertUnicode() + hexCode = scanner.chop(8) + result = unichr(string.atoi(hexCode, 16)) + elif code == 'v': # VT + result = '\x0b' + elif code == 'x': # hexadecimal code + hexCode = scanner.chop(2) + result = chr(string.atoi(hexCode, 16)) + elif code == 'z': # EOT + result = '\x04' + elif code == '^': # control character + controlCode = string.upper(scanner.chop(1)) + if controlCode >= '@' and controlCode <= '`': + result = chr(ord(controlCode) - ord('@')) + elif controlCode == '?': + result = '\x7f' + else: + raise ParseError, "invalid escape control code" + else: + raise ParseError, "unrecognized escape code" + assert result is not None + self.code = result + except ValueError: + raise ParseError, "invalid numeric escape code" + + def run(self, interpreter, locals): + interpreter.write(self.code) + + def string(self): + return '%s\\x%02x' % (self.prefix, ord(self.code)) + +class SignificatorToken(ExpansionToken): + """A significator markup.""" + def scan(self, scanner): + loc = scanner.find('\n') + if loc >= 0: + line = scanner.chop(loc, 1) + if not line: + raise ParseError, "significator must have nonblank key" + if line[0] in ' \t\v\n': + raise ParseError, "no whitespace between % and key" + # Work around a subtle CPython-Jython difference by stripping + # the string before splitting it: 'a '.split(None, 1) has two + # elements in Jython 2.1). + fields = string.split(string.strip(line), None, 1) + if len(fields) == 2 and fields[1] == '': + fields.pop() + self.key = fields[0] + if len(fields) < 2: + fields.append(None) + self.key, self.valueCode = fields + else: + raise TransientParseError, "significator expects newline" + + def run(self, interpreter, locals): + value = self.valueCode + if value is not None: + value = interpreter.evaluate(string.strip(value), locals) + interpreter.significate(self.key, value) + + def string(self): + if self.valueCode is None: + return '%s%%%s\n' % (self.prefix, self.key) + else: + return '%s%%%s %s\n' % (self.prefix, self.key, self.valueCode) + +class ExpressionToken(ExpansionToken): + """An expression markup.""" + def scan(self, scanner): + z = scanner.complex('(', ')', 0) + try: + q = scanner.next('$', 0, z, True) + except ParseError: + q = z + try: + i = scanner.next('?', 0, q, True) + try: + j = scanner.next('!', i, q, True) + except ParseError: + try: + j = scanner.next(':', i, q, True) # DEPRECATED + except ParseError: + j = q + except ParseError: + i = j = q + code = scanner.chop(z, 1) + self.testCode = code[:i] + self.thenCode = code[i + 1:j] + self.elseCode = code[j + 1:q] + self.exceptCode = code[q + 1:z] + + def run(self, interpreter, locals): + try: + result = interpreter.evaluate(self.testCode, locals) + if self.thenCode: + if result: + result = interpreter.evaluate(self.thenCode, locals) + else: + if self.elseCode: + result = interpreter.evaluate(self.elseCode, locals) + else: + result = None + except SyntaxError: + # Don't catch syntax errors; let them through. + raise + except: + if self.exceptCode: + result = interpreter.evaluate(self.exceptCode, locals) + else: + raise + if result is not None: + interpreter.write(str(result)) + + def string(self): + result = self.testCode + if self.thenCode: + result = result + '?' + self.thenCode + if self.elseCode: + result = result + '!' + self.elseCode + if self.exceptCode: + result = result + '$' + self.exceptCode + return '%s(%s)' % (self.prefix, result) + +class StringLiteralToken(ExpansionToken): + """A string token markup.""" + def scan(self, scanner): + scanner.retreat() + assert scanner[0] == self.first + i = scanner.quote() + self.literal = scanner.chop(i) + + def run(self, interpreter, locals): + interpreter.literal(self.literal) + + def string(self): + return '%s%s' % (self.prefix, self.literal) + +class SimpleExpressionToken(ExpansionToken): + """A simple expression markup.""" + def scan(self, scanner): + i = scanner.simple() + self.code = self.first + scanner.chop(i) + + def run(self, interpreter, locals): + interpreter.serialize(self.code, locals) + + def string(self): + return '%s%s' % (self.prefix, self.code) + +class ReprToken(ExpansionToken): + """A repr markup.""" + def scan(self, scanner): + i = scanner.next('`', 0) + self.code = scanner.chop(i, 1) + + def run(self, interpreter, locals): + interpreter.write(repr(interpreter.evaluate(self.code, locals))) + + def string(self): + return '%s`%s`' % (self.prefix, self.code) + +class InPlaceToken(ExpansionToken): + """An in-place markup.""" + def scan(self, scanner): + i = scanner.next(':', 0) + j = scanner.next(':', i + 1) + self.code = scanner.chop(i, j - i + 1) + + def run(self, interpreter, locals): + interpreter.write("%s:%s:" % (interpreter.prefix, self.code)) + try: + interpreter.serialize(self.code, locals) + finally: + interpreter.write(":") + + def string(self): + return '%s:%s::' % (self.prefix, self.code) + +class StatementToken(ExpansionToken): + """A statement markup.""" + def scan(self, scanner): + i = scanner.complex('{', '}', 0) + self.code = scanner.chop(i, 1) + + def run(self, interpreter, locals): + interpreter.execute(self.code, locals) + + def string(self): + return '%s{%s}' % (self.prefix, self.code) + +class CustomToken(ExpansionToken): + """A custom markup.""" + def scan(self, scanner): + i = scanner.complex('<', '>', 0) + self.contents = scanner.chop(i, 1) + + def run(self, interpreter, locals): + interpreter.invokeCallback(self.contents) + + def string(self): + return '%s<%s>' % (self.prefix, self.contents) + +class ControlToken(ExpansionToken): + + """A control token.""" + + PRIMARY_TYPES = ['if', 'for', 'while', 'try', 'def'] + SECONDARY_TYPES = ['elif', 'else', 'except', 'finally'] + TERTIARY_TYPES = ['continue', 'break'] + GREEDY_TYPES = ['if', 'elif', 'for', 'while', 'def', 'end'] + END_TYPES = ['end'] + + IN_RE = re.compile(r"\bin\b") + + def scan(self, scanner): + scanner.acquire() + i = scanner.complex('[', ']', 0) + self.contents = scanner.chop(i, 1) + fields = string.split(string.strip(self.contents), ' ', 1) + if len(fields) > 1: + self.type, self.rest = fields + else: + self.type = fields[0] + self.rest = None + self.subtokens = [] + if self.type in self.GREEDY_TYPES and self.rest is None: + raise ParseError, "control '%s' needs arguments" % self.type + if self.type in self.PRIMARY_TYPES: + self.subscan(scanner, self.type) + self.kind = 'primary' + elif self.type in self.SECONDARY_TYPES: + self.kind = 'secondary' + elif self.type in self.TERTIARY_TYPES: + self.kind = 'tertiary' + elif self.type in self.END_TYPES: + self.kind = 'end' + else: + raise ParseError, "unknown control markup: '%s'" % self.type + scanner.release() + + def subscan(self, scanner, primary): + """Do a subscan for contained tokens.""" + while True: + token = scanner.one() + if token is None: + raise TransientParseError, \ + "control '%s' needs more tokens" % primary + if isinstance(token, ControlToken) and \ + token.type in self.END_TYPES: + if token.rest != primary: + raise ParseError, \ + "control must end with 'end %s'" % primary + break + self.subtokens.append(token) + + def build(self, allowed=None): + """Process the list of subtokens and divide it into a list of + 2-tuples, consisting of the dividing tokens and the list of + subtokens that follow them. If allowed is specified, it will + represent the list of the only secondary markup types which + are allowed.""" + if allowed is None: + allowed = SECONDARY_TYPES + result = [] + latest = [] + result.append((self, latest)) + for subtoken in self.subtokens: + if isinstance(subtoken, ControlToken) and \ + subtoken.kind == 'secondary': + if subtoken.type not in allowed: + raise ParseError, \ + "control unexpected secondary: '%s'" % subtoken.type + latest = [] + result.append((subtoken, latest)) + else: + latest.append(subtoken) + return result + + def run(self, interpreter, locals): + interpreter.invoke('beforeControl', type=self.type, rest=self.rest, \ + locals=locals) + if self.type == 'if': + info = self.build(['elif', 'else']) + elseTokens = None + if info[-1][0].type == 'else': + elseTokens = info.pop()[1] + for secondary, subtokens in info: + if secondary.type not in ('if', 'elif'): + raise ParseError, \ + "control 'if' unexpected secondary: '%s'" % secondary.type + if interpreter.evaluate(secondary.rest, locals): + self.subrun(subtokens, interpreter, locals) + break + else: + if elseTokens: + self.subrun(elseTokens, interpreter, locals) + elif self.type == 'for': + sides = self.IN_RE.split(self.rest, 1) + if len(sides) != 2: + raise ParseError, "control expected 'for x in seq'" + iterator, sequenceCode = sides + info = self.build(['else']) + elseTokens = None + if info[-1][0].type == 'else': + elseTokens = info.pop()[1] + if len(info) != 1: + raise ParseError, "control 'for' expects at most one 'else'" + sequence = interpreter.evaluate(sequenceCode, locals) + for element in sequence: + try: + interpreter.assign(iterator, element, locals) + self.subrun(info[0][1], interpreter, locals) + except ContinueFlow: + continue + except BreakFlow: + break + else: + if elseTokens: + self.subrun(elseTokens, interpreter, locals) + elif self.type == 'while': + testCode = self.rest + info = self.build(['else']) + elseTokens = None + if info[-1][0].type == 'else': + elseTokens = info.pop()[1] + if len(info) != 1: + raise ParseError, "control 'while' expects at most one 'else'" + atLeastOnce = False + while True: + try: + if not interpreter.evaluate(testCode, locals): + break + atLeastOnce = True + self.subrun(info[0][1], interpreter, locals) + except ContinueFlow: + continue + except BreakFlow: + break + if not atLeastOnce and elseTokens: + self.subrun(elseTokens, interpreter, locals) + elif self.type == 'try': + info = self.build(['except', 'finally']) + if len(info) == 1: + raise ParseError, "control 'try' needs 'except' or 'finally'" + type = info[-1][0].type + if type == 'except': + for secondary, _tokens in info[1:]: + if secondary.type != 'except': + raise ParseError, \ + "control 'try' cannot have 'except' and 'finally'" + else: + assert type == 'finally' + if len(info) != 2: + raise ParseError, \ + "control 'try' can only have one 'finally'" + if type == 'except': + try: + self.subrun(info[0][1], interpreter, locals) + except FlowError: + raise + except Exception, e: + for secondary, tokens in info[1:]: + exception, variable = interpreter.clause(secondary.rest) + if variable is not None: + interpreter.assign(variable, e) + if isinstance(e, exception): + self.subrun(tokens, interpreter, locals) + break + else: + raise + else: + try: + self.subrun(info[0][1], interpreter, locals) + finally: + self.subrun(info[1][1], interpreter, locals) + elif self.type == 'continue': + raise ContinueFlow, "control 'continue' without 'for', 'while'" + elif self.type == 'break': + raise BreakFlow, "control 'break' without 'for', 'while'" + elif self.type == 'def': + signature = self.rest + definition = self.substring() + code = 'def %s:\n' \ + ' r"""%s"""\n' \ + ' return %s.expand(r"""%s""", locals())\n' % \ + (signature, definition, interpreter.pseudo, definition) + interpreter.execute(code, locals) + elif self.type == 'end': + raise ParseError, "control 'end' requires primary markup" + else: + raise ParseError, \ + "control '%s' cannot be at this level" % self.type + interpreter.invoke('afterControl') + + def subrun(self, tokens, interpreter, locals): + """Execute a sequence of tokens.""" + for token in tokens: + token.run(interpreter, locals) + + def substring(self): + return string.join(map(str, self.subtokens), '') + + def string(self): + if self.kind == 'primary': + return '%s[%s]%s%s[end %s]' % \ + (self.prefix, self.contents, self.substring(), \ + self.prefix, self.type) + else: + return '%s[%s]' % (self.prefix, self.contents) + + +class Scanner: + + """A scanner holds a buffer for lookahead parsing and has the + ability to scan for special symbols and indicators in that + buffer.""" + + # This is the token mapping table that maps first characters to + # token classes. + TOKEN_MAP = [ + (None, PrefixToken), + (' \t\v\r\n', WhitespaceToken), + (')]}', LiteralToken), + ('\\', EscapeToken), + ('#', CommentToken), + ('?', ContextNameToken), + ('!', ContextLineToken), + ('%', SignificatorToken), + ('(', ExpressionToken), + (IDENTIFIER_FIRST_CHARS, SimpleExpressionToken), + ('\'\"', StringLiteralToken), + ('`', ReprToken), + (':', InPlaceToken), + ('[', ControlToken), + ('{', StatementToken), + ('<', CustomToken), + ] + + def __init__(self, prefix, data=''): + self.prefix = prefix + self.pointer = 0 + self.buffer = data + self.lock = 0 + + def __nonzero__(self): return self.pointer < len(self.buffer) + def __len__(self): return len(self.buffer) - self.pointer + def __getitem__(self, index): return self.buffer[self.pointer + index] + + def __getslice__(self, start, stop): + if stop > len(self): + stop = len(self) + return self.buffer[self.pointer + start:self.pointer + stop] + + def advance(self, count=1): + """Advance the pointer count characters.""" + self.pointer = self.pointer + count + + def retreat(self, count=1): + self.pointer = self.pointer - count + if self.pointer < 0: + raise ParseError, "can't retreat back over synced out chars" + + def set(self, data): + """Start the scanner digesting a new batch of data; start the pointer + over from scratch.""" + self.pointer = 0 + self.buffer = data + + def feed(self, data): + """Feed some more data to the scanner.""" + self.buffer = self.buffer + data + + def chop(self, count=None, slop=0): + """Chop the first count + slop characters off the front, and return + the first count. If count is not specified, then return + everything.""" + if count is None: + assert slop == 0 + count = len(self) + if count > len(self): + raise TransientParseError, "not enough data to read" + result = self[:count] + self.advance(count + slop) + return result + + def acquire(self): + """Lock the scanner so it doesn't destroy data on sync.""" + self.lock = self.lock + 1 + + def release(self): + """Unlock the scanner.""" + self.lock = self.lock - 1 + + def sync(self): + """Sync up the buffer with the read head.""" + if self.lock == 0 and self.pointer != 0: + self.buffer = self.buffer[self.pointer:] + self.pointer = 0 + + def unsync(self): + """Undo changes; reset the read head.""" + if self.pointer != 0: + self.lock = 0 + self.pointer = 0 + + def rest(self): + """Get the remainder of the buffer.""" + return self[:] + + def read(self, i=0, count=1): + """Read count chars starting from i; raise a transient error if + there aren't enough characters remaining.""" + if len(self) < i + count: + raise TransientParseError, "need more data to read" + else: + return self[i:i + count] + + def check(self, i, archetype=None): + """Scan for the next single or triple quote, with the specified + archetype. Return the found quote or None.""" + quote = None + if self[i] in '\'\"': + quote = self[i] + if len(self) - i < 3: + for j in range(i, len(self)): + if self[i] == quote: + return quote + else: + raise TransientParseError, "need to scan for rest of quote" + if self[i + 1] == self[i + 2] == quote: + quote = quote * 3 + if quote is not None: + if archetype is None: + return quote + else: + if archetype == quote: + return quote + elif len(archetype) < len(quote) and archetype[0] == quote[0]: + return archetype + else: + return None + else: + return None + + def find(self, sub, start=0, end=None): + """Find the next occurrence of the character, or return -1.""" + if end is not None: + return string.find(self.rest(), sub, start, end) + else: + return string.find(self.rest(), sub, start) + + def last(self, char, start=0, end=None): + """Find the first character that is _not_ the specified character.""" + if end is None: + end = len(self) + i = start + while i < end: + if self[i] != char: + return i + i = i + 1 + else: + raise TransientParseError, "expecting other than %s" % char + + def next(self, target, start=0, end=None, mandatory=False): + """Scan for the next occurrence of one of the characters in + the target string; optionally, make the scan mandatory.""" + if mandatory: + assert end is not None + quote = None + if end is None: + end = len(self) + i = start + while i < end: + newQuote = self.check(i, quote) + if newQuote: + if newQuote == quote: + quote = None + else: + quote = newQuote + i = i + len(newQuote) + else: + c = self[i] + if quote: + if c == '\\': + i = i + 1 + else: + if c in target: + return i + i = i + 1 + else: + if mandatory: + raise ParseError, "expecting %s, not found" % target + else: + raise TransientParseError, "expecting ending character" + + def quote(self, start=0, end=None, mandatory=False): + """Scan for the end of the next quote.""" + assert self[start] in '\'\"' + quote = self.check(start) + if end is None: + end = len(self) + i = start + len(quote) + while i < end: + newQuote = self.check(i, quote) + if newQuote: + i = i + len(newQuote) + if newQuote == quote: + return i + else: + c = self[i] + if c == '\\': + i = i + 1 + i = i + 1 + else: + if mandatory: + raise ParseError, "expecting end of string literal" + else: + raise TransientParseError, "expecting end of string literal" + + def nested(self, enter, exit, start=0, end=None): + """Scan from i for an ending sequence, respecting entries and exits + only.""" + depth = 0 + if end is None: + end = len(self) + i = start + while i < end: + c = self[i] + if c == enter: + depth = depth + 1 + elif c == exit: + depth = depth - 1 + if depth < 0: + return i + i = i + 1 + else: + raise TransientParseError, "expecting end of complex expression" + + def complex(self, enter, exit, start=0, end=None, skip=None): + """Scan from i for an ending sequence, respecting quotes, + entries and exits.""" + quote = None + depth = 0 + if end is None: + end = len(self) + last = None + i = start + while i < end: + newQuote = self.check(i, quote) + if newQuote: + if newQuote == quote: + quote = None + else: + quote = newQuote + i = i + len(newQuote) + else: + c = self[i] + if quote: + if c == '\\': + i = i + 1 + else: + if skip is None or last != skip: + if c == enter: + depth = depth + 1 + elif c == exit: + depth = depth - 1 + if depth < 0: + return i + last = c + i = i + 1 + else: + raise TransientParseError, "expecting end of complex expression" + + def word(self, start=0): + """Scan from i for a simple word.""" + length = len(self) + i = start + while i < length: + if not self[i] in IDENTIFIER_CHARS: + return i + i = i + 1 + else: + raise TransientParseError, "expecting end of word" + + def phrase(self, start=0): + """Scan from i for a phrase (e.g., 'word', 'f(a, b, c)', 'a[i]', or + combinations like 'x[i](a)'.""" + # Find the word. + i = self.word(start) + while i < len(self) and self[i] in '([{': + enter = self[i] + if enter == '{': + raise ParseError, "curly braces can't open simple expressions" + exit = ENDING_CHARS[enter] + i = self.complex(enter, exit, i + 1) + 1 + return i + + def simple(self, start=0): + """Scan from i for a simple expression, which consists of one + more phrases separated by dots.""" + i = self.phrase(start) + length = len(self) + while i < length and self[i] == '.': + i = self.phrase(i) + # Make sure we don't end with a trailing dot. + while i > 0 and self[i - 1] == '.': + i = i - 1 + return i + + def one(self): + """Parse and return one token, or None if the scanner is empty.""" + if not self: + return None + if not self.prefix: + loc = -1 + else: + loc = self.find(self.prefix) + if loc < 0: + # If there's no prefix in the buffer, then set the location to + # the end so the whole thing gets processed. + loc = len(self) + if loc == 0: + # If there's a prefix at the beginning of the buffer, process + # an expansion. + prefix = self.chop(1) + assert prefix == self.prefix + first = self.chop(1) + if first == self.prefix: + first = None + for firsts, factory in self.TOKEN_MAP: + if firsts is None: + if first is None: + break + elif first in firsts: + break + else: + raise ParseError, "unknown markup: %s%s" % (self.prefix, first) + token = factory(self.prefix, first) + try: + token.scan(self) + except TransientParseError: + # If a transient parse error occurs, reset the buffer pointer + # so we can (conceivably) try again later. + self.unsync() + raise + else: + # Process everything up to loc as a null token. + data = self.chop(loc) + token = NullToken(data) + self.sync() + return token + + +class Interpreter: + + """An interpreter can process chunks of EmPy code.""" + + # Constants. + + VERSION = __version__ + SIGNIFICATOR_RE_SUFFIX = SIGNIFICATOR_RE_SUFFIX + SIGNIFICATOR_RE_STRING = None + + # Types. + + Interpreter = None # define this below to prevent a circular reference + Hook = Hook # DEPRECATED + Filter = Filter # DEPRECATED + NullFilter = NullFilter # DEPRECATED + FunctionFilter = FunctionFilter # DEPRECATED + StringFilter = StringFilter # DEPRECATED + BufferedFilter = BufferedFilter # DEPRECATED + SizeBufferedFilter = SizeBufferedFilter # DEPRECATED + LineBufferedFilter = LineBufferedFilter # DEPRECATED + MaximallyBufferedFilter = MaximallyBufferedFilter # DEPRECATED + + # Tables. + + ESCAPE_CODES = {0x00: '0', 0x07: 'a', 0x08: 'b', 0x1b: 'e', 0x0c: 'f', \ + 0x7f: 'h', 0x0a: 'n', 0x0d: 'r', 0x09: 't', 0x0b: 'v', \ + 0x04: 'z'} + + ASSIGN_TOKEN_RE = re.compile(r"[_a-zA-Z][_a-zA-Z0-9]*|\(|\)|,") + + DEFAULT_OPTIONS = {BANGPATH_OPT: True, + BUFFERED_OPT: False, + RAW_OPT: False, + EXIT_OPT: True, + FLATTEN_OPT: False, + OVERRIDE_OPT: True, + CALLBACK_OPT: False} + + _wasProxyInstalled = False # was a proxy installed? + + # Construction, initialization, destruction. + + def __init__(self, output=None, argv=None, prefix=DEFAULT_PREFIX, \ + pseudo=None, options=None, globals=None, hooks=None): + self.interpreter = self # DEPRECATED + # Set up the stream. + if output is None: + output = UncloseableFile(sys.__stdout__) + self.output = output + self.prefix = prefix + if pseudo is None: + pseudo = DEFAULT_PSEUDOMODULE_NAME + self.pseudo = pseudo + if argv is None: + argv = [DEFAULT_SCRIPT_NAME] + self.argv = argv + self.args = argv[1:] + if options is None: + options = {} + self.options = options + # Initialize any hooks. + self.hooksEnabled = None # special sentinel meaning "false until added" + self.hooks = [] + if hooks is None: + hooks = [] + for hook in hooks: + self.register(hook) + # Initialize callback. + self.callback = None + # Finalizers. + self.finals = [] + # The interpreter stacks. + self.contexts = Stack() + self.streams = Stack() + # Now set up the globals. + self.globals = globals + self.fix() + self.history = Stack() + # Install a proxy stdout if one hasn't been already. + self.installProxy() + # Finally, reset the state of all the stacks. + self.reset() + # Okay, now flatten the namespaces if that option has been set. + if self.options.get(FLATTEN_OPT, False): + self.flatten() + # Set up old pseudomodule attributes. + if prefix is None: + self.SIGNIFICATOR_RE_STRING = None + else: + self.SIGNIFICATOR_RE_STRING = prefix + self.SIGNIFICATOR_RE_SUFFIX + self.Interpreter = self.__class__ + # Done. Now declare that we've started up. + self.invoke('atStartup') + + def __del__(self): + self.shutdown() + + def __repr__(self): + return '<%s pseudomodule/interpreter at 0x%x>' % \ + (self.pseudo, id(self)) + + def ready(self): + """Declare the interpreter ready for normal operations.""" + self.invoke('atReady') + + def fix(self): + """Reset the globals, stamping in the pseudomodule.""" + if self.globals is None: + self.globals = {} + # Make sure that there is no collision between two interpreters' + # globals. + if self.globals.has_key(self.pseudo): + if self.globals[self.pseudo] is not self: + raise Error, "interpreter globals collision" + self.globals[self.pseudo] = self + + def unfix(self): + """Remove the pseudomodule (if present) from the globals.""" + UNWANTED_KEYS = [self.pseudo, '__builtins__'] + for unwantedKey in UNWANTED_KEYS: + if self.globals.has_key(unwantedKey): + del self.globals[unwantedKey] + + def update(self, other): + """Update the current globals dictionary with another dictionary.""" + self.globals.update(other) + self.fix() + + def clear(self): + """Clear out the globals dictionary with a brand new one.""" + self.globals = {} + self.fix() + + def save(self, deep=True): + if deep: + copyMethod = copy.deepcopy + else: + copyMethod = copy.copy + """Save a copy of the current globals on the history stack.""" + self.unfix() + self.history.push(copyMethod(self.globals)) + self.fix() + + def restore(self, destructive=True): + """Restore the topmost historic globals.""" + if destructive: + fetchMethod = self.history.pop + else: + fetchMethod = self.history.top + self.unfix() + self.globals = fetchMethod() + self.fix() + + def shutdown(self): + """Declare this interpreting session over; close the stream file + object. This method is idempotent.""" + if self.streams is not None: + try: + self.finalize() + self.invoke('atShutdown') + while self.streams: + stream = self.streams.pop() + stream.close() + finally: + self.streams = None + + def ok(self): + """Is the interpreter still active?""" + return self.streams is not None + + # Writeable file-like methods. + + def write(self, data): + self.stream().write(data) + + def writelines(self, stuff): + self.stream().writelines(stuff) + + def flush(self): + self.stream().flush() + + def close(self): + self.shutdown() + + # Stack-related activity. + + def context(self): + return self.contexts.top() + + def stream(self): + return self.streams.top() + + def reset(self): + self.contexts.purge() + self.streams.purge() + self.streams.push(Stream(self.output)) + if self.options.get(OVERRIDE_OPT, True): + sys.stdout.clear(self) + + def push(self): + if self.options.get(OVERRIDE_OPT, True): + sys.stdout.push(self) + + def pop(self): + if self.options.get(OVERRIDE_OPT, True): + sys.stdout.pop(self) + + # Higher-level operations. + + def include(self, fileOrFilename, locals=None): + """Do an include pass on a file or filename.""" + if type(fileOrFilename) is types.StringType: + # Either it's a string representing a filename ... + filename = fileOrFilename + name = filename + file = theSubsystem.open(filename, 'r') + else: + # ... or a file object. + file = fileOrFilename + name = "<%s>" % str(file.__class__) + self.invoke('beforeInclude', name=name, file=file, locals=locals) + self.file(file, name, locals) + self.invoke('afterInclude') + + def expand(self, data, locals=None): + """Do an explicit expansion on a subordinate stream.""" + outFile = StringIO.StringIO() + stream = Stream(outFile) + self.invoke('beforeExpand', string=data, locals=locals) + self.streams.push(stream) + try: + self.string(data, '<expand>', locals) + stream.flush() + expansion = outFile.getvalue() + self.invoke('afterExpand', result=expansion) + return expansion + finally: + self.streams.pop() + + def quote(self, data): + """Quote the given string so that if it were expanded it would + evaluate to the original.""" + self.invoke('beforeQuote', string=data) + scanner = Scanner(self.prefix, data) + result = [] + i = 0 + try: + j = scanner.next(self.prefix, i) + result.append(data[i:j]) + result.append(self.prefix * 2) + i = j + 1 + except TransientParseError: + pass + result.append(data[i:]) + result = string.join(result, '') + self.invoke('afterQuote', result=result) + return result + + def escape(self, data, more=''): + """Escape a string so that nonprintable characters are replaced + with compatible EmPy expansions.""" + self.invoke('beforeEscape', string=data, more=more) + result = [] + for char in data: + if char < ' ' or char > '~': + charOrd = ord(char) + if Interpreter.ESCAPE_CODES.has_key(charOrd): + result.append(self.prefix + '\\' + \ + Interpreter.ESCAPE_CODES[charOrd]) + else: + result.append(self.prefix + '\\x%02x' % charOrd) + elif char in more: + result.append(self.prefix + '\\' + char) + else: + result.append(char) + result = string.join(result, '') + self.invoke('afterEscape', result=result) + return result + + # Processing. + + def wrap(self, callable, args): + """Wrap around an application of a callable and handle errors. + Return whether no error occurred.""" + try: + apply(callable, args) + self.reset() + return True + except KeyboardInterrupt, e: + # Handle keyboard interrupts specially: we should always exit + # from these. + self.fail(e, True) + except Exception, e: + # A standard exception (other than a keyboard interrupt). + self.fail(e) + except: + # If we get here, then either it's an exception not derived from + # Exception or it's a string exception, so get the error type + # from the sys module. + e = sys.exc_type + self.fail(e) + # An error occurred if we leak through to here, so do cleanup. + self.reset() + return False + + def interact(self): + """Perform interaction.""" + self.invoke('atInteract') + done = False + while not done: + result = self.wrap(self.file, (sys.stdin, '<interact>')) + if self.options.get(EXIT_OPT, True): + done = True + else: + if result: + done = True + else: + self.reset() + + def fail(self, error, fatal=False): + """Handle an actual error that occurred.""" + if self.options.get(BUFFERED_OPT, False): + try: + self.output.abort() + except AttributeError: + # If the output file object doesn't have an abort method, + # something got mismatched, but it's too late to do + # anything about it now anyway, so just ignore it. + pass + meta = self.meta(error) + self.handle(meta) + if self.options.get(RAW_OPT, False): + raise + if fatal or self.options.get(EXIT_OPT, True): + sys.exit(FAILURE_CODE) + + def file(self, file, name='<file>', locals=None): + """Parse the entire contents of a file-like object, line by line.""" + context = Context(name) + self.contexts.push(context) + self.invoke('beforeFile', name=name, file=file, locals=locals) + scanner = Scanner(self.prefix) + first = True + done = False + while not done: + self.context().bump() + line = file.readline() + if first: + if self.options.get(BANGPATH_OPT, True) and self.prefix: + # Replace a bangpath at the beginning of the first line + # with an EmPy comment. + if string.find(line, BANGPATH) == 0: + line = self.prefix + '#' + line[2:] + first = False + if line: + scanner.feed(line) + else: + done = True + self.safe(scanner, done, locals) + self.invoke('afterFile') + self.contexts.pop() + + def binary(self, file, name='<binary>', chunkSize=0, locals=None): + """Parse the entire contents of a file-like object, in chunks.""" + if chunkSize <= 0: + chunkSize = DEFAULT_CHUNK_SIZE + context = Context(name, units='bytes') + self.contexts.push(context) + self.invoke('beforeBinary', name=name, file=file, \ + chunkSize=chunkSize, locals=locals) + scanner = Scanner(self.prefix) + done = False + while not done: + chunk = file.read(chunkSize) + if chunk: + scanner.feed(chunk) + else: + done = True + self.safe(scanner, done, locals) + self.context().bump(len(chunk)) + self.invoke('afterBinary') + self.contexts.pop() + + def string(self, data, name='<string>', locals=None): + """Parse a string.""" + context = Context(name) + self.contexts.push(context) + self.invoke('beforeString', name=name, string=data, locals=locals) + context.bump() + scanner = Scanner(self.prefix, data) + self.safe(scanner, True, locals) + self.invoke('afterString') + self.contexts.pop() + + def safe(self, scanner, final=False, locals=None): + """Do a protected parse. Catch transient parse errors; if + final is true, then make a final pass with a terminator, + otherwise ignore the transient parse error (more data is + pending).""" + try: + self.parse(scanner, locals) + except TransientParseError: + if final: + # If the buffer doesn't end with a newline, try tacking on + # a dummy terminator. + buffer = scanner.rest() + if buffer and buffer[-1] != '\n': + scanner.feed(self.prefix + '\n') + # A TransientParseError thrown from here is a real parse + # error. + self.parse(scanner, locals) + + def parse(self, scanner, locals=None): + """Parse and run as much from this scanner as possible.""" + self.invoke('atParse', scanner=scanner, locals=locals) + while True: + token = scanner.one() + if token is None: + break + self.invoke('atToken', token=token) + token.run(self, locals) + + # Medium-level evaluation and execution. + + def tokenize(self, name): + """Take an lvalue string and return a name or a (possibly recursive) + list of names.""" + result = [] + stack = [result] + for garbage in self.ASSIGN_TOKEN_RE.split(name): + garbage = string.strip(garbage) + if garbage: + raise ParseError, "unexpected assignment token: '%s'" % garbage + tokens = self.ASSIGN_TOKEN_RE.findall(name) + # While processing, put a None token at the start of any list in which + # commas actually appear. + for token in tokens: + if token == '(': + stack.append([]) + elif token == ')': + top = stack.pop() + if len(top) == 1: + top = top[0] # no None token means that it's not a 1-tuple + elif top[0] is None: + del top[0] # remove the None token for real tuples + stack[-1].append(top) + elif token == ',': + if len(stack[-1]) == 1: + stack[-1].insert(0, None) + else: + stack[-1].append(token) + # If it's a 1-tuple at the top level, turn it into a real subsequence. + if result and result[0] is None: + result = [result[1:]] + if len(result) == 1: + return result[0] + else: + return result + + def significate(self, key, value=None, locals=None): + """Declare a significator.""" + self.invoke('beforeSignificate', key=key, value=value, locals=locals) + name = '__%s__' % key + self.atomic(name, value, locals) + self.invoke('afterSignificate') + + def atomic(self, name, value, locals=None): + """Do an atomic assignment.""" + self.invoke('beforeAtomic', name=name, value=value, locals=locals) + if locals is None: + self.globals[name] = value + else: + locals[name] = value + self.invoke('afterAtomic') + + def multi(self, names, values, locals=None): + """Do a (potentially recursive) assignment.""" + self.invoke('beforeMulti', names=names, values=values, locals=locals) + # No zip in 1.5, so we have to do it manually. + i = 0 + try: + values = tuple(values) + except TypeError: + raise TypeError, "unpack non-sequence" + if len(names) != len(values): + raise ValueError, "unpack tuple of wrong size" + for i in range(len(names)): + name = names[i] + if type(name) is types.StringType: + self.atomic(name, values[i], locals) + else: + self.multi(name, values[i], locals) + self.invoke('afterMulti') + + def assign(self, name, value, locals=None): + """Do a potentially complex (including tuple unpacking) assignment.""" + left = self.tokenize(name) + # The return value of tokenize can either be a string or a list of + # (lists of) strings. + if type(left) is types.StringType: + self.atomic(left, value, locals) + else: + self.multi(left, value, locals) + + def import_(self, name, locals=None): + """Do an import.""" + self.invoke('beforeImport', name=name, locals=locals) + self.execute('import %s' % name, locals) + self.invoke('afterImport') + + def clause(self, catch, locals=None): + """Given the string representation of an except clause, turn it into + a 2-tuple consisting of the class name, and either a variable name + or None.""" + self.invoke('beforeClause', catch=catch, locals=locals) + if catch is None: + exceptionCode, variable = None, None + elif string.find(catch, ',') >= 0: + exceptionCode, variable = string.split(string.strip(catch), ',', 1) + variable = string.strip(variable) + else: + exceptionCode, variable = string.strip(catch), None + if not exceptionCode: + exception = Exception + else: + exception = self.evaluate(exceptionCode, locals) + self.invoke('afterClause', exception=exception, variable=variable) + return exception, variable + + def serialize(self, expression, locals=None): + """Do an expansion, involving evaluating an expression, then + converting it to a string and writing that string to the + output if the evaluation is not None.""" + self.invoke('beforeSerialize', expression=expression, locals=locals) + result = self.evaluate(expression, locals) + if result is not None: + self.write(str(result)) + self.invoke('afterSerialize') + + def defined(self, name, locals=None): + """Return a Boolean indicating whether or not the name is + defined either in the locals or the globals.""" + self.invoke('beforeDefined', name=name, local=local) + if locals is not None: + if locals.has_key(name): + result = True + else: + result = False + elif self.globals.has_key(name): + result = True + else: + result = False + self.invoke('afterDefined', result=result) + + def literal(self, text): + """Process a string literal.""" + self.invoke('beforeLiteral', text=text) + self.serialize(text) + self.invoke('afterLiteral') + + # Low-level evaluation and execution. + + def evaluate(self, expression, locals=None): + """Evaluate an expression.""" + if expression in ('1', 'True'): return True + if expression in ('0', 'False'): return False + self.push() + try: + self.invoke('beforeEvaluate', \ + expression=expression, locals=locals) + if locals is not None: + result = eval(expression, self.globals, locals) + else: + result = eval(expression, self.globals) + self.invoke('afterEvaluate', result=result) + return result + finally: + self.pop() + + def execute(self, statements, locals=None): + """Execute a statement.""" + # If there are any carriage returns (as opposed to linefeeds/newlines) + # in the statements code, then remove them. Even on DOS/Windows + # platforms, + if string.find(statements, '\r') >= 0: + statements = string.replace(statements, '\r', '') + # If there are no newlines in the statements code, then strip any + # leading or trailing whitespace. + if string.find(statements, '\n') < 0: + statements = string.strip(statements) + self.push() + try: + self.invoke('beforeExecute', \ + statements=statements, locals=locals) + if locals is not None: + exec statements in self.globals, locals + else: + exec statements in self.globals + self.invoke('afterExecute') + finally: + self.pop() + + def single(self, source, locals=None): + """Execute an expression or statement, just as if it were + entered into the Python interactive interpreter.""" + self.push() + try: + self.invoke('beforeSingle', \ + source=source, locals=locals) + code = compile(source, '<single>', 'single') + if locals is not None: + exec code in self.globals, locals + else: + exec code in self.globals + self.invoke('afterSingle') + finally: + self.pop() + + # Hooks. + + def register(self, hook, prepend=False): + """Register the provided hook.""" + hook.register(self) + if self.hooksEnabled is None: + # A special optimization so that hooks can be effectively + # disabled until one is added or they are explicitly turned on. + self.hooksEnabled = True + if prepend: + self.hooks.insert(0, hook) + else: + self.hooks.append(hook) + + def deregister(self, hook): + """Remove an already registered hook.""" + hook.deregister(self) + self.hooks.remove(hook) + + def invoke(self, _name, **keywords): + """Invoke the hook(s) associated with the hook name, should they + exist.""" + if self.hooksEnabled: + for hook in self.hooks: + hook.push() + try: + method = getattr(hook, _name) + apply(method, (), keywords) + finally: + hook.pop() + + def finalize(self): + """Execute any remaining final routines.""" + self.push() + self.invoke('atFinalize') + try: + # Pop them off one at a time so they get executed in reverse + # order and we remove them as they're executed in case something + # bad happens. + while self.finals: + final = self.finals.pop() + final() + finally: + self.pop() + + # Error handling. + + def meta(self, exc=None): + """Construct a MetaError for the interpreter's current state.""" + return MetaError(self.contexts.clone(), exc) + + def handle(self, meta): + """Handle a MetaError.""" + first = True + self.invoke('atHandle', meta=meta) + for context in meta.contexts: + if first: + if meta.exc is not None: + desc = "error: %s: %s" % (meta.exc.__class__, meta.exc) + else: + desc = "error" + else: + desc = "from this context" + first = False + sys.stderr.write('%s: %s\n' % (context, desc)) + + def installProxy(self): + """Install a proxy if necessary.""" + # Unfortunately, there's no surefire way to make sure that installing + # a sys.stdout proxy is idempotent, what with different interpreters + # running from different modules. The best we can do here is to try + # manipulating the proxy's test function ... + try: + sys.stdout._testProxy() + except AttributeError: + # ... if the current stdout object doesn't have one, then check + # to see if we think _this_ particularly Interpreter class has + # installed it before ... + if Interpreter._wasProxyInstalled: + # ... and if so, we have a proxy problem. + raise Error, "interpreter stdout proxy lost" + else: + # Otherwise, install the proxy and set the flag. + sys.stdout = ProxyFile(sys.stdout) + Interpreter._wasProxyInstalled = True + + # + # Pseudomodule routines. + # + + # Identification. + + def identify(self): + """Identify the topmost context with a 2-tuple of the name and + line number.""" + return self.context().identify() + + def atExit(self, callable): + """Register a function to be called at exit.""" + self.finals.append(callable) + + # Context manipulation. + + def pushContext(self, name='<unnamed>', line=0): + """Create a new context and push it.""" + self.contexts.push(Context(name, line)) + + def popContext(self): + """Pop the top context.""" + self.contexts.pop() + + def setContextName(self, name): + """Set the name of the topmost context.""" + context = self.context() + context.name = name + + def setContextLine(self, line): + """Set the name of the topmost context.""" + context = self.context() + context.line = line + + setName = setContextName # DEPRECATED + setLine = setContextLine # DEPRECATED + + # Globals manipulation. + + def getGlobals(self): + """Retrieve the globals.""" + return self.globals + + def setGlobals(self, globals): + """Set the globals to the specified dictionary.""" + self.globals = globals + self.fix() + + def updateGlobals(self, otherGlobals): + """Merge another mapping object into this interpreter's globals.""" + self.update(otherGlobals) + + def clearGlobals(self): + """Clear out the globals with a brand new dictionary.""" + self.clear() + + def saveGlobals(self, deep=True): + """Save a copy of the globals off onto the history stack.""" + self.save(deep) + + def restoreGlobals(self, destructive=True): + """Restore the most recently saved copy of the globals.""" + self.restore(destructive) + + # Hook support. + + def areHooksEnabled(self): + """Return whether or not hooks are presently enabled.""" + if self.hooksEnabled is None: + return True + else: + return self.hooksEnabled + + def enableHooks(self): + """Enable hooks.""" + self.hooksEnabled = True + + def disableHooks(self): + """Disable hooks.""" + self.hooksEnabled = False + + def getHooks(self): + """Get the current hooks.""" + return self.hooks[:] + + def clearHooks(self): + """Clear all hooks.""" + self.hooks = [] + + def addHook(self, hook, prepend=False): + """Add a new hook; optionally insert it rather than appending it.""" + self.register(hook, prepend) + + def removeHook(self, hook): + """Remove a preexisting hook.""" + self.deregister(hook) + + def invokeHook(self, _name, **keywords): + """Manually invoke a hook.""" + apply(self.invoke, (_name,), keywords) + + # Callbacks. + + def getCallback(self): + """Get the callback registered with this interpreter, or None.""" + return self.callback + + def registerCallback(self, callback): + """Register a custom markup callback with this interpreter.""" + self.callback = callback + + def deregisterCallback(self): + """Remove any previously registered callback with this interpreter.""" + self.callback = None + + def invokeCallback(self, contents): + """Invoke the callback.""" + if self.callback is None: + if self.options.get(CALLBACK_OPT, False): + raise Error, "custom markup invoked with no defined callback" + else: + self.callback(contents) + + # Pseudomodule manipulation. + + def flatten(self, keys=None): + """Flatten the contents of the pseudo-module into the globals + namespace.""" + if keys is None: + keys = self.__dict__.keys() + self.__class__.__dict__.keys() + dict = {} + for key in keys: + # The pseudomodule is really a class instance, so we need to + # fumble use getattr instead of simply fumbling through the + # instance's __dict__. + dict[key] = getattr(self, key) + # Stomp everything into the globals namespace. + self.globals.update(dict) + + # Prefix. + + def getPrefix(self): + """Get the current prefix.""" + return self.prefix + + def setPrefix(self, prefix): + """Set the prefix.""" + self.prefix = prefix + + # Diversions. + + def stopDiverting(self): + """Stop any diverting.""" + self.stream().revert() + + def createDiversion(self, name): + """Create a diversion (but do not divert to it) if it does not + already exist.""" + self.stream().create(name) + + def retrieveDiversion(self, name): + """Retrieve the diversion object associated with the name.""" + return self.stream().retrieve(name) + + def startDiversion(self, name): + """Start diverting to the given diversion name.""" + self.stream().divert(name) + + def playDiversion(self, name): + """Play the given diversion and then purge it.""" + self.stream().undivert(name, True) + + def replayDiversion(self, name): + """Replay the diversion without purging it.""" + self.stream().undivert(name, False) + + def purgeDiversion(self, name): + """Eliminate the given diversion.""" + self.stream().purge(name) + + def playAllDiversions(self): + """Play all existing diversions and then purge them.""" + self.stream().undivertAll(True) + + def replayAllDiversions(self): + """Replay all existing diversions without purging them.""" + self.stream().undivertAll(False) + + def purgeAllDiversions(self): + """Purge all existing diversions.""" + self.stream().purgeAll() + + def getCurrentDiversion(self): + """Get the name of the current diversion.""" + return self.stream().currentDiversion + + def getAllDiversions(self): + """Get the names of all existing diversions.""" + names = self.stream().diversions.keys() + names.sort() + return names + + # Filter. + + def resetFilter(self): + """Reset the filter so that it does no filtering.""" + self.stream().install(None) + + def nullFilter(self): + """Install a filter that will consume all text.""" + self.stream().install(0) + + def getFilter(self): + """Get the current filter.""" + filter = self.stream().filter + if filter is self.stream().file: + return None + else: + return filter + + def setFilter(self, shortcut): + """Set the filter.""" + self.stream().install(shortcut) + + def attachFilter(self, shortcut): + """Attach a single filter to the end of the current filter chain.""" + self.stream().attach(shortcut) + + +class Document: + + """A representation of an individual EmPy document, as used by a + processor.""" + + def __init__(self, ID, filename): + self.ID = ID + self.filename = filename + self.significators = {} + + +class Processor: + + """An entity which is capable of processing a hierarchy of EmPy + files and building a dictionary of document objects associated + with them describing their significator contents.""" + + DEFAULT_EMPY_EXTENSIONS = ('.em',) + SIGNIFICATOR_RE = re.compile(SIGNIFICATOR_RE_STRING) + + def __init__(self, factory=Document): + self.factory = factory + self.documents = {} + + def identifier(self, pathname, filename): return filename + + def clear(self): + self.documents = {} + + def scan(self, basename, extensions=DEFAULT_EMPY_EXTENSIONS): + if type(extensions) is types.StringType: + extensions = (extensions,) + def _noCriteria(x): + return True + def _extensionsCriteria(pathname, extensions=extensions): + if extensions: + for extension in extensions: + if pathname[-len(extension):] == extension: + return True + return False + else: + return True + self.directory(basename, _noCriteria, _extensionsCriteria, None) + self.postprocess() + + def postprocess(self): + pass + + def directory(self, basename, dirCriteria, fileCriteria, depth=None): + if depth is not None: + if depth <= 0: + return + else: + depth = depth - 1 + filenames = os.listdir(basename) + for filename in filenames: + pathname = os.path.join(basename, filename) + if os.path.isdir(pathname): + if dirCriteria(pathname): + self.directory(pathname, dirCriteria, fileCriteria, depth) + elif os.path.isfile(pathname): + if fileCriteria(pathname): + documentID = self.identifier(pathname, filename) + document = self.factory(documentID, pathname) + self.file(document, open(pathname)) + self.documents[documentID] = document + + def file(self, document, file): + while True: + line = file.readline() + if not line: + break + self.line(document, line) + + def line(self, document, line): + match = self.SIGNIFICATOR_RE.search(line) + if match: + key, valueS = match.groups() + valueS = string.strip(valueS) + if valueS: + value = eval(valueS) + else: + value = None + document.significators[key] = value + + +def expand(_data, _globals=None, \ + _argv=None, _prefix=DEFAULT_PREFIX, _pseudo=None, _options=None, \ + **_locals): + """Do an atomic expansion of the given source data, creating and + shutting down an interpreter dedicated to the task. The sys.stdout + object is saved off and then replaced before this function + returns.""" + if len(_locals) == 0: + # If there were no keyword arguments specified, don't use a locals + # dictionary at all. + _locals = None + output = NullFile() + interpreter = Interpreter(output, argv=_argv, prefix=_prefix, \ + pseudo=_pseudo, options=_options, \ + globals=_globals) + if interpreter.options.get(OVERRIDE_OPT, True): + oldStdout = sys.stdout + try: + result = interpreter.expand(_data, _locals) + finally: + interpreter.shutdown() + if _globals is not None: + interpreter.unfix() # remove pseudomodule to prevent clashes + if interpreter.options.get(OVERRIDE_OPT, True): + sys.stdout = oldStdout + return result + +def environment(name, default=None): + """Get data from the current environment. If the default is True + or False, then presume that we're only interested in the existence + or non-existence of the environment variable.""" + if os.environ.has_key(name): + # Do the True/False test by value for future compatibility. + if default == False or default == True: + return True + else: + return os.environ[name] + else: + return default + +def info(table): + DEFAULT_LEFT = 28 + maxLeft = 0 + maxRight = 0 + for left, right in table: + if len(left) > maxLeft: + maxLeft = len(left) + if len(right) > maxRight: + maxRight = len(right) + FORMAT = ' %%-%ds %%s\n' % max(maxLeft, DEFAULT_LEFT) + for left, right in table: + if right.find('\n') >= 0: + for right in right.split('\n'): + sys.stderr.write(FORMAT % (left, right)) + left = '' + else: + sys.stderr.write(FORMAT % (left, right)) + +def usage(verbose=True): + """Print usage information.""" + programName = sys.argv[0] + def warn(line=''): + sys.stderr.write("%s\n" % line) + warn("""\ +Usage: %s [options] [<filename, or '-' for stdin> [<argument>...]] +Welcome to EmPy version %s.""" % (programName, __version__)) + warn() + warn("Valid options:") + info(OPTION_INFO) + if verbose: + warn() + warn("The following markups are supported:") + info(MARKUP_INFO) + warn() + warn("Valid escape sequences are:") + info(ESCAPE_INFO) + warn() + warn("The %s pseudomodule contains the following attributes:" % \ + DEFAULT_PSEUDOMODULE_NAME) + info(PSEUDOMODULE_INFO) + warn() + warn("The following environment variables are recognized:") + info(ENVIRONMENT_INFO) + warn() + warn(USAGE_NOTES) + else: + warn() + warn("Type %s -H for more extensive help." % programName) + +def invoke(args): + """Run a standalone instance of an EmPy interpeter.""" + # Initialize the options. + _output = None + _options = {BUFFERED_OPT: environment(BUFFERED_ENV, False), + RAW_OPT: environment(RAW_ENV, False), + EXIT_OPT: True, + FLATTEN_OPT: environment(FLATTEN_ENV, False), + OVERRIDE_OPT: not environment(NO_OVERRIDE_ENV, False), + CALLBACK_OPT: False} + _preprocessing = [] + _prefix = environment(PREFIX_ENV, DEFAULT_PREFIX) + _pseudo = environment(PSEUDO_ENV, None) + _interactive = environment(INTERACTIVE_ENV, False) + _extraArguments = environment(OPTIONS_ENV) + _binary = -1 # negative for not, 0 for default size, positive for size + _unicode = environment(UNICODE_ENV, False) + _unicodeInputEncoding = environment(INPUT_ENCODING_ENV, None) + _unicodeOutputEncoding = environment(OUTPUT_ENCODING_ENV, None) + _unicodeInputErrors = environment(INPUT_ERRORS_ENV, None) + _unicodeOutputErrors = environment(OUTPUT_ERRORS_ENV, None) + _hooks = [] + _pauseAtEnd = False + _relativePath = False + if _extraArguments is not None: + _extraArguments = string.split(_extraArguments) + args = _extraArguments + args + # Parse the arguments. + pairs, remainder = getopt.getopt(args, 'VhHvkp:m:frino:a:buBP:I:D:E:F:', ['version', 'help', 'extended-help', 'verbose', 'null-hook', 'suppress-errors', 'prefix=', 'no-prefix', 'module=', 'flatten', 'raw-errors', 'interactive', 'no-override-stdout', 'binary', 'chunk-size=', 'output=' 'append=', 'preprocess=', 'import=', 'define=', 'execute=', 'execute-file=', 'buffered-output', 'pause-at-end', 'relative-path', 'no-callback-error', 'no-bangpath-processing', 'unicode', 'unicode-encoding=', 'unicode-input-encoding=', 'unicode-output-encoding=', 'unicode-errors=', 'unicode-input-errors=', 'unicode-output-errors=']) + for option, argument in pairs: + if option in ('-V', '--version'): + sys.stderr.write("%s version %s\n" % (__program__, __version__)) + return + elif option in ('-h', '--help'): + usage(False) + return + elif option in ('-H', '--extended-help'): + usage(True) + return + elif option in ('-v', '--verbose'): + _hooks.append(VerboseHook()) + elif option in ('--null-hook',): + _hooks.append(Hook()) + elif option in ('-k', '--suppress-errors'): + _options[EXIT_OPT] = False + _interactive = True # suppress errors implies interactive mode + elif option in ('-m', '--module'): + _pseudo = argument + elif option in ('-f', '--flatten'): + _options[FLATTEN_OPT] = True + elif option in ('-p', '--prefix'): + _prefix = argument + elif option in ('--no-prefix',): + _prefix = None + elif option in ('-r', '--raw-errors'): + _options[RAW_OPT] = True + elif option in ('-i', '--interactive'): + _interactive = True + elif option in ('-n', '--no-override-stdout'): + _options[OVERRIDE_OPT] = False + elif option in ('-o', '--output'): + _output = argument, 'w', _options[BUFFERED_OPT] + elif option in ('-a', '--append'): + _output = argument, 'a', _options[BUFFERED_OPT] + elif option in ('-b', '--buffered-output'): + _options[BUFFERED_OPT] = True + elif option in ('-B',): # DEPRECATED + _options[BUFFERED_OPT] = True + elif option in ('--binary',): + _binary = 0 + elif option in ('--chunk-size',): + _binary = int(argument) + elif option in ('-P', '--preprocess'): + _preprocessing.append(('pre', argument)) + elif option in ('-I', '--import'): + for module in string.split(argument, ','): + module = string.strip(module) + _preprocessing.append(('import', module)) + elif option in ('-D', '--define'): + _preprocessing.append(('define', argument)) + elif option in ('-E', '--execute'): + _preprocessing.append(('exec', argument)) + elif option in ('-F', '--execute-file'): + _preprocessing.append(('file', argument)) + elif option in ('-u', '--unicode'): + _unicode = True + elif option in ('--pause-at-end',): + _pauseAtEnd = True + elif option in ('--relative-path',): + _relativePath = True + elif option in ('--no-callback-error',): + _options[CALLBACK_OPT] = True + elif option in ('--no-bangpath-processing',): + _options[BANGPATH_OPT] = False + elif option in ('--unicode-encoding',): + _unicodeInputEncoding = _unicodeOutputEncoding = argument + elif option in ('--unicode-input-encoding',): + _unicodeInputEncoding = argument + elif option in ('--unicode-output-encoding',): + _unicodeOutputEncoding = argument + elif option in ('--unicode-errors',): + _unicodeInputErrors = _unicodeOutputErrors = argument + elif option in ('--unicode-input-errors',): + _unicodeInputErrors = argument + elif option in ('--unicode-output-errors',): + _unicodeOutputErrors = argument + # Set up the Unicode subsystem if required. + if _unicode or \ + _unicodeInputEncoding or _unicodeOutputEncoding or \ + _unicodeInputErrors or _unicodeOutputErrors: + theSubsystem.initialize(_unicodeInputEncoding, \ + _unicodeOutputEncoding, \ + _unicodeInputErrors, _unicodeOutputErrors) + # Now initialize the output file if something has already been selected. + if _output is not None: + _output = apply(AbstractFile, _output) + # Set up the main filename and the argument. + if not remainder: + remainder.append('-') + filename, arguments = remainder[0], remainder[1:] + # Set up the interpreter. + if _options[BUFFERED_OPT] and _output is None: + raise ValueError, "-b only makes sense with -o or -a arguments" + if _prefix == 'None': + _prefix = None + if _prefix and type(_prefix) is types.StringType and len(_prefix) != 1: + raise Error, "prefix must be single-character string" + interpreter = Interpreter(output=_output, \ + argv=remainder, \ + prefix=_prefix, \ + pseudo=_pseudo, \ + options=_options, \ + hooks=_hooks) + try: + # Execute command-line statements. + i = 0 + for which, thing in _preprocessing: + if which == 'pre': + command = interpreter.file + target = theSubsystem.open(thing, 'r') + name = thing + elif which == 'define': + command = interpreter.string + if string.find(thing, '=') >= 0: + target = '%s{%s}' % (_prefix, thing) + else: + target = '%s{%s = None}' % (_prefix, thing) + name = '<define:%d>' % i + elif which == 'exec': + command = interpreter.string + target = '%s{%s}' % (_prefix, thing) + name = '<exec:%d>' % i + elif which == 'file': + command = interpreter.string + name = '<file:%d (%s)>' % (i, thing) + target = '%s{execfile("""%s""")}' % (_prefix, thing) + elif which == 'import': + command = interpreter.string + name = '<import:%d>' % i + target = '%s{import %s}' % (_prefix, thing) + else: + assert 0 + interpreter.wrap(command, (target, name)) + i = i + 1 + # Now process the primary file. + interpreter.ready() + if filename == '-': + if not _interactive: + name = '<stdin>' + path = '' + file = sys.stdin + else: + name, file = None, None + else: + name = filename + file = theSubsystem.open(filename, 'r') + path = os.path.split(filename)[0] + if _relativePath: + sys.path.insert(0, path) + if file is not None: + if _binary < 0: + interpreter.wrap(interpreter.file, (file, name)) + else: + chunkSize = _binary + interpreter.wrap(interpreter.binary, (file, name, chunkSize)) + # If we're supposed to go interactive afterwards, do it. + if _interactive: + interpreter.interact() + finally: + interpreter.shutdown() + # Finally, if we should pause at the end, do it. + if _pauseAtEnd: + try: + raw_input() + except EOFError: + pass + +def main(): + invoke(sys.argv[1:]) + +if __name__ == '__main__': main() diff --git a/shell/data/gtkrc.em b/shell/data/gtkrc.em new file mode 100644 index 0000000..d4e1a7c --- /dev/null +++ b/shell/data/gtkrc.em @@ -0,0 +1,12 @@ +@{ +if scaling == '72': + icon_sizes = 'gtk-large-toolbar=40,40' +else: + icon_sizes = 'gtk-large-toolbar=55,55' +}@ +gtk-theme-name = "sugar-@scaling" +gtk-icon-theme-name = "sugar" +gtk-cursor-theme-name = "sugar" +gtk-toolbar-style = GTK_TOOLBAR_ICONS +gtk-icon-sizes = "@icon_sizes" +gtk-cursor-blink-timeout = 3 diff --git a/shell/data/icons/Makefile.am b/shell/data/icons/Makefile.am new file mode 100644 index 0000000..a35643a --- /dev/null +++ b/shell/data/icons/Makefile.am @@ -0,0 +1,15 @@ +sugardir = $(pkgdatadir)/data/icons + +sugar_DATA = \ + module-about_me.svg \ + module-about_my_computer.svg \ + module-date_and_time.svg \ + module-frame.svg \ + module-keyboard.svg \ + module-language.svg \ + module-modemconfiguration.svg \ + module-network.svg \ + module-power.svg \ + module-updater.svg + +EXTRA_DIST = $(sugar_DATA) diff --git a/shell/data/icons/module-about_me.svg b/shell/data/icons/module-about_me.svg new file mode 100644 index 0000000..7abe926 --- /dev/null +++ b/shell/data/icons/module-about_me.svg @@ -0,0 +1,7 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + <!ENTITY stroke_color "#666666"> + <!ENTITY fill_color "#ffffff"> +]><svg enable-background="new 0 0 55 55" height="55px" id="Layer_1" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="module-about_x5F_me_1_"> + <path d="M33.359,35.101L43.46,45.201c0.752,0.75,1.217,1.784,1.217,2.932 c0,2.287-1.855,4.143-4.146,4.143c-1.145,0-2.178-0.463-2.932-1.211L27.498,40.963l-10.1,10.1c-0.75,0.75-1.787,1.211-2.933,1.211 c-2.285,0-4.143-1.854-4.143-4.141c0-1.146,0.465-2.184,1.212-2.934l10.104-10.101L11.535,24.997 c-0.747-0.749-1.212-1.785-1.212-2.93c0-2.289,1.854-4.145,4.146-4.145c1.143,0,2.18,0.465,2.93,1.214l10.099,10.101l10.101-10.102 c0.754-0.749,1.787-1.214,2.934-1.214c2.289,0,4.146,1.856,4.146,4.145c0,1.145-0.467,2.179-1.217,2.93L33.359,35.101z" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5"/> + <circle cx="27.497" cy="10.849" fill="&fill_color;" r="8.122" stroke="&stroke_color;" stroke-width="3.5"/> +</g></svg>
\ No newline at end of file diff --git a/shell/data/icons/module-about_my_computer.svg b/shell/data/icons/module-about_my_computer.svg new file mode 100644 index 0000000..cf3528e --- /dev/null +++ b/shell/data/icons/module-about_my_computer.svg @@ -0,0 +1,6 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + <!ENTITY stroke_color "#666666"> + <!ENTITY fill_color "#ffffff"> +]><svg enable-background="new 0 0 55 55" height="55px" id="Layer_1" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="module-about_x5F_my_x5F_xo_1_"> + <path d="M52.957,40.602h0.002l-0.025-0.017 c-0.152-0.11-0.315-0.21-0.483-0.302l-12.204-7.605V8.667c0-1.624-1.316-2.943-2.941-2.943H6.291c-1.625,0-2.942,1.319-2.942,2.943 V35.08c0,1.1,0.61,2.045,1.503,2.551l-0.019,0.004L19.49,46.77c0.694,0.436,1.534,0.691,2.438,0.691h28.319 c2.362,0,4.296-1.74,4.296-3.865C54.543,42.391,53.923,41.312,52.957,40.602z M9.072,12.392c0-0.619,0.506-1.124,1.124-1.124H33.4 c0.617,0,1.123,0.505,1.123,1.124v16.561c0,0.617-0.506,1.126-1.123,1.126H10.196c-0.617,0-1.124-0.509-1.124-1.126V12.392z" display="inline" fill="&fill_color;" id="module-about_x5F_my_x5F_xo"/> +</g></svg>
\ No newline at end of file diff --git a/shell/data/icons/module-date_and_time.svg b/shell/data/icons/module-date_and_time.svg new file mode 100644 index 0000000..605dbeb --- /dev/null +++ b/shell/data/icons/module-date_and_time.svg @@ -0,0 +1,19 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + <!ENTITY stroke_color "#666666"> + <!ENTITY fill_color "#ffffff"> +]><svg enable-background="new 0 0 55 55" height="55px" id="Layer_1" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="module-date_x5F_and_x5F_time"> + <g display="inline"> + <defs> + <path d="M29.891,31.641h17.255c0.346-1.563,0.534-3.187,0.534-4.854c0-12.35-10.013-22.362-22.362-22.362 c-12.351,0-22.362,10.012-22.362,22.362c0,12.351,10.011,22.362,22.362,22.362c1.567,0,3.097-0.163,4.573-0.47V31.641z M26.286,28.242c-0.034,0.022-0.071,0.038-0.107,0.058c-0.064,0.037-0.127,0.075-0.196,0.104 c-0.039,0.016-0.079,0.023-0.118,0.036c-0.069,0.023-0.138,0.049-0.21,0.062c-0.048,0.01-0.098,0.01-0.147,0.015 c-0.063,0.007-0.126,0.02-0.191,0.02c-0.071,0-0.139-0.013-0.208-0.021c-0.043-0.006-0.086-0.005-0.129-0.014 c-0.078-0.015-0.152-0.041-0.226-0.066c-0.034-0.012-0.069-0.019-0.102-0.032c-0.077-0.031-0.147-0.072-0.217-0.113 c-0.028-0.017-0.059-0.028-0.086-0.047c-0.193-0.129-0.359-0.294-0.487-0.487c-0.028-0.042-0.047-0.086-0.071-0.13 c-0.031-0.057-0.065-0.111-0.09-0.171c-0.023-0.056-0.037-0.115-0.054-0.173c-0.015-0.051-0.035-0.101-0.045-0.153 c-0.023-0.114-0.035-0.229-0.035-0.344V10.349c0-0.966,0.783-1.75,1.75-1.75s1.75,0.784,1.75,1.75v12.212l3.973-3.973 c0.684-0.683,1.792-0.683,2.476,0c0.683,0.683,0.683,1.792,0,2.475l-6.96,6.96c-0.001,0.002-0.003,0.003-0.005,0.004 C26.469,28.107,26.381,28.179,26.286,28.242z" id="SVGID_5_"/> + </defs> + <clipPath id="SVGID_6_"> + <use overflow="visible" xlink:href="#SVGID_5_"/> + </clipPath> + <circle clip-path="url(#SVGID_6_)" cx="25.318" cy="26.786" fill="&fill_color;" r="22.362"/> + </g> + <rect display="inline" fill="none" height="19.319" stroke="&fill_color;" stroke-width="2" width="21.064" x="29.891" y="31.641"/> + <g display="inline"> + <path d="M39.056,44.155c0.527,0,0.936,0.239,0.936,0.792c0,0.551-0.408,0.791-0.864,0.791h-4.006 c-0.527,0-0.936-0.24-0.936-0.791c0-0.252,0.156-0.469,0.276-0.612c0.995-1.188,2.075-2.267,2.986-3.586 c0.216-0.312,0.42-0.684,0.42-1.115c0-0.491-0.372-0.924-0.863-0.924c-1.38,0-0.72,1.943-1.871,1.943 c-0.575,0-0.876-0.408-0.876-0.876c0-1.511,1.344-2.723,2.818-2.723c1.476,0,2.663,0.972,2.663,2.495 c0,1.667-1.858,3.322-2.878,4.605H39.056z" fill="&fill_color;"/> + <path d="M46.339,39.25c0,0.756-0.323,1.415-0.983,1.835c0.863,0.396,1.463,1.199,1.463,2.146 c0,1.439-1.318,2.651-3.021,2.651c-1.775,0-2.879-1.309-2.879-2.256c0-0.467,0.492-0.803,0.924-0.803 c0.815,0,0.623,1.402,1.979,1.402c0.623,0,1.127-0.479,1.127-1.115c0-1.679-2.039-0.443-2.039-1.858 c0-1.259,1.703-0.408,1.703-1.739c0-0.455-0.323-0.804-0.863-0.804c-1.139,0-0.982,1.176-1.799,1.176 c-0.492,0-0.779-0.444-0.779-0.888c0-0.936,1.283-1.943,2.614-1.943C45.512,37.055,46.339,38.314,46.339,39.25z" fill="&fill_color;"/> + </g> +</g></svg>
\ No newline at end of file diff --git a/shell/data/icons/module-frame.svg b/shell/data/icons/module-frame.svg new file mode 100644 index 0000000..11ccee4 --- /dev/null +++ b/shell/data/icons/module-frame.svg @@ -0,0 +1,13 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + <!ENTITY stroke_color "#666666"> + <!ENTITY fill_color "#ffffff"> +]><svg enable-background="new 0 0 55 55" height="55px" id="Layer_1" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="module-frame"> + <g display="inline"> + <g> + <path d="M2.934,8.664v38.209h49.391V8.664H2.934z M49.115,43.833H6.144V11.704h42.971V43.833z" fill="&fill_color;"/> + </g> + </g> + <g display="inline" id="Left_Pointer_1_"> + <path d="M12.533,16.981l-2.359-2.359h1.597c0.2,0,0.401-0.077,0.555-0.23c0.307-0.306,0.307-0.804,0-1.11 c-0.153-0.154-0.355-0.23-0.555-0.231H7.49l0.001,4.28c0,0.201,0.076,0.401,0.23,0.555c0.306,0.307,0.804,0.307,1.111,0 c0.154-0.153,0.229-0.354,0.229-0.555v-1.597l2.36,2.358c0.142,0.142,0.338,0.23,0.556,0.23c0.434,0,0.785-0.353,0.785-0.786 C12.763,17.319,12.674,17.123,12.533,16.981z" fill="&fill_color;"/> + </g> +</g></svg> diff --git a/shell/data/icons/module-keyboard.svg b/shell/data/icons/module-keyboard.svg new file mode 100644 index 0000000..43bbc57 --- /dev/null +++ b/shell/data/icons/module-keyboard.svg @@ -0,0 +1,134 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + <!ENTITY stroke_color "#666666"> + <!ENTITY fill_color "#ffffff"> +]><svg enable-background="new 0 0 55 55" height="55px" id="Layer_1" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="module-keyboard"> + <rect display="inline" fill="&fill_color;" height="23.326" width="54" x="0.5" y="15.837"/> + <g display="inline"> + <path d="M52.61,28.081c0,0.55-0.45,1-1,1h-5.443c-0.55,0-1-0.45-1-1v-5.444c0-0.55,0.45-1,1-1h5.443c0.55,0,1,0.45,1,1V28.081z"/> + </g> + <g display="inline"> + <path d="M52.61,19.941c0,0.55-0.45,1-1,1h-5.412c-0.55,0-1-0.45-1-1v-1.368c0-0.55,0.45-1,1-1h5.412c0.55,0,1,0.45,1,1V19.941z"/> + </g> + <g display="inline"> + <path d="M52.61,32.267c0,0.55-0.45,1-1,1h-5.412c-0.55,0-1-0.45-1-1v-1.367c0-0.55,0.45-1,1-1h5.412c0.55,0,1,0.45,1,1V32.267z"/> + </g> + <g display="inline"> + <path d="M39.11,36.403c0,0.55-0.45,1-1,1H13.176c-0.55,0-1-0.45-1-1v-1.366c0-0.55,0.45-1,1-1H38.11c0.55,0,1,0.45,1,1V36.403z"/> + </g> + <g display="inline"> + <g> + <path d="M5.889,19.977c0,0.55-0.45,1-1,1H3.549c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1h1.339c0.55,0,1,0.45,1,1V19.977z"/> + </g> + <g> + <path d="M10.65,19.977c0,0.55-0.45,1-1,1H8.311c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1H9.65c0.55,0,1,0.45,1,1V19.977z"/> + </g> + <g> + <path d="M15.411,19.977c0,0.55-0.45,1-1,1h-1.339c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1h1.339c0.55,0,1,0.45,1,1V19.977z"/> + </g> + <g> + <path d="M20.173,19.978c0,0.55-0.45,1-1,1h-1.34c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.34c0.55,0,1,0.45,1,1V19.978z"/> + </g> + <g> + <path d="M24.934,19.977c0,0.55-0.45,1-1,1h-1.34c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1h1.34c0.55,0,1,0.45,1,1V19.977z"/> + </g> + <g> + <path d="M29.695,19.978c0,0.55-0.45,1-1,1h-1.34c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.34c0.55,0,1,0.45,1,1V19.978z"/> + </g> + <g> + <path d="M34.457,19.977c0,0.55-0.45,1-1,1h-1.341c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1h1.341c0.55,0,1,0.45,1,1V19.977z"/> + </g> + <g> + <path d="M39.218,19.977c0,0.55-0.45,1-1,1h-1.341c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1h1.341c0.55,0,1,0.45,1,1V19.977z"/> + </g> + <g> + <path d="M43.979,19.977c0,0.55-0.45,1-1,1h-1.341c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1h1.341c0.55,0,1,0.45,1,1V19.977z"/> + </g> + </g> + <g display="inline"> + <g> + <path d="M5.889,24.038c0,0.55-0.45,1-1,1H3.549c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1h1.339c0.55,0,1,0.45,1,1V24.038z"/> + </g> + <g> + <path d="M10.65,24.038c0,0.55-0.45,1-1,1H8.311c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1H9.65c0.55,0,1,0.45,1,1V24.038z"/> + </g> + <g> + <path d="M15.411,24.038c0,0.55-0.45,1-1,1h-1.339c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1h1.339c0.55,0,1,0.45,1,1V24.038z"/> + </g> + <g> + <path d="M20.173,24.038c0,0.55-0.45,1-1,1h-1.34c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.34c0.55,0,1,0.45,1,1V24.038z"/> + </g> + <g> + <path d="M24.934,24.038c0,0.55-0.45,1-1,1h-1.34c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1h1.34c0.55,0,1,0.45,1,1V24.038z"/> + </g> + <g> + <path d="M29.695,24.038c0,0.55-0.45,1-1,1h-1.34c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.34c0.55,0,1,0.45,1,1V24.038z"/> + </g> + <g> + <path d="M34.457,24.038c0,0.55-0.45,1-1,1h-1.341c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1h1.341c0.55,0,1,0.45,1,1V24.038z"/> + </g> + <g> + <path d="M39.218,24.038c0,0.55-0.45,1-1,1h-1.341c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1h1.341c0.55,0,1,0.45,1,1V24.038z"/> + </g> + <g> + <path d="M43.979,24.038c0,0.55-0.45,1-1,1h-1.341c-0.55,0-1-0.45-1-1v-1.339c0-0.55,0.45-1,1-1h1.341c0.55,0,1,0.45,1,1V24.038z"/> + </g> + </g> + <g display="inline"> + <g> + <path d="M5.889,28.099c0,0.55-0.45,1-1,1.001H3.549c-0.55,0.001-1-0.449-1-0.999V26.76c0-0.55,0.45-1,1-1h1.339 c0.55,0,1,0.45,1,1V28.099z"/> + </g> + <g> + <path d="M10.65,28.099c0,0.55-0.45,1-1,1.001H8.311c-0.55,0.001-1-0.449-1-0.999V26.76c0-0.55,0.45-1,1-1H9.65c0.55,0,1,0.45,1,1 V28.099z"/> + </g> + <g> + <path d="M15.411,28.099c0,0.55-0.45,1-1,1L13.072,29.1c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.339c0.55,0,1,0.45,1,1 V28.099z"/> + </g> + <g> + <path d="M20.173,28.099c0,0.55-0.45,1-1,1l-1.34,0.001c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.34c0.55,0,1,0.45,1,1 V28.099z"/> + </g> + <g> + <path d="M24.934,28.099c0,0.55-0.45,1-1,1l-1.34,0.001c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.34c0.55,0,1,0.45,1,1 V28.099z"/> + </g> + <g> + <path d="M29.695,28.099c0,0.55-0.45,1-1,1l-1.34,0.001c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.34c0.55,0,1,0.45,1,1 V28.099z"/> + </g> + <g> + <path d="M34.457,28.099c0,0.55-0.45,1-1,1L32.116,29.1c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.341c0.55,0,1,0.45,1,1 V28.099z"/> + </g> + <g> + <path d="M39.218,28.099c0,0.55-0.45,1-1,1h-1.341c-0.55,0-1-0.45-1-1V26.76c0-0.55,0.45-1,1-1h1.341c0.55,0,1,0.45,1,1V28.099z"/> + </g> + <g> + <path d="M43.979,28.099c0,0.55-0.45,1-1,1h-1.341c-0.55,0-1-0.45-1-1V26.76c0-0.55,0.45-1,1-1h1.341c0.55,0,1,0.45,1,1V28.099z"/> + </g> + </g> + <g display="inline"> + <g> + <path d="M5.889,32.161c0,0.55-0.45,1-1,1H3.549c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.339c0.55,0,1,0.45,1,1V32.161z"/> + </g> + <g> + <path d="M10.65,32.161c0,0.55-0.45,1-1,1H8.311c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1H9.65c0.55,0,1,0.45,1,1V32.161z"/> + </g> + <g> + <path d="M15.411,32.161c0,0.55-0.45,1-1,1h-1.339c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.339c0.55,0,1,0.45,1,1V32.161z"/> + </g> + <g> + <path d="M20.173,32.161c0,0.55-0.45,1-1,1h-1.34c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.34c0.55,0,1,0.45,1,1V32.161z"/> + </g> + <g> + <path d="M24.934,32.161c0,0.55-0.45,1-1,1h-1.34c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.34c0.55,0,1,0.45,1,1V32.161z"/> + </g> + <g> + <path d="M29.695,32.161c0,0.55-0.45,1-1,1h-1.34c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.34c0.55,0,1,0.45,1,1V32.161z"/> + </g> + <g> + <path d="M34.457,32.161c0,0.55-0.45,1-1,1h-1.341c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.341c0.55,0,1,0.45,1,1V32.161z"/> + </g> + <g> + <path d="M39.218,32.161c0,0.55-0.45,1-1,1h-1.341c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.341c0.55,0,1,0.45,1,1V32.161z"/> + </g> + <g> + <path d="M43.979,32.161c0,0.55-0.45,1-1,1h-1.341c-0.55,0-1-0.45-1-1v-1.34c0-0.55,0.45-1,1-1h1.341c0.55,0,1,0.45,1,1V32.161z"/> + </g> + </g> +</g></svg>
\ No newline at end of file diff --git a/shell/data/icons/module-language.svg b/shell/data/icons/module-language.svg new file mode 100644 index 0000000..ce04cb4 --- /dev/null +++ b/shell/data/icons/module-language.svg @@ -0,0 +1,59 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + <!ENTITY stroke_color "#666666"> + <!ENTITY fill_color "#ffffff"> +]><svg enable-background="new 0 0 55 55" height="55px" id="Layer_1" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="module-language"> + <g display="inline"> + <g> + <path clip-rule="evenodd" d="M35.805,13.962c-0.346-0.084-0.779-0.072-0.725-0.6 c0.24,0,0.482,0,0.725,0l-0.092,0.301L35.805,13.962z" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M36.438,14.063l0.09-0.3c1.146-0.067,1.871,0.331,2.533,0.8 c3.684,0.596,9.051-0.669,10.676,2.2c-0.164,0.485-0.727,0.53-1.268,0.6c0.531,0.215,0.637,0.898,0.543,1.8 c-0.928-0.174-1.295-0.968-1.447-2c-0.553,0.389-1.396,0.457-2.352,0.4c-0.121,0.867,0.84,0.539,1.447,0.6 c0.057,0.472,0.629,0.373,0.543,1l-0.271,0.1l0.09,0.3c-0.549,0.658-0.812,1.635-0.723,3c-0.551,0.01-0.703-0.422-1.086-0.6 c0.26,1.426,0.908,1.89,0.723,3.4c-1.1-1.013-1.793,1.516-1.99,2.799c-0.627,0.161-0.693-0.297-1.266-0.199l-0.182-0.1l-0.18,0.1 c-0.475-1.659-2.096-3.383-3.076-1c0,0.4,0,0.8,0,1.199l-0.271-0.1l0.09,0.301c-1.533,0.073-0.889-3.936-3.438-3.4 c-0.357,1.338-1.098,2.254-2.535,2.4c-0.164,0.784,0.955,0.145,1.086,0.6c-0.146,1.638-1.449,1.998-1.99,3.2 c0.646,2.376-0.838,2.551-0.902,4.601c-0.834,0.479-0.881,1.828-1.811,2.2c-3.492-0.651-1.328-6.379-3.258-8.601 c-0.848-0.263-1.984-0.205-3.075-0.2c-2.032-1.712-0.716-5.163,0.724-6.8c-0.372-0.323-0.419-1.003-0.362-1.801 c0.481-0.002,1.034,0.076,1.267-0.2c-0.148-0.703-0.412-1.279-1.267-1.201c0.081-0.912,0.522-1.423,1.267-1.6 c0.269,0.237,0.282,0.755,0.543,1c0.512,0.165,0.469-0.282,0.904-0.201c0.191-0.877-0.611-0.657-0.543-1.4 c0.357-0.828,1.436-1.889,2.354-2c1.213-0.147,1.916,0.831,3.617,0.6c0.695-0.094,1.172-0.681,2.172-1 c0.594-0.19,1.852,0.085,2.354-0.601L36.438,14.063z M27.842,17.963c0.438-0.392,0.416-1-0.18-1.2 C27.766,17.115,27.441,17.938,27.842,17.963z M27.48,21.563c-0.186-0.944-2.604-0.928-2.353,0.4c0.483,0,0.966,0,1.448,0 l0.09,0.3l0.271-0.101c0,0.066,0,0.134,0,0.201c0.442,1.067,3.484,1.27,3.98,0c-1.439,0.273-2.379-0.674-3.256-0.4l0.09-0.301 L27.48,21.563z M32.365,26.764c0.031-0.501-0.277-0.626-0.541-0.8C31.791,26.464,32.102,26.59,32.365,26.764z" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M48.018,21.863l0.09-0.3c0.316,0.184,0.4,0.625,0.361,1.2 c-0.547,0.261-1.043,0.579-1.627,0.8c-0.492-1.168,0.654-0.949,0.904-1.8L48.018,21.863z" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M42.77,28.864l0.092-0.301c0.662,0.467,0.711,1.615,0.904,2.601 l-0.332-0.1l-0.211,0.3c-0.619-0.582-0.996-1.434-1.268-2.4c0.146,0.105,0.295,0.209,0.543,0.2c0-0.134,0-0.267,0-0.399 L42.77,28.864z" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M11.376,25.163c0.423,0.067,0.78,0.206,0.905,0.601 l-0.271,0.233l0.09,0.367c-0.21-0.033-0.322,0.044-0.361,0.199c-0.465-0.02-0.291-0.744-0.543-1l0.271-0.1L11.376,25.163z" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M46.299,27.764c-0.281-0.29-0.381-0.78-0.363-1.399 c0.182,0,0.363,0,0.545,0c0.104,0.418,0.447,0.57,0.361,1.199l-0.332-0.1L46.299,27.764z" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M45.936,30.364c0.131,0.877-0.602,0.8-1.266,0.8 c-0.264-0.44-0.549-0.858-0.543-1.601c0.738-0.051,0.895-0.744,1.809-0.6c-0.057,0.465,0.029,0.768,0.182,1l-0.271,0.101 L45.936,30.364z" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M46.389,30.265l-0.09-0.301c0.42-0.063,0.693,0.033,0.904,0.2 c-0.332,0.501-0.145,1.574-1.086,1.4c0-0.4,0-0.8,0-1.2L46.389,30.265z" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M48.65,31.164c-0.553,0.146-0.531-0.345-1.086-0.199 c-0.086-0.716,1.123-1.144,1.268-0.4l-0.271,0.233L48.65,31.164z" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M49.104,30.931l-0.092-0.366c0.926-0.487,1.51,0.948,2.715,0.8 c-0.617,0.261-0.084,0.855-0.361,1.199" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M49.918,32.765c0.291,0.117,1.43,2.391,1.447,3 c0.045,1.674-1.633,3.377-2.715,3.201c-0.922-0.152-0.688-0.955-1.447-1.601c-0.98,0.12-1.854,0.957-2.895,0.399 c-0.109-1.053,0.133-1.718,0.18-2.6c1.658-0.205,3.107-3.646,4.705-1.4C49.775,33.807,49.633,33.051,49.918,32.765z" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M33.451,33.164c0.725,1.004,0.084,2.368-0.725,2.8 C32.002,34.962,32.742,33.707,33.451,33.164z" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M48.65,39.165c0.383,0.062,0.039,0.948-0.361,0.8 C48.082,39.336,48.572,39.479,48.65,39.165z" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M16.805,12.962c2.05,0,4.102,0,6.15,0 c0.007,0.195,0.223,0.155,0.363,0.2c0.324,0.701-0.65,1.677-1.084,2.2c-1.523,0.317-2.302,1.457-3.621,2 c-0.971-0.425-0.523-1.94-0.724-2.8c-0.439-0.464-2.139-0.687-2.532,0c1.822-0.026,1.732,2.399,0.18,2.6 c1.181-0.023,1.775,2.452,0.543,2.8l0.091-0.3l-0.272-0.1c-0.099-0.657-1.186,0.234-0.541,0.4l-0.092,0.3l0.271,0.101 c-2.093,0.085-2.461,2.079-3.98,2.799c0,0.201,0,0.4,0,0.601l-0.332-0.1l-0.21,0.3c-0.761-0.482-2.09-0.11-2.534,0.399 c0,0.534,0,1.067,0,1.601c0.622,0.076,1.287-0.828,1.628-0.4c-0.564,1.371,0.746,1.471,0.906,2.6l-0.272,0.201l0.272,0.199 c-0.433,0.062-1.751-0.617-2.534-1.199C7.746,26.816,7,25.966,6.673,25.163c-0.38-0.229-0.707,0.123-1.086-0.399 c-0.229-1.306-0.774-2.063-0.724-3.2c0.032-0.728,0.597-0.782,0.724-1.601c0.033-0.217-0.352-0.856-0.362-1.399 c-0.01-0.526,0.43-0.783,0-1.201c-1.454-0.274-1.845,0.627-3.076,0.6l0.09-0.199l-0.09-0.2c-0.231-0.521-0.397-0.604-0.182-1.2 c1.83-1.044,4.094-1.609,7.057-1.4c0.688-0.04,0.687-0.841,1.448-0.8c1.325-0.132,2.296,0.13,3.257,0.4 c0.705-0.021,0.311-1.256,0.904-1.4C15.303,13.035,16.436,13.422,16.805,12.962z M14.452,15.963 c0.286-0.02,0.628,0.027,0.542-0.4c-0.119,0-0.24,0-0.361,0C14.633,15.764,14.486,15.801,14.452,15.963z M11.92,17.763 c0.789-0.139,0.803,0.577,1.447,0.6c0.266-0.505,0.639-0.893,0.723-1.6C13.093,16.545,11.914,16.393,11.92,17.763z" fill="&fill_color;" fill-rule="evenodd"/> + <path clip-rule="evenodd" d="M11.467,28.364l-0.091-0.201 c1.866-1.496,4.541,0.503,5.247,2.201c0.822,0.426,2.057,0.393,2.352,1.4c-0.152,1.164-0.635,1.965-0.723,3.199 c-0.226,0.484-0.742,0.648-1.268,0.801c-0.201,2.777-2.827,3.017-2.17,6.201c0.453-0.035,0.566,0.307,0.723,0.6 c-0.36,0-0.723,0-1.085,0c-1.601-1.566-1.526-4.982-1.81-8.001c-1.498-1.305-2.468-3.841-1.267-6.001L11.467,28.364z" fill="&fill_color;" fill-rule="evenodd"/> + <g> + + <path clip-rule="evenodd" d=" M48.018,21.863" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="2.1637"/> + + <path clip-rule="evenodd" d=" M46.932,19.263" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="2.1637"/> + + <path clip-rule="evenodd" d=" M43.434,31.064" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="2.8752"/> + + <path clip-rule="evenodd" d=" M42.498,27.864" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="2.1506"/> + + <path clip-rule="evenodd" d=" M38.971,28.063" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="1.2247"/> + + <path clip-rule="evenodd" d=" M26.851,21.793" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="2.1448"/> + + <path clip-rule="evenodd" d=" M12.01,25.997" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="2.8087"/> + + <path clip-rule="evenodd" d=" M46.51,27.464" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="3.5214"/> + + <path clip-rule="evenodd" d=" M46.752,28.264" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="3.5214"/> + + <path clip-rule="evenodd" d=" M45.846,30.064" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="2.1602"/> + + <path clip-rule="evenodd" d=" M49.104,30.931" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="3.1091"/> + + <path clip-rule="evenodd" d=" M46.752,32.165" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="2.1381"/> + + <path clip-rule="evenodd" d=" M15.266,20.263" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="1.6279"/> + + <path clip-rule="evenodd" d=" M11.225,23.664" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="2.9155"/> + + <path clip-rule="evenodd" d=" M11.467,28.364" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="2.0976"/> + + <path clip-rule="evenodd" d=" M10.743,28.364" fill="&fill_color;" fill-rule="evenodd" stroke="#000000" stroke-linecap="round" stroke-width="2.0976"/> + </g> + </g> + </g> + <rect display="inline" fill="none" height="30.334" stroke="&fill_color;" stroke-width="3.5" width="50.67" x="2.25" y="12.625"/> +</g></svg>
\ No newline at end of file diff --git a/shell/data/icons/module-modemconfiguration.svg b/shell/data/icons/module-modemconfiguration.svg new file mode 100644 index 0000000..02ccc81 --- /dev/null +++ b/shell/data/icons/module-modemconfiguration.svg @@ -0,0 +1,11 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + <!ENTITY stroke_color "#ffffff"> + <!ENTITY fill_color "none"> +]><svg enable-background="new 0 0 56.167 55" height="55px" version="1.1" viewBox="0 0 56.167 55" width="56.167px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="network-gsm"> + <g> + <path d="M13.759,11.28 v28.937h0.002c0,0.004-0.002,0.008-0.002,0.014c0,7.05,5.715,12.763,12.764,12.763c7.047,0,12.762-5.713,12.762-12.763v-0.014 V11.28H13.759z" fill="&fill_color;" stroke="&stroke_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5"/> + <rect fill="&stroke_color;" height="9.702" width="14.063" x="19.43" y="16.902"/> + + <line fill="&fill_color;" stroke="&stroke_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5" x1="39.286" x2="39.286" y1="11.28" y2="1.993"/> + </g> +</g></svg> diff --git a/shell/data/icons/module-network.svg b/shell/data/icons/module-network.svg new file mode 100644 index 0000000..a750a38 --- /dev/null +++ b/shell/data/icons/module-network.svg @@ -0,0 +1,32 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + <!ENTITY stroke_color "#666666"> + <!ENTITY fill_color "#ffffff"> +]><svg enable-background="new 0 0 55 55" height="55px" id="Layer_1" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="module-network"> + <g display="inline"> + <defs> + <path d="M14.897,34.339c0-10.144,8.224-18.367,18.367-18.367c3.929,0,7.562,1.244,10.549,3.345V0H0v43.812h17.55 C15.877,41.044,14.897,37.81,14.897,34.339z" id="SVGID_1_"/> + </defs> + <clipPath id="SVGID_2_"> + <use overflow="visible" xlink:href="#SVGID_1_"/> + </clipPath> + <g clip-path="url(#SVGID_2_)"> + + <circle cx="21.47" cy="21.073" fill="none" r="18.368" stroke="&fill_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + + <circle cx="21.469" cy="21.073" fill="none" r="10.476" stroke="&fill_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"/> + <circle cx="21.469" cy="21.073" fill="&fill_color;" r="3.966"/> + </g> + </g> + <g display="inline"> + <g> + <defs> + <rect height="18.367" id="SVGID_3_" width="36.736" x="14.897" y="34.339"/> + </defs> + <clipPath id="SVGID_4_"> + <use overflow="visible" xlink:href="#SVGID_3_"/> + </clipPath> + <circle clip-path="url(#SVGID_4_)" cx="33.265" cy="34.339" fill="&fill_color;" r="18.368"/> + </g> + <circle cx="33.265" cy="34.339" fill="none" r="18.368" stroke="&fill_color;" stroke-width="3.5"/> + </g> +</g></svg>
\ No newline at end of file diff --git a/shell/data/icons/module-power.svg b/shell/data/icons/module-power.svg new file mode 100644 index 0000000..4db57ea --- /dev/null +++ b/shell/data/icons/module-power.svg @@ -0,0 +1,13 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + <!ENTITY stroke_color "#666666"> + <!ENTITY fill_color "#ffffff"> +]><svg enable-background="new 0 0 55 55" height="55px" id="Layer_1" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="module-energy"> + <g display="inline" id="device-battery-charging-050"> + <g> + <g> + <path d="M2.215,15.271v24.833l33.094,0.002V15.271H2.215z M20.817,26.089l-6.599,9.903l2.339-8.285h-2.472 l1.85-7.121h5.411l-2.773,5.503H20.817z" fill="&fill_color;"/> + </g> + </g> + <polygon fill="none" points="2.215,39.896 47.602,39.896 47.602,34.607 52.611,34.607 52.611,20.565 47.602,20.565 47.602,15.271 2.215,15.271 " stroke="&fill_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5"/> + </g> +</g></svg>
\ No newline at end of file diff --git a/shell/data/icons/module-updater.svg b/shell/data/icons/module-updater.svg new file mode 100644 index 0000000..a521f61 --- /dev/null +++ b/shell/data/icons/module-updater.svg @@ -0,0 +1,16 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + <!ENTITY stroke_color "#000"> + <!ENTITY fill_color "#fff"> +]><svg height="55px" viewBox="0 0 55 55" width="55px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <g> + <g> + <path d="M 31.752 7.088 C 41.935 9.118 49.609 18.107 49.609 28.887 C 49.609 41.173 39.65 51.129 27.374 51.129 C 15.086 51.129 5.133 41.173 5.133 28.887 C 5.133 19.648 10.768 11.723 18.801 8.365 " fill="none" stroke="&fill_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5" /> + <path d="M 36.134 15.154 L 31.752 7.088 L 40.439 4.13 " fill="none" stroke="&fill_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5" /> + </g> + <g> + <g> + <path d="M 38.57 25.886 C 37.597 25.886 36.718 26.282 36.082 26.918 L 31.021 31.979 L 31.02 17.022 C 31.018 16.124 30.675 15.221 29.99 14.533 C 28.613 13.159 26.383 13.159 25.01 14.533 C 24.321 15.222 23.98 16.122 23.979 17.023 L 23.977 31.978 L 18.918 26.918 C 18.281 26.281 17.4 25.886 16.429 25.887 C 14.484 25.885 12.908 27.465 12.908 29.408 C 12.907 30.381 13.304 31.263 13.936 31.899 L 27.5 45.463 L 41.062 31.898 C 41.697 31.262 42.09 30.382 42.093 29.41 C 42.094 27.463 40.516 25.885 38.57 25.886 Z " fill="&fill_color;" stroke="none" /> + </g> + </g> + </g> +</svg> diff --git a/shell/data/kbdconfig b/shell/data/kbdconfig new file mode 100644 index 0000000..03c288a --- /dev/null +++ b/shell/data/kbdconfig @@ -0,0 +1,3 @@ +# This is the sugar keyboard configuration for matchbox + +<Alt>return=fullscreen diff --git a/shell/data/mime.defaults b/shell/data/mime.defaults new file mode 100644 index 0000000..f07e22c --- /dev/null +++ b/shell/data/mime.defaults @@ -0,0 +1,24 @@ +# MIME Activity service name + +application/pdf org.laptop.sugar.ReadActivity + +text/rtf org.laptop.AbiWordActivity +text/plain org.laptop.AbiWordActivity +application/x-abiword org.laptop.AbiWordActivity +text/x-xml-abiword org.laptop.AbiWordActivity +application/msword org.laptop.AbiWordActivity +application/rtf org.laptop.AbiWordActivity + +image/png org.laptop.ImageViewerActivity +image/gif org.laptop.ImageViewerActivity +image/jpeg org.laptop.ImageViewerActivity +text/html org.laptop.WebActivity +application/xhtml+xml org.laptop.WebActivity +application/xml org.laptop.WebActivity +application/rss+xml org.laptop.WebActivity +application/ogg org.laptop.sugar.Jukebox +audio/ogg org.laptop.sugar.Jukebox +video/ogg org.laptop.sugar.Jukebox + +text/x-python org.laptop.PippyActivity + diff --git a/shell/data/nm-user-settings.conf b/shell/data/nm-user-settings.conf new file mode 100644 index 0000000..16e71e4 --- /dev/null +++ b/shell/data/nm-user-settings.conf @@ -0,0 +1,28 @@ +<!DOCTYPE busconfig PUBLIC + "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> +<busconfig> + <policy user="root"> + <allow own="org.freedesktop.NetworkManagerUserSettings"/> + + <allow send_destination="org.freedesktop.NetworkManagerUserSettings"/> + </policy> + <policy at_console="true"> + <allow own="org.freedesktop.NetworkManagerUserSettings"/> + + <allow send_destination="org.freedesktop.NetworkManagerUserSettings"/> + + <!-- Only root can get secrets --> + <deny send_destination="org.freedesktop.NetworkManagerUserSettings" + send_interface="org.freedesktop.NetworkManagerSettings.Connection.Secrets"/> + </policy> + <policy context="default"> + <deny send_destination="org.freedesktop.NetworkManagerUserSettings"/> + + <allow send_destination="org.freedesktop.NetworkManagerUserSettings" + send_interface="org.freedesktop.DBus.Introspectable"/> + </policy> + + <limit name="max_replies_per_connection">512</limit> +</busconfig> + diff --git a/shell/data/sugar-emulator.desktop.in b/shell/data/sugar-emulator.desktop.in new file mode 100644 index 0000000..6247bd7 --- /dev/null +++ b/shell/data/sugar-emulator.desktop.in @@ -0,0 +1,10 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Sugar +GenericName=Sugar Emulator +Comment=The emulator for the Sugar Desktop Environment +Exec=@prefix@/bin/sugar-emulator +Terminal=false +Type=Application +Icon=sugar-xo +Categories=Education;Teaching; diff --git a/shell/data/sugar-xo.svg b/shell/data/sugar-xo.svg new file mode 100644 index 0000000..b673179 --- /dev/null +++ b/shell/data/sugar-xo.svg @@ -0,0 +1,7 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + <!ENTITY stroke_color "#010101"> + <!ENTITY fill_color "#FFFFFF"> +]><svg enable-background="new 0 0 55 55" height="55px" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="stock-xo_1_"> + <path d="M33.233,35.1l10.102,10.1c0.752,0.75,1.217,1.783,1.217,2.932 c0,2.287-1.855,4.143-4.146,4.143c-1.145,0-2.178-0.463-2.932-1.211L27.372,40.961l-10.1,10.1c-0.75,0.75-1.787,1.211-2.934,1.211 c-2.284,0-4.143-1.854-4.143-4.141c0-1.146,0.465-2.184,1.212-2.934l10.104-10.102L11.409,24.995 c-0.747-0.748-1.212-1.785-1.212-2.93c0-2.289,1.854-4.146,4.146-4.146c1.143,0,2.18,0.465,2.93,1.214l10.099,10.102l10.102-10.103 c0.754-0.749,1.787-1.214,2.934-1.214c2.289,0,4.146,1.856,4.146,4.145c0,1.146-0.467,2.18-1.217,2.932L33.233,35.1z" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5"/> + <circle cx="27.371" cy="10.849" fill="&fill_color;" r="8.122" stroke="&stroke_color;" stroke-width="3.5"/> +</g></svg>
\ No newline at end of file diff --git a/shell/data/sugar.desktop b/shell/data/sugar.desktop new file mode 100644 index 0000000..2d7133f --- /dev/null +++ b/shell/data/sugar.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Sugar +GenericName=Sugar +Exec=sugar +Type=Application diff --git a/shell/data/sugar.schemas.in b/shell/data/sugar.schemas.in new file mode 100644 index 0000000..2e6b820 --- /dev/null +++ b/shell/data/sugar.schemas.in @@ -0,0 +1,347 @@ +<?xml version="1.0"?> +<gconfschemafile> + <schemalist> + <schema> + <key>/schemas/desktop/sugar/user/nick</key> + <applyto>/desktop/sugar/user/nick</applyto> + <owner>sugar</owner> + <type>string</type> + <default></default> + <locale name="C"> + <short>User Name</short> + <long>User name that is used throughout the desktop.</long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/sugar/user/default_nick</key> + <applyto>/desktop/sugar/user/default_nick</applyto> + <owner>sugar</owner> + <type>string</type> + <default>system</default> + <locale name="C"> + <short>Default nick</short> + <long>"disabled" to ask nick on initialization; "system" to reuse UNIX account long name.</long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/sugar/user/color</key> + <applyto>/desktop/sugar/user/color</applyto> + <owner>sugar</owner> + <type>string</type> + <default></default> + <locale name="C"> + <short>User Color</short> + <long>Color for the XO icon that is used throughout the + desktop. The string is composed of the stroke color and fill + color, format is that of rbg colors. Example: #AC32FF,#9A5200 + </long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/sound/volume</key> + <applyto>/desktop/sugar/sound/volume</applyto> + <owner>sugar</owner> + <type>int</type> + <default>80</default> + <locale name="C"> + <short>Volume Level</short> + <long>Volume level for the sound device.</long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/sugar/sound/mute</key> + <applyto>/desktop/sugar/sound/mute</applyto> + <owner>sugar</owner> + <type>bool</type> + <default>false</default> + <locale name="C"> + <short>Sound Muted</short> + <long>Setting for muting the sound device.</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/backup_url</key> + <applyto>/desktop/sugar/backup_url</applyto> + <owner>sugar</owner> + <type>string</type> + <default></default> + <locale name="C"> + <short>Backup URL</short> + <long>Url where the backup is saved to.</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/date/timezone</key> + <applyto>/desktop/sugar/date/timezone</applyto> + <owner>sugar</owner> + <type>string</type> + <default>UTC</default> + <locale name="C"> + <short>Timezone</short> + <long>Timezone setting for the system.</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/desktop/favorites_layout</key> + <applyto>/desktop/sugar/desktop/favorites_layout</applyto> + <owner>sugar</owner> + <type>string</type> + <default>ring-layout</default> + <locale name="C"> + <short>Favorites Layout</short> + <long>Layout of the favorites view.</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/desktop/favorites_mode</key> + <applyto>/desktop/sugar/desktop/favorites_mode</applyto> + <owner>sugar</owner> + <type>bool</type> + <default>false</default> + <locale name="C"> + <short>Favorites resume mode</short> + <long>When in resume mode, clicking on a favorite icon will cause the last entry for that activity to be resumed.</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/frame/edge_delay</key> + <applyto>/desktop/sugar/frame/edge_delay</applyto> + <owner>sugar</owner> + <type>int</type> + <default>1000</default> + <locale name="C"> + <short>Edge Delay</short> + <long>Delay for the activation of the frame using the edges.</long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/sugar/frame/corner_delay</key> + <applyto>/desktop/sugar/frame/corner_delay</applyto> + <owner>sugar</owner> + <type>int</type> + <default>0</default> + <locale name="C"> + <short>Corner Delay</short> + <long>Delay for the activation of the frame using the corners.</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/collaboration/jabber_server</key> + <applyto>/desktop/sugar/collaboration/jabber_server</applyto> + <owner>sugar</owner> + <type>string</type> + <default>jabber.sugarlabs.org</default> + <locale name="C"> + <short>Jabber Server</short> + <long>Url of the jabber server to use.</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/power/automatic</key> + <applyto>/desktop/sugar/power/automatic</applyto> + <owner>sugar</owner> + <type>bool</type> + <default>false</default> + <locale name="C"> + <short>Power Automatic</short> + <long>Power Automatic.</long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/sugar/power/extreme</key> + <applyto>/desktop/sugar/power/extreme</applyto> + <owner>sugar</owner> + <type>bool</type> + <default>false</default> + <locale name="C"> + <short>Power Extreme</short> + <long>Power Extreme. </long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/collaboration/publish_gadget</key> + <applyto>/desktop/sugar/collaboration/publish_gadget</applyto> + <owner>sugar</owner> + <type>bool</type> + <default>true</default> + <locale name="C"> + <short>Publish to Gadget</short> + <long>If TRUE, Sugar will make us searchable for the other users of the Jabber server.</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/show_logout</key> + <applyto>/desktop/sugar/show_logout</applyto> + <owner>sugar</owner> + <type>bool</type> + <default>true</default> + <locale name="C"> + <short>Show Log out</short> + <long>If TRUE, Sugar will show a "Log out" option.</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/peripherals/keyboard/layouts</key> + <applyto>/desktop/sugar/peripherals/keyboard/layouts</applyto> + <owner>sugar</owner> + <type>list</type> + <list_type>string</list_type> + <locale name="C"> + <short>Keyboard layouts</short> + <long>List of keyboard layouts. Each entry should be in the form layout(variant)</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/peripherals/keyboard/options</key> + <applyto>/desktop/sugar/peripherals/keyboard/options</applyto> + <owner>sugar</owner> + <type>list</type> + <list_type>string</list_type> + <locale name="C"> + <short>Keyboard options</short> + <long>List of keyboard options.</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/peripherals/keyboard/model</key> + <applyto>/desktop/sugar/peripherals/keyboard/model</applyto> + <owner>sugar</owner> + <type>string</type> + <default>evdev</default> + <locale name="C"> + <short>Keyboard model</short> + <long>The keyboard model to be used</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/font/default_face</key> + <applyto>/desktop/sugar/font/default_face</applyto> + <owner>sugar</owner> + <type>string</type> + <default>Sans Serif</default> + <locale name="C"> + <short>Default font face</short> + <long>Font face that is used throughout the desktop.</long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/sugar/font/default_size</key> + <applyto>/desktop/sugar/font/default_size</applyto> + <owner>sugar</owner> + <type>float</type> + <default>10</default> + <locale name="C"> + <short>Default font size</short> + <long>Font size that is used throughout the desktop.</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/i18n/langpackdir</key> + <applyto>/desktop/sugar/i18n/langpackdir</applyto> + <owner>sugar</owner> + <type>string</type> + <default></default> + <locale name="C"> + <short>Directory to search for translations</short> + <long>Additional directories which can contain updated translations.</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/network/gsm/username</key> + <applyto>/desktop/sugar/network/gsm/username</applyto> + <owner>sugar</owner> + <type>string</type> + <default></default> + <locale name="C"> + <short>GSM network username</short> + <long>GSM network username configuration</long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/sugar/network/gsm/password</key> + <applyto>/desktop/sugar/network/gsm/password</applyto> + <owner>sugar</owner> + <type>string</type> + <default></default> + <locale name="C"> + <short>GSM network password</short> + <long>GSM network password configuration</long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/sugar/network/gsm/number</key> + <applyto>/desktop/sugar/network/gsm/number</applyto> + <owner>sugar</owner> + <type>string</type> + <default>*99#</default> + <locale name="C"> + <short>GSM network number</short> + <long>GSM network telephone number configuration</long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/sugar/network/gsm/apn</key> + <applyto>/desktop/sugar/network/gsm/apn</applyto> + <owner>sugar</owner> + <type>string</type> + <default></default> + <locale name="C"> + <short>GSM network APN</short> + <long>GSM network access point name configuration</long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/sugar/network/gsm/pin</key> + <applyto>/desktop/sugar/network/gsm/pin</applyto> + <owner>sugar</owner> + <type>string</type> + <default></default> + <locale name="C"> + <short>GSM network PIN</short> + <long>GSM network personal identification number configuration</long> + </locale> + </schema> + <schema> + <key>/schemas/desktop/sugar/network/gsm/puk</key> + <applyto>/desktop/sugar/network/gsm/puk</applyto> + <owner>sugar</owner> + <type>string</type> + <default></default> + <locale name="C"> + <short>GSM network PUK</short> + <long>GSM network personal unlock key configuration</long> + </locale> + </schema> + + <schema> + <key>/schemas/desktop/sugar/network/adhoc</key> + <applyto>/desktop/sugar/network/adhoc</applyto> + <owner>sugar</owner> + <type>bool</type> + <default>true</default> + <locale name="C"> + <short>Show Sugar Ad-hoc networks</short> + <long>If TRUE, Sugar will show default Ad-hoc networks for + channel 1,6 and 11. If Sugar sees no "known" network when + it starts, it does autoconnect to an Ad-hoc network.</long> + </locale> + </schema> + + </schemalist> +</gconfschemafile> diff --git a/shell/data/sugar.xml.in b/shell/data/sugar.xml.in new file mode 100644 index 0000000..6a7f253 --- /dev/null +++ b/shell/data/sugar.xml.in @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info"> + <mime-type type="application/vnd.olpc-sugar"> + <_comment>Sugar activity bundle</_comment> + <glob pattern="*.xo"/> + </mime-type> + <mime-type type="application/vnd.olpc-content"> + <_comment>Sugar content bundle</_comment> + <glob pattern="*.xol"/> + </mime-type> +</mime-info>
\ No newline at end of file |