Moved the Agents into their own repo. Kept the agent.pl just for reference
This commit is contained in:
parent
22381be29a
commit
8680a02b13
18132 changed files with 0 additions and 2569420 deletions
|
|
@ -1 +0,0 @@
|
|||
Options -Indexes
|
||||
|
|
@ -1,502 +0,0 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 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.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
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 and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, 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 library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete 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 distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
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 Library or any portion
|
||||
of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
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 Library, 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 Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you 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.
|
||||
|
||||
If distribution of 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 satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be 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.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library 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.
|
||||
|
||||
9. 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 Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
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 with
|
||||
this License.
|
||||
|
||||
11. 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 Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library 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 Library.
|
||||
|
||||
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.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library 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.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser 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 Library
|
||||
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 Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
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
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "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
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. 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 LIBRARY 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
|
||||
LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; 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.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
|
@ -1 +0,0 @@
|
|||
allow from all
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,281 +0,0 @@
|
|||
/**
|
||||
* This simply adds some extras to Luminous elements via a jQUery
|
||||
* plugin. The extras are currently a toggleable line-highlighting
|
||||
* on click
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
"use strict";
|
||||
|
||||
var LINE_SELECTOR = 'td .code > span ';
|
||||
|
||||
if (typeof $ === 'undefined') { return; }
|
||||
|
||||
/****************************************************************
|
||||
* UTILITY FUNCTIONS *
|
||||
****************************************************************/
|
||||
|
||||
// determines if the given element is a line element of luminous
|
||||
function isLine($line) {
|
||||
return $line.is(LINE_SELECTOR) && $line.parents('.luminous').length > 0;
|
||||
}
|
||||
|
||||
function isLineNumber($element) {
|
||||
return $element.is('.luminous .line-numbers span');
|
||||
}
|
||||
|
||||
function highlightLine($line) {
|
||||
$line.toggleClass('highlight');
|
||||
}
|
||||
|
||||
function highlightLineByIndex($luminous, index) {
|
||||
var $line = $luminous.find(LINE_SELECTOR).eq(index);
|
||||
highlightLine($line);
|
||||
}
|
||||
|
||||
function highlightLineByNumber($luminous, number) {
|
||||
// the line's index must take into account the initial line number
|
||||
var offset = parseInt($luminous.find('.code').data('startline'), 10);
|
||||
if (isNaN(offset)) offset = 0;
|
||||
highlightLineByIndex($luminous, number - offset);
|
||||
}
|
||||
|
||||
function toggleHighlightAndPlain($luminous, forceState) {
|
||||
var data = $luminous.data('luminous'),
|
||||
state = data.code.active,
|
||||
$elem = $luminous.find('.code'),
|
||||
toSetCode, toSetState;
|
||||
|
||||
if (forceState === 'plain') state = 'highlighted';
|
||||
else if (forceState === 'highlighted') state = 'plain';
|
||||
|
||||
toSetCode = (state === 'plain')? data.code.highlighted : data.code.plain;
|
||||
toSetState = (state === 'plain')? 'highlighted' : 'plain';
|
||||
|
||||
$elem.html(toSetCode);
|
||||
}
|
||||
|
||||
|
||||
function toggleLineNumbers($luminous, forceState) {
|
||||
var data = $luminous.data('luminous'),
|
||||
show = (typeof forceState !== 'undefined')? forceState :
|
||||
!data.lineNumbers.visible;
|
||||
|
||||
data.lineNumbers.visible = show;
|
||||
|
||||
|
||||
var $numberContainer = $luminous.find('.line-numbers'),
|
||||
$control = $luminous.find('.line-number-control');
|
||||
|
||||
if (!show) {
|
||||
$numberContainer.addClass('collapsed');
|
||||
$control.addClass('show-line-numbers');
|
||||
$luminous.addClass('collapsed-line-numbers');
|
||||
} else {
|
||||
$numberContainer.removeClass('collapsed');
|
||||
$control.removeClass('show-line-numbers');
|
||||
}
|
||||
$luminous.data('luminous', data);
|
||||
|
||||
}
|
||||
|
||||
// binds the event handlers to a luminous element
|
||||
function bindLuminousExtras($element) {
|
||||
var highlightLinesData, highlightLines, data = {},
|
||||
hasLineNumbers = $element.find('td .line-numbers').length > 0,
|
||||
schedule = [];
|
||||
|
||||
if (!$element.is('.luminous')) { return false; }
|
||||
else if ($element.is('.bound')) { return true; }
|
||||
|
||||
$element.addClass('bound');
|
||||
|
||||
// highlight lines on click
|
||||
$element.find('td .code').click(function(ev) {
|
||||
var $t = $(ev.target);
|
||||
var $lines = $t.parents().add($t).
|
||||
filter(function() { return isLine($(this)); }),
|
||||
$line
|
||||
;
|
||||
|
||||
if ($lines.length > 0) {
|
||||
$line = $lines.eq(0);
|
||||
highlightLine($line);
|
||||
}
|
||||
});
|
||||
// highlight lines on clicking the line number
|
||||
$element.find('td .line-numbers').click(function(ev) {
|
||||
var $t = $(ev.target),
|
||||
index;
|
||||
if ($t.is('span')) {
|
||||
index = $t.prevAll().length;
|
||||
highlightLineByIndex($element, index);
|
||||
}
|
||||
});
|
||||
|
||||
data.lineNumbers = {visible: false};
|
||||
|
||||
if (hasLineNumbers) {
|
||||
/**
|
||||
* Line numbering is semi complicated because we can make it better
|
||||
* with javascript!
|
||||
* TODO: probably refactor this into a sub-function
|
||||
*/
|
||||
|
||||
// the control is a show/hide line numbers, we can fade it
|
||||
// in/out when the user hovers over the line numbers.
|
||||
// We can also fix the line numbers so they move left
|
||||
// as the widget is hoz-scrolled.
|
||||
var $control, controlHeight, controlWidth, gutterWidth,
|
||||
controlIsVisible = false,
|
||||
$lineNumbers = $element.find('pre.line-numbers'),
|
||||
defaultLineNumberWidth = $lineNumbers.outerWidth(),
|
||||
mouseY = 0,
|
||||
controlCalculateLeftCss = function() {
|
||||
var visible = $element.data('luminous').lineNumbers.visible,
|
||||
base = visible? gutterWidth - controlWidth : 0,
|
||||
total = 0;
|
||||
total = $element.scrollLeft() + base;
|
||||
return total + 'px';
|
||||
|
||||
};
|
||||
|
||||
data.lineNumbers.visible = true;
|
||||
data.lineNumbers.setControlPosition = function() {
|
||||
$control.css('top', Math.max(0, mouseY - (controlHeight/2)) + 'px');
|
||||
}
|
||||
|
||||
$control = $('<a class="line-number-control"></a>');
|
||||
$control.click(function() {
|
||||
$element.luminous('showLineNumbers');
|
||||
$control.css('left', controlCalculateLeftCss());
|
||||
if (!$element.data('luminous').lineNumbers.visible) {
|
||||
$element.find('pre.code').css('padding-left', '');
|
||||
} else {
|
||||
$element.find('pre.code').css('padding-left', defaultLineNumberWidth + 'px');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$control.appendTo($element);
|
||||
$control.show();
|
||||
controlWidth = $control.outerWidth();
|
||||
controlHeight = $control.outerHeight();
|
||||
gutterWidth = $element.find('.line-numbers').outerWidth();
|
||||
$control.css('left', gutterWidth - controlWidth + 'px');
|
||||
$control.hide();
|
||||
$element.mousemove(function(ev) {
|
||||
var scrollLeft = $element.scrollLeft();
|
||||
mouseY = ev.pageY - $(this).offset().top;
|
||||
if (ev.pageX < gutterWidth) {
|
||||
if (!controlIsVisible) {
|
||||
data.lineNumbers.setControlPosition();
|
||||
$control.stop(true, true).fadeIn('fast');
|
||||
controlIsVisible = true;
|
||||
}
|
||||
} else {
|
||||
if (controlIsVisible) {
|
||||
$control.stop(true, true).fadeOut('fast');
|
||||
controlIsVisible = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
data.lineNumbers.setControlPosition();
|
||||
$element.find('pre.code').css('padding-left', $lineNumbers.outerWidth() + 'px');
|
||||
$lineNumbers.css({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0
|
||||
});
|
||||
$element.scroll(function() {
|
||||
data.lineNumbers.setControlPosition();
|
||||
$control.css('left', controlCalculateLeftCss());
|
||||
$lineNumbers.css('left', $element.scrollLeft() + 'px');
|
||||
});
|
||||
schedule.push(function() { $element.luminous('showLineNumbers', true); });
|
||||
$element.find('.line-numbers').parent().css({width: 0, maxWidth: 0});
|
||||
|
||||
}
|
||||
|
||||
// highlight all the initial lines
|
||||
highlightLinesData = $element.find('.code').data('highlightlines') || "";
|
||||
highlightLines = highlightLinesData.split(",");
|
||||
$.each(highlightLines, function(i, element) {
|
||||
var lineNo = parseInt(element, 10);
|
||||
if (!isNaN(lineNo)) {
|
||||
highlightLineByNumber($element, lineNo);
|
||||
}
|
||||
});
|
||||
|
||||
data.code = {};
|
||||
data.code.highlighted = $element.find('.code').html();
|
||||
|
||||
data.code.plain = '';
|
||||
$element.find(LINE_SELECTOR).each(function(i, e) {
|
||||
var line = $(e).text();
|
||||
line = line
|
||||
.replace(/&/g, '&')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/</g, '<');
|
||||
|
||||
data.code.plain += '<span>' + line + '</span>';
|
||||
});
|
||||
data.code.active = 'highlighted';
|
||||
|
||||
$element.data('luminous', data);
|
||||
|
||||
$.each(schedule, function(i, f) {
|
||||
f();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* JQUERY PLUGIN *
|
||||
***************************************************************/
|
||||
|
||||
|
||||
$.fn.luminous = function(optionsOrCommand /* variadic */) {
|
||||
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
|
||||
return $(this).each(function() {
|
||||
var $luminous = $(this);
|
||||
|
||||
// no instructions - bind everything
|
||||
if (!optionsOrCommand) {
|
||||
bindLuminousExtras($luminous);
|
||||
return;
|
||||
}
|
||||
|
||||
// $('.luminous').luminous('highlightLine', [2, 3]);
|
||||
if (optionsOrCommand === 'highlightLine') {
|
||||
var lineNumbers = args[1];
|
||||
if (!$.isArray(lineNumbers))
|
||||
lineNumbers = [lineNumbers];
|
||||
|
||||
$.each(lineNumbers, function(index, el) {
|
||||
highlightLineByNumber($luminous, el);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
else if (optionsOrCommand === 'show') {
|
||||
// args[1] should be 'highlighted' or 'plain'
|
||||
toggleHighlightAndPlain($luminous, args[1]);
|
||||
}
|
||||
else if (optionsOrCommand === 'showLineNumbers') {
|
||||
toggleLineNumbers($luminous, args[1]);
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
$('.luminous').luminous();
|
||||
});
|
||||
|
||||
}(jQuery));
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Luminous Syntax Highlighter</title>
|
||||
<link rel='stylesheet' type='text/css' href='style/luminous.css'>
|
||||
<link rel='stylesheet' type='text/css' href='style/geonyx.css'>
|
||||
<style>
|
||||
h1{font-size: x-large;}
|
||||
h2{font-size: large; }
|
||||
h3{font-size: medium;}
|
||||
body{ margin:1em; font-family: sans-serif; font-size:12pt;}
|
||||
.luminous { border: 1px solid #bbb; }
|
||||
span.inline-code {
|
||||
background-color: #E7E7E7;
|
||||
padding: 1px 0.25em;
|
||||
font-family: monospace;
|
||||
font-weight: bold;
|
||||
color: #323232;
|
||||
border: 1px solid #888;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Luminous - a Syntax Highlighter for PHP - v0.7.0</h1>
|
||||
|
||||
<p><a href="http://travis-ci.org/markwatkinson/luminous"><img src="https://secure.travis-ci.org/markwatkinson/luminous.png" alt="Build Status" title="" /></a></p>
|
||||
|
||||
<p>Luminous is an accurate and style-able syntax highlighter for PHP which
|
||||
supports a bunch of common languages and output to HTML and LaTeX.</p>
|
||||
|
||||
<p>If you simply want to use Luminous as a library, <strong>please don't clone this
|
||||
repository</strong>. Or if you do, make sure you delete luminous/tests afterwards.
|
||||
Do not expose luminous/tests on a public machine. It is recommended to get a
|
||||
packaged version from the links below.</p>
|
||||
|
||||
<h2>Links:</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="http://luminous.asgaard.co.uk/">Luminous PHP syntax highlighter official site</a> - news, latest stable versions, etc</li>
|
||||
<li><a href="http://luminous.asgaard.co.uk/index.php/demo">Online demo</a></li>
|
||||
<li><a href="http://luminous.asgaard.co.uk/index.php/docs/show/index">Documentation and help</a>,
|
||||
read this if you get stuck!</li>
|
||||
<li><a href="http://luminous.asgaard.co.uk/assets/luminous/supported.php">Supported language list</a></li>
|
||||
<li><a href="https://github.com/markwatkinson/luminous">Luminous on GitHub</a> - please
|
||||
report problems to the issue tracker here</li>
|
||||
</ul>
|
||||
|
||||
<h1>Installation</h1>
|
||||
|
||||
<p>Extract your tarball, zip, whatever, into some directory where it's going to be
|
||||
used (i.e. probably your web-server). We'll assume it's called `luminous/'</p>
|
||||
|
||||
<h1>Quick Usage </h1>
|
||||
|
||||
<p>First, if you're going to use caching, which you probably are, create a
|
||||
directory called luminous/cache and give it writable permissions (chmod 777 on
|
||||
most servers -- yours may accept a less permissive value). Then include
|
||||
luminous/luminous.php and away you go!</p>
|
||||
|
||||
<p><div
|
||||
class="luminous"
|
||||
data-language="PHP"
|
||||
style=""
|
||||
><table><tbody><tr>
|
||||
<td><pre class="line-numbers"><span>1</span><span>2</span><span>3</span><span>4</span></pre></td>
|
||||
|
||||
<td class="code-container"><pre class="code numbered"
|
||||
data-startline="1"
|
||||
data-highlightlines=""
|
||||
><span><span class='delimiter'><?php</span>
|
||||
</span><span><span class='function'>require_once</span> <span class='string'>'luminous/luminous.php'</span><span class='operator'>;</span>
|
||||
</span><span><span class='function'>echo</span> <span class='obj'>luminous</span><span class='operator'>::</span><span class='oo'>head_html</span>()<span class='operator'>;</span> <span class='comment'>// outputs CSS includes, intended to go in <head></span>
|
||||
</span><span><span class='function'>echo</span> <span class='obj'>luminous</span><span class='operator'>::</span><span class='oo'>highlight</span>(<span class='string'>'c'</span><span class='operator'>,</span> <span class='string'>'printf("hello world<span class='esc'>\n</span>");'</span>)<span class='operator'>;</span>
|
||||
</span></pre></td></tr></tbody></table></div></p>
|
||||
|
||||
<p>Useful examples can be found in luminous/examples/. If you have problems,
|
||||
check that luminous/examples/example.php works.</p>
|
||||
|
||||
<h1>Command Line Usage</h1>
|
||||
|
||||
<p>If you're crazy and want to use Luminous/PHP on the command line, guess what,
|
||||
you can!</p>
|
||||
|
||||
<p><div
|
||||
class="luminous"
|
||||
data-language="Bash"
|
||||
style=""
|
||||
><table><tbody><tr><td><pre class="line-numbers"><span>1</span><span>2</span></pre></td><td class="code-container"><pre class="code numbered"
|
||||
data-startline="1"
|
||||
data-highlightlines=""
|
||||
><span>$ <span class='function'>cd</span> luminous/
|
||||
</span><span>$ php luminous.php --help
|
||||
</span></pre></td></tr></tbody></table></div></p>
|
||||
|
||||
<h1>Polite Warning</h1>
|
||||
|
||||
<p>Luminous is fairly slow. But it caches! So it's not slow. Or is it?</p>
|
||||
|
||||
<p>It depends on your use-case, is the simple answer. Most people should make sure
|
||||
the cache works (create luminous/cache with appropriate permissions), and after
|
||||
that, Luminous will almost certainly have negligable impact on their
|
||||
performance.</p>
|
||||
|
||||
<p>Optimizations are welcome, but not at the expense of maintainability.</p>
|
||||
|
||||
<h2>Caching</h2>
|
||||
|
||||
<p>The cache can be stored either directly on the file system or in a MySQL table
|
||||
(support for other DBMSs will come later, patches welcome). In either case,
|
||||
check out the <a href="http://luminous.asgaard.co.uk/index.php/docs/show/cache">cache documentation</a>.</p>
|
||||
|
||||
<h1>Licensing</h1>
|
||||
|
||||
<p>Luminous is distributed under the LGPL but includes a bunch of stuff which is
|
||||
separate.</p>
|
||||
|
||||
<ul>
|
||||
<li>Everything under src/ and languages/ is part of Luminous.</li>
|
||||
<li>Everything under tests/regression/<em>/</em> is real source code taken from various
|
||||
projects, which is used only as test data. It is all GPL-compatible, but
|
||||
is distributed under its own license. This directory is only present in
|
||||
the git repository and is not part of any stable distribution archives.</li>
|
||||
<li>We also include jQuery which is provided under its own license.</li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1 +0,0 @@
|
|||
Deny from All
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* TODO: user defined types and stuff
|
||||
*
|
||||
*/
|
||||
|
||||
class LuminousAdaScanner extends LuminousSimpleScanner {
|
||||
|
||||
public function init() {
|
||||
// http://en.wikibooks.org/wiki/Ada_Programming/Keywords
|
||||
// http://en.wikibooks.org/wiki/Ada_Programming/All_Keywords
|
||||
$kws = array('abort', 'abstract', 'accept', 'access', 'aliased',
|
||||
'all', 'array', 'at',
|
||||
'begin', 'body',
|
||||
'case', 'constant',
|
||||
'declare','delay', 'delta', 'digits', 'do',
|
||||
'else', 'elsif', 'end', 'entry', 'exception', 'exit',
|
||||
'for', 'function',
|
||||
'generic', 'goto',
|
||||
'if', 'interface', 'is',
|
||||
'limited', 'loop',
|
||||
'new',
|
||||
'of', 'others', 'out', 'overriding',
|
||||
'package', 'pragma', 'private', 'procedure', 'protected',
|
||||
'raise', 'range', 'record', 'renames', 'requeue', 'return', 'reverse',
|
||||
'select', 'separate', 'subtype', 'synchronized',
|
||||
'tagged', 'task', 'terminate', 'then', 'type',
|
||||
'until', 'use',
|
||||
'when', 'while', 'with',
|
||||
);
|
||||
$ops = array('abs', 'and', 'in', 'mod', 'not', 'or', 'rem', 'xor');
|
||||
$vals = array('false', 'null', 'true');
|
||||
// http://en.wikibooks.org/wiki/Ada_Programming/Type_System#Predefined_types
|
||||
$types = array('Float', 'Duration', 'Character', 'String', 'Boolean',
|
||||
'Address', 'Storage_Offset', 'Storage_Count', 'Storage_Element',
|
||||
'Storage_Array',
|
||||
'Wide_character', 'Wide_Wide_Character',
|
||||
'Wide_String', 'Wide_Wide_String',
|
||||
'Integer',
|
||||
'Long', 'Short', 'Byte');
|
||||
|
||||
$ident = '(?i:[a-z](?:_?[a-z]++|\d++)*+)';
|
||||
// http://en.wikibooks.org/wiki/Ada_Programming/Lexical_elements#Identifiers
|
||||
$this->add_pattern('OO', "/(?<=[a-z0-9_]')$ident/");
|
||||
$this->add_pattern('IDENT', "/$ident/");
|
||||
// http://en.wikibooks.org/wiki/Ada_Programming/Lexical_elements#Numbers
|
||||
// no bnf :( might be wrong
|
||||
$this->add_pattern('NUMERIC', '/\d+#[a-f0-9]*#/i');
|
||||
$this->add_pattern('NUMERIC', "/[0-9]++[0-9_]*+(\.[0-9_]++)?([eE][\-+]?[0-9_]++)?/");
|
||||
$this->add_pattern('COMMENT', '/--.*/');
|
||||
$this->add_pattern('OPERATOR', '@=|/=|>=?|<=?|\+|-|\*\*?|/|&|:=@');
|
||||
|
||||
// http://rosettacode.org/wiki/Special_characters#Ada
|
||||
$this->add_pattern('CHARACTER', "/'.'/");
|
||||
$this->add_pattern('STRING', '/"(?:[^"]++|"")*"/');
|
||||
|
||||
$this->add_identifier_mapping('KEYWORD', $kws);
|
||||
$this->add_identifier_mapping('OPERATOR', $ops);
|
||||
$this->add_identifier_mapping('VALUE', $vals);
|
||||
$this->add_identifier_mapping('TYPE', $types);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
<?php
|
||||
|
||||
// as far as I know, actionscript and javascript are both derivatives of
|
||||
// ECMA script, and therefore we can subclass JavaScript's scanner and just
|
||||
// and override the identifier names.
|
||||
// but we also override init so as to prevent any embedding
|
||||
|
||||
class LuminousActionScriptScanner extends LuminousECMAScriptScanner {
|
||||
|
||||
|
||||
function init() {
|
||||
$this->embedded_server = false;
|
||||
$this->embedded_script = false;
|
||||
parent::init();
|
||||
|
||||
// add preprocessor support
|
||||
$this->add_pattern('PREPROCESSOR', '/\^\s*#.*/m');
|
||||
|
||||
|
||||
// clear the identifier map for JS and insert our own.
|
||||
// $this->ident_map = array();
|
||||
$this->add_identifier_mapping('', array());
|
||||
|
||||
|
||||
|
||||
$this->add_identifier_mapping('FUNCTION', array('add', 'chr',
|
||||
'clearInterval', 'escape', 'eval',
|
||||
'evaluate', 'fscommand', 'getProperty', 'getTimer', 'getVersion',
|
||||
'globalStyleFormat', 'gotoAndPlay', 'gotoAndStop', 'ifFrameLoaded',
|
||||
'instanceOf', 'isFinite', 'isNaN', 'loadMovie', 'loadMovieNum',
|
||||
'loadVariables', 'mbchr', 'mblength', 'mbord', 'mbsubstring', 'nextFrame',
|
||||
'nextScene', 'onClipEvent',
|
||||
'ord', 'parseFloat', 'parseInt', 'play', 'prevFrame', 'prevScene', 'print',
|
||||
'printAsBitMap', 'printNum', 'printNum', 'random', 'scroll', 'setInterval',
|
||||
'setProperty', 'stop', 'stopDrag', 'substring', 'super', 'targetPath',
|
||||
'tellTarget', 'toString', 'toggleHighQuality', 'trace', 'unescape'));
|
||||
|
||||
$this->add_identifier_mapping('TYPE', array('Accessibility',
|
||||
'Array', 'Arguments', 'Boolean',
|
||||
'Button', 'ByteArray', 'Camera', 'Color', 'Date', 'Event', 'FScrollPane',
|
||||
'FStyleFormat',
|
||||
'Function', 'int', 'Key', 'LoadVars', 'LocalConnection', 'Math',
|
||||
'Microphone', 'Mouse', 'Movieclip', 'Number', 'Object', 'Selection',
|
||||
'Sound', 'Sprite', 'String', 'System', 'TextField', 'TextFormat',
|
||||
'Timer', 'TimerEvent', 'uint', 'var', 'void', 'XML'));
|
||||
|
||||
$this->add_identifier_mapping('KEYWORD', array('as', 'break',
|
||||
'case', 'catch', 'class', 'const', 'continue', 'default', 'delete',
|
||||
'do', 'else', 'extends', 'false', 'finally', 'for', 'function',
|
||||
'if', 'implements', 'import', 'in', 'instanceof', 'interface', 'internal',
|
||||
'is', 'native', 'new', 'null', 'package', 'private', 'protected', 'public',
|
||||
'return', 'super', 'switch', 'static', 'this', 'throw', 'to', 'true', 'try',
|
||||
'typeof', 'use', 'void', 'while', 'with'));
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
// actionscript looks a lot like a cross between Java and, umm, well,
|
||||
// Java.
|
||||
// It has a semi-unique way of declaring types for arguments and
|
||||
// returns and so forth as argname:type, or function name(args):ret-type
|
||||
$p = 0.0;
|
||||
|
||||
if (preg_match(
|
||||
'/\\bfunction\s+\w+\s*\\([^\\)]+\\):(String|int|Number|void)/',
|
||||
$src)) $p += 0.15;
|
||||
if (preg_match('/\\bvar\s+\w+:(String|int|Number)/', $src)) $p += 0.15;
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,273 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* XXX: I don't really know bash all that well. I don't know how the
|
||||
* interpolation rules work exactly, i.e. if
|
||||
* x=" $( # )"
|
||||
* is a left unterminated by the comment or if the comment terminates at the )
|
||||
* Kate things the latter and I'll go with it.
|
||||
*
|
||||
*
|
||||
* 2011-10-10: Changed comment regex to require a preceding whitespace char
|
||||
* (or start of string). This seems in line with Kate, and it prevents
|
||||
* incorrectly hitting some things as comments which are actually
|
||||
* [I have no idea]. e.g.: for (( i=0; i<${#1}; i=i+2 ));
|
||||
*
|
||||
* Also changed it to not apply any highlighting between (( ... ))
|
||||
* blocks, which fixes a bug regarding shifts being detected as
|
||||
* heredocs. This is buggy - it should detect SOME types inside
|
||||
* these blocks, and it should be aware of nested brackets. FIXME.
|
||||
*/
|
||||
|
||||
class LuminousBashScanner extends LuminousScanner {
|
||||
|
||||
public $interpolated = false;
|
||||
|
||||
|
||||
public static function string_filter($token) {
|
||||
$token = LuminousUtils::escape_token($token);
|
||||
$token[1] = preg_replace("/\\$(?:\w+|\\{[^}\n]+\\})/",
|
||||
'<VARIABLE>$0</VARIABLE>', $token[1]);
|
||||
return $token;
|
||||
}
|
||||
|
||||
public function init() {
|
||||
$this->add_identifier_mapping('KEYWORD', array('case', 'do', 'done',
|
||||
'elif', 'else', 'esac', 'fi', 'for', 'function', 'if', 'in', 'select',
|
||||
'then', 'time', 'until', 'while',
|
||||
'foreach', 'end' // zsh I think
|
||||
));
|
||||
// I could ls /usr/bin, but i think this will do for now
|
||||
$this->add_identifier_mapping('FUNCTION', array('adduser', 'addgroup',
|
||||
'alias', 'apropos', 'apt-get', 'aptitude', 'aspell', 'awk', 'basename', 'bash',
|
||||
'bc', 'bg', 'break', 'builtin', 'bzip2', 'cal', 'case', 'cat', 'cd', 'cfdisk',
|
||||
'chgrp', 'chmod', 'chown', 'chroot', 'chkconfig', 'cksum', 'clear', 'cmp',
|
||||
'comm', 'command', 'continue', 'cp', 'cron', 'crontab', 'csplit', 'cut', 'date',
|
||||
'dc', 'dd', 'ddrescue', 'declare', 'df', 'diff', 'diff3', 'dig', 'dir',
|
||||
'dircolors', 'dirname', 'dirs', 'dmesg', 'du', 'echo', 'egrep', 'eject',
|
||||
'enable', 'env', 'ethtool', 'eval', 'exec', 'exit', 'expect', 'expand',
|
||||
'export', 'expr', 'false', 'fdformat', 'fdisk', 'fg', 'fgrep', 'file', 'find',
|
||||
'fmt', 'fold', 'for', 'format', 'free', 'fsck', 'ftp', 'function', 'fuser',
|
||||
'gawk', 'getopts', 'git', 'grep', 'groups', 'gzip', 'hash', 'head', 'help',
|
||||
'history', 'hg', 'hostname', 'iconv', 'id', 'if', 'ifconfig', 'ifdown', 'ifup',
|
||||
'import', 'install', 'jobs', 'join', 'kill', 'killall', 'less', 'let', 'ln',
|
||||
'local', 'locate', 'logname', 'logout', 'look', 'lpc', 'lpr', 'lprint',
|
||||
'lprintd', 'lprintq', 'lprm', 'ls', 'lsof', 'make', 'man', 'mkdir', 'mkfifo',
|
||||
'mkisofs', 'mknod', 'more', 'mount', 'mtools', 'mtr', 'mv', 'mmv', 'nano',
|
||||
'netstat', 'nice', 'nl', 'nohup', 'notify-send', 'nslookup', 'open', 'op',
|
||||
'passwd', 'paste', 'pathchk', 'ping', 'pkill', 'popd', 'pr', 'printcap',
|
||||
'printenv', 'printf', 'ps', 'pushd', 'pwd', 'quota', 'quotacheck', 'quotactl',
|
||||
'ram', 'rcp', 'read', 'readarray', 'readonly', 'reboot', 'rename', 'renice',
|
||||
'remsync', 'return', 'rev', 'rm', 'rmdir', 'rsync', 'screen', 'scp', 'sdiff',
|
||||
'sed', 'select', 'seq', 'set', 'sftp', 'shift', 'shopt', 'shutdown', 'sleep',
|
||||
'slocate', 'sort', 'source', 'split', 'ssh', 'strace', 'su', 'sudo', 'sum',
|
||||
'suspend', 'svn', 'symlink', 'sync', 'tail', 'tar', 'tee', 'test', 'time',
|
||||
'times', 'touch', 'top', 'traceroute', 'trap', 'tr', 'true', 'tsort', 'tty',
|
||||
'type', 'ulimit', 'umask', 'umount', 'unalias', 'uname', 'unexpand', 'uniq',
|
||||
'units', 'unset', 'unshar', 'until', 'useradd', 'usermod', 'users', 'uuencode',
|
||||
'uudecode', 'v', 'vdir', 'vi', 'vim', 'vmstat', 'watch', 'wc', 'whereis',
|
||||
'which', 'while', 'who', 'whoami', 'Wget', 'write', 'xargs', 'xdg-open',
|
||||
'yes',));
|
||||
$this->remove_stream_filter('oo-syntax');
|
||||
$this->remove_filter('comment-to-doc');
|
||||
$this->add_filter('str-filter', 'STRING', array($this, 'string_filter'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
function main() {
|
||||
|
||||
$stack = array();
|
||||
while(!$this->eos()) {
|
||||
|
||||
$c = $this->peek();
|
||||
|
||||
// double brackets are apparently an arithemtic operation
|
||||
// http://stackoverflow.com/questions/2188199/bash-double-or-single-bracket-parentheses-curly-braces
|
||||
// anyway, if we apply normal highlighting in them, it seems to break some
|
||||
// things
|
||||
// TODO I think we should respect certain sub-types in the (( ... ))
|
||||
// block, like strings and other stuff. It may require re-factoring the
|
||||
// scanner to get this right. It may be best to switch this to a
|
||||
// LumiousStatefulScanner. This will do for now though.
|
||||
if ($this->scan('/(\\$?)(\({2})/')) {
|
||||
$dollar = $this->match_group(1);
|
||||
$this->record($this->match(), $dollar? 'KEYWORD' : null);
|
||||
if ($this->scan_until('/\){2}/') !== null) {
|
||||
$this->record($this->match(), null);
|
||||
$this->record($this->scan('/\){2}/'), $dollar? 'KEYWORD' : null);
|
||||
} else {
|
||||
$this->record($this->rest(), null);
|
||||
$this->terminate();
|
||||
}
|
||||
}
|
||||
if ($this->scan('/\\$([{(])/')) {
|
||||
$this->record($this->match(), 'KEYWORD');
|
||||
$stack[] = array($this->match_group(1), true);
|
||||
}
|
||||
elseif($c === '[') {
|
||||
$this->record($this->get(), 'KEYWORD');
|
||||
$stack[] = array($c, true);
|
||||
}
|
||||
elseif ($c === '{' || $c === '(') {
|
||||
$this->record($this->get(), null);
|
||||
$stack[] = array($c, false);
|
||||
}
|
||||
elseif($c === '}' || $c === ')' || $c ===']') {
|
||||
$match = array('{'=>'}', '('=>')', '[' => ']');
|
||||
$type = null;
|
||||
if (isset($stack[0])) {
|
||||
$pop = array_pop($stack);
|
||||
if ($pop[1]) $type = 'KEYWORD';
|
||||
if ($match[$pop[0]] !== $c) {
|
||||
// err
|
||||
$stack[] = $pop;
|
||||
$type = null;
|
||||
}
|
||||
}
|
||||
$this->record($this->get(), $type);
|
||||
if (empty($stack) && $this->interpolated) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
elseif($c === '`') {
|
||||
$this->record($this->get(), 'KEYWORD');
|
||||
}
|
||||
elseif ($this->scan('/
|
||||
\$( [_a-zA-Z]\w* | [\d\#*@\-!_\\?\\$])
|
||||
/xm')
|
||||
) {
|
||||
$this->record($this->match(), 'VARIABLE');
|
||||
}
|
||||
elseif($this->scan('/^(\s*)([_a-zA-Z]\w*(?=[=]))/m')) {
|
||||
$m = $this->match_groups();
|
||||
if ($m[1] !== '') $this->record($m[1], null);
|
||||
$this->record($m[2], 'VARIABLE');
|
||||
|
||||
}
|
||||
elseif (($this->interpolated && count($stack) === 1 &&
|
||||
$this->scan('/(?<=\s|^)\#.*?(?=[)]|$)/m'))
|
||||
|| $this->scan('/(?<=\s|^)\#.*/')) {
|
||||
$this->record($this->match(), 'COMMENT');
|
||||
}
|
||||
elseif(($m = $this->scan("/\\$?'(?> [^'\\\\]+ | \\\\.)* '/sx"))) {
|
||||
$tok = ($m[0] === '$')? 'VARIABLE' : 'STRING';
|
||||
$this->record($m, $tok);
|
||||
}
|
||||
elseif($this->scan('/-*[a-zA-Z_][\-\w]*/')) {
|
||||
$this->record($this->match(), 'IDENT');
|
||||
}
|
||||
// quoted heredoc is the same as a single string, no interpolation,
|
||||
// A straight regex is causing backtracking problems on my box so
|
||||
// we're going to do it the hard way
|
||||
// note that the <<- means the delimiter can be indented.
|
||||
elseif($this->scan('/(<<-?)(\s*)(["\'])(\w+)((?:\\3)?)/msx')) {
|
||||
$m = $this->match_groups();
|
||||
$this->record($m[1] . $m[2], null);
|
||||
$this->record($m[3] . $m[4] . $m[5], 'DELIMITER');
|
||||
$delim_regex = "/^(" . (($m[1] === '<<-')? '\s*' : '')
|
||||
. ')(' . preg_quote($m[4], '/') . ')\\b/m';
|
||||
$heredoc = $this->scan_until($delim_regex);
|
||||
if ($heredoc === null) {
|
||||
$heredoc = $this->rest();
|
||||
$this->terminate();
|
||||
}
|
||||
$this->record($heredoc, 'HEREDOC');
|
||||
if ($this->scan($delim_regex) !== null) {
|
||||
$g = $this->match_groups();
|
||||
if ($g[1] !== '') $this->record($g[1], null);
|
||||
$this->record($g[2], 'DELIMITER');
|
||||
}
|
||||
}
|
||||
// heredocs and double quoted strings are pretty much the same
|
||||
elseif($this->scan('/(<<-?\s*)(\w+)/') ||
|
||||
$this->scan('/\\$?"/'))
|
||||
{
|
||||
$pos = $this->match_pos();
|
||||
|
||||
$m = $this->match_groups();
|
||||
$type = 'STRING';
|
||||
$delim = '';
|
||||
if ($m[0][0] === '<') {
|
||||
$type = 'HEREDOC';
|
||||
$this->record($m[1], null);
|
||||
$this->record($m[2], 'KEYWORD');
|
||||
$delim = $m[2];
|
||||
if ($m[0][2] === '-') $delim = "[ \t]*" . $delim;
|
||||
$pos = $this->pos();
|
||||
}
|
||||
elseif($m[0][0] === '$') $type = 'VARIABLE';
|
||||
$in_str = true;
|
||||
|
||||
$searches = array(($type === 'HEREDOC')? "/^$delim\\b/m" :
|
||||
'/(?<!\\\\)((?:\\\\\\\\)*)(")/',
|
||||
'/(?<!\\\\)((?:\\\\\\\\)*)(\\$\\()/');
|
||||
|
||||
while(1) {
|
||||
list($index, $matches) = $this->get_next($searches);
|
||||
|
||||
if ($index === -1) {
|
||||
$this->record(substr($this->string(), $pos), $type);
|
||||
$this->terminate();
|
||||
break;
|
||||
}
|
||||
$hit = isset($matches[2])? $matches[2] : $matches[0];
|
||||
$index_ = $index + strlen($matches[0]);
|
||||
if($hit === '"') {
|
||||
$this->record(substr($this->string(), $pos, $index_ - $pos), $type);
|
||||
$this->pos($index_);
|
||||
break;
|
||||
}
|
||||
// URGH WORST CHECK EVER.
|
||||
elseif($type === 'HEREDOC' && !isset($matches[2])) {
|
||||
$this->record(substr($this->string(), $pos, $index-$pos), $type);
|
||||
$this->record($hit, 'KEYWORD');
|
||||
$this->pos($index_);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
$index_ = $index + strlen($matches[1]);
|
||||
$this->record(substr($this->string(), $pos, $index_-$pos), $type);
|
||||
$child = new LuminousBashScanner($this->string());
|
||||
$child->pos($index_);
|
||||
$child->interpolated = true;
|
||||
$child->init();
|
||||
$child->main();
|
||||
$this->record($child->tagged(), 'INTERPOLATED', true);
|
||||
$pos = $child->pos();
|
||||
$this->pos($pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif($this->scan('/\d*[<>]+&?\d*/')) {
|
||||
$this->record($this->match(), 'KEYWORD');
|
||||
}
|
||||
|
||||
elseif($this->scan("/[^_\-a-zA-Z$'\"\#\{\}\(\)\[\]<>&\d`\n]+/") !== null) {
|
||||
$this->record($this->match(), null);
|
||||
}
|
||||
else
|
||||
$this->record($this->get(), null);
|
||||
}
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
$p = 0.0;
|
||||
if (preg_match('%\\b (?:bash|csh|ksh|zsh|sh) \\b%x',
|
||||
$info['shebang'])
|
||||
)
|
||||
return 1.0;
|
||||
|
||||
// strange conditional syntax -- if [ -z ... ]
|
||||
if (preg_match('/ (if|while) \s++ \\[\s++-\w/x', $src)) $p += 0.10;
|
||||
|
||||
// quoted vars used in comparison: if [ "$somevar" ...
|
||||
if (preg_match('/"\\$\w++"/', $src)) $p += 0.05;
|
||||
|
||||
// case ... esac has to be worth something
|
||||
if (strpos($src, 'case') < strpos($src, 'esac')) $p += 0.1;
|
||||
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* BNF has a lot of different variants and matching them all is pretty much
|
||||
* impossible.
|
||||
*
|
||||
* We're going to match the standard BNF and extended BNF and hopefully a
|
||||
* few very similar dialects
|
||||
*/
|
||||
|
||||
class LuminousBNFScanner extends LuminousStatefulScanner {
|
||||
|
||||
function user_def_ext($matches) {
|
||||
if ($matches[1] !== '')
|
||||
$this->record($matches[1], null);
|
||||
$this->record_token($matches[2], 'USER_FUNCTION');
|
||||
$this->user_defs[$matches[2]] = 'VALUE';
|
||||
$this->pos_shift(strlen($matches[1]) + strlen($matches[2]));
|
||||
}
|
||||
|
||||
private function set_strict() {
|
||||
// no transition table necessary, I think
|
||||
$this->add_pattern('COMMENT', '/<![^>]*>/');
|
||||
$this->add_pattern('KEYWORD', '/(?<=^<)[^>]+(?=>)/m');
|
||||
$this->add_pattern('KEYWORD', '/(?<=^\\{)[^\\}]+(?=\\})/m');
|
||||
$this->add_pattern('VALUE', '/(?<=\\{)[^\\}]+(?=\\})/');
|
||||
$this->add_pattern('VALUE', '/[\\-\w]+/');
|
||||
|
||||
}
|
||||
private function set_extended() {
|
||||
|
||||
|
||||
$this->add_pattern('COMMENT', '/\\(\\* .*? \\*\\)/sx');
|
||||
$this->add_pattern('OPTION', '/\\[/', '/\\]/');
|
||||
$this->add_pattern('REPETITION', '/\\{/', '/\\}/');
|
||||
$this->add_pattern('GROUP', '/\\(/', '/\\)/');
|
||||
$this->add_pattern('SPECIAL', '/\\?/', '/\\?/');
|
||||
|
||||
$ident = '(?:[\w\\-]+)';
|
||||
$this->add_pattern('RULE', "/(^[ \t]*)($ident)(\s*(?![[:alnum:]\s]))/mi");
|
||||
$this->overrides['RULE'] = array($this, 'user_def_ext');
|
||||
$this->add_pattern('IDENT', "/$ident/");
|
||||
|
||||
// technically I don't know if we really need to worry about a transition
|
||||
// table, but here we are anyway
|
||||
$all = array('COMMENT', 'OPTION', 'REPETITION', 'GROUP', 'SPECIAL',
|
||||
'STRING', 'IDENT', 'OPERATOR');
|
||||
$almost_all = array_filter($all, create_function('$x',
|
||||
'return $x !== "SPECIAL";'));
|
||||
$this->transitions = array(
|
||||
'initial' => array_merge(array('RULE'), $all),
|
||||
'OPTION' => $all,
|
||||
'REPETITION' => $all,
|
||||
'GROUP' => $all,
|
||||
'SPECIAL' => $almost_all
|
||||
);
|
||||
|
||||
$this->rule_tag_map = array(
|
||||
'OPTION' => null,
|
||||
'REPETITION' => null,
|
||||
'GROUP' => null,
|
||||
'SPECIAL' => null
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function init() {
|
||||
|
||||
// the original BNF uses <angle brackets> to delimit its
|
||||
// production rule names
|
||||
if (preg_match('/<\w+>/', $this->string())) {
|
||||
$this->set_strict();
|
||||
}
|
||||
else {
|
||||
$this->set_extended();
|
||||
}
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$SINGLE_STR_SL);
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$DOUBLE_STR_SL);
|
||||
$this->add_pattern('OPERATOR', '/[*\\-=+;:\\|,]+/');
|
||||
// assume a few chars at bol indicate a commented line
|
||||
$this->add_pattern('COMMENT', '/^[!%-;].*/m');
|
||||
|
||||
$this->remove_filter('constant');
|
||||
$this->remove_filter('comment-to-doc');
|
||||
|
||||
}
|
||||
|
||||
static function guess_language($src, $info) {
|
||||
// being honest, BNF is going to be so rare that if we ever return
|
||||
// anything other than 0, it's more likely that we're obscuring the
|
||||
// correct scanner than correctly identifying BNF.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(__FILE__) . '/include/c_func_list.php');
|
||||
// TODO: trigraph... does anyone use these?
|
||||
|
||||
class LuminousCppScanner extends LuminousSimpleScanner {
|
||||
|
||||
function __construct($src=null) {
|
||||
parent::__construct($src);
|
||||
$this->add_filter('preprocessor', 'PREPROCESSOR',
|
||||
array($this, 'preprocessor_filter'));
|
||||
|
||||
$this->add_identifier_mapping('FUNCTION',
|
||||
$GLOBALS['luminous_c_funcs']);
|
||||
$this->add_identifier_mapping('KEYWORD',
|
||||
$GLOBALS['luminous_c_keywords']);
|
||||
$this->add_identifier_mapping('TYPE',
|
||||
$GLOBALS['luminous_c_types']);
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
||||
// http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
|
||||
// D [0-9]
|
||||
// L [a-zA-Z_]
|
||||
// H [a-fA-F0-9]
|
||||
// E [Ee][+-]?{D}+
|
||||
// FS (f|F|l|L)
|
||||
// IS (u|U|l|L)*//
|
||||
// {L}({L}|{D})* ident
|
||||
// 0[xX]{H}+{IS}? hex
|
||||
// 0{D}+{IS}? octal
|
||||
// {D}+{IS}? int
|
||||
// L?'(\\.|[^\\'])+' char
|
||||
// {D}+{E}{FS}? real/float
|
||||
// {D}*"."{D}+({E})?{FS}? real/float
|
||||
// {D}+"."{D}*({E})?{FS}? real/float
|
||||
// L?\"(\\.|[^\\"])*\" string, but we should exclude nl
|
||||
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_ML);
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_SL);
|
||||
$this->add_pattern('STRING', "/L?\"(?: [^\\\\\"\n]+ | \\\\.)*(?:$|\")/xms");
|
||||
// if memory serves, a char looks like this:
|
||||
$this->add_pattern('CHARACTER',
|
||||
"/L? ' (?: \\\\(?: x[A-F0-9]{1,2}| . ) | . ) (?: '|$)/ixm");
|
||||
|
||||
$this->add_pattern('OPERATOR', '@[!%^&*\-/+=~:?.|<>]+@');
|
||||
|
||||
$this->add_pattern('NUMERIC', '/0[xX][A-F0-9]+[uUlL]*/i');
|
||||
$this->add_pattern('NUMERIC', '/
|
||||
(?:
|
||||
(?: \d* \.\d+ | \d+\.\d*)
|
||||
([eE][+-]?\d+)?
|
||||
([fFlL]?)
|
||||
)
|
||||
/ix');
|
||||
$this->add_pattern('NUMERIC', '/
|
||||
\d+([uUlL]+ | ([eE][+-]?\d+)?[fFlL]? | ) #empty string on the end
|
||||
/x'); //inc octal
|
||||
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_HEX);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_REAL);
|
||||
$this->add_pattern('PREPROCESSOR', '/^[ \t]*\#/m');
|
||||
$this->add_pattern('IDENT', '/[a-zA-Z_]+\w*/');
|
||||
|
||||
$this->overrides['PREPROCESSOR'] = array($this, 'preprocessor_override');
|
||||
}
|
||||
|
||||
|
||||
function preprocessor_override() {
|
||||
$this->skip_whitespace();
|
||||
// #if 0s nest, according to Kate, which sounds reasonable
|
||||
$pattern = '/^\s*#\s*if\s+0\\b/m';
|
||||
if($this->check($pattern)) {
|
||||
$this->nestable_token('COMMENT', '/^\s*#\s*if(?:n?def)?\\b/m',
|
||||
'/^\s*#\s*endif\\b/m');
|
||||
}
|
||||
else {
|
||||
// a preprocessor statement may have nested comments and strings. We
|
||||
// go the lazy route and just zap the whole thing with a regex and let a
|
||||
// filter figure out any nested highlighting
|
||||
$this->scan("@ \#
|
||||
(?: [^/\n\\\\]+
|
||||
| /\* (?> [^\\*]+ | (?:\*(?!/))+ ) (?: $|\*/) # nested ML comment
|
||||
| //.* # nested SL comment
|
||||
| /
|
||||
| \\\\(?s:.) # escape, and newline
|
||||
)* @x");
|
||||
$this->record($this->match(), 'PREPROCESSOR');
|
||||
}
|
||||
}
|
||||
|
||||
static function preprocessor_filter_cb($matches) {
|
||||
|
||||
if (!isset($matches[0]) || !isset($matches[0][0]))
|
||||
return ''; // shouldn't ever happen
|
||||
if ($matches[0][0] === '"') return LuminousUtils::tag_block('STRING', $matches[0]);
|
||||
else if ($matches[0][0] === '&')
|
||||
return '<' . LuminousUtils::tag_block('STRING', $matches[1]) . '>';
|
||||
else return LuminousUtils::tag_block('COMMENT', $matches[0]);
|
||||
}
|
||||
|
||||
static function preprocessor_filter($token) {
|
||||
$token = LuminousUtils::escape_token($token);
|
||||
$token[1] = preg_replace_callback("@
|
||||
(?:\" (?> [^\\\\\n\"]+ | \\\\. )* (?: \"|$) | (?: < (.*?) >))
|
||||
| // .*
|
||||
| /\* (?s:.*?) (\*/ | $)
|
||||
@x",
|
||||
array('LuminousCppScanner', 'preprocessor_filter_cb'),
|
||||
$token[1]);
|
||||
return $token;
|
||||
}
|
||||
|
||||
static function guess_language($src, $info) {
|
||||
// Obviously, C tends to look an awful lot like pretty much every other
|
||||
// language. Its only real pseudo-distinct feature is the ugly
|
||||
// preprocessor and "char * ", so let's go with that
|
||||
|
||||
$p = 0.0;
|
||||
if (preg_match('/^\s*+#\s*+(include\s++[<"]|ifdef|endif|define)\\b/m',
|
||||
$src)
|
||||
)
|
||||
$p += 0.3;
|
||||
if (preg_match('/\\bchar\s*\\*\s*\w+/', $src)) $p += 0.05;
|
||||
if (preg_match('/\\bmalloc\s*\\(/', $src)) $p += 0.02;
|
||||
// TODO we could guess at some C++ stuff too
|
||||
return $p;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
<?php
|
||||
class LuminousCSharpScanner extends LuminousSimpleScanner {
|
||||
|
||||
public function init() {
|
||||
|
||||
|
||||
$this->add_pattern('PREPROCESSOR', "/\\#(?: [^\\\\\n]+ | \\\\. )*/sx");
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_SL);
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_ML);
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$DOUBLE_STR);
|
||||
$this->add_pattern('CHARACTER', LuminousTokenPresets::$SINGLE_STR);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_HEX);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_REAL);
|
||||
$this->add_pattern('IDENT', '/[a-z_]\w+/i');
|
||||
$this->add_pattern('OPERATOR', '/[¬!%^&*\-=+~|?\\/><;:.,]+/i');
|
||||
|
||||
|
||||
|
||||
$this->add_identifier_mapping('KEYWORD', array('abstract', 'as', 'base',
|
||||
'break', 'case', 'catch', 'checked', 'class', 'continue', 'default',
|
||||
'delegate', 'do', 'event', 'explicit', 'extern', 'else', 'finally',
|
||||
'false', 'fixed', 'for', 'foreach', 'goto', 'if', 'implicit', 'in',
|
||||
'interface', 'internal', 'is', 'lock', 'new', 'null', 'namespace',
|
||||
'operator', 'out', 'override', 'params', 'private',
|
||||
'protected', 'public', 'readonly', 'ref', 'return', 'struct', 'switch',
|
||||
'sealed', 'sizeof', 'stackalloc', 'static', 'this', 'throw', 'true',
|
||||
'try', 'typeof', 'unchecked', 'unsafe', 'using', 'var', 'virtual',
|
||||
'volatile', 'while', 'yield'));
|
||||
|
||||
require(dirname(__FILE__) . '/include/csharp_list.php');
|
||||
|
||||
$this->add_identifier_mapping('TYPE', array_merge(array(
|
||||
// primatives
|
||||
'bool', 'byte', 'char',
|
||||
'const', 'double', 'decimal', 'enum', 'float', 'int', 'long',
|
||||
'object',
|
||||
'sbyte', 'short', 'string', 'uint', 'ulong', 'ushort',
|
||||
'void'
|
||||
),
|
||||
$luminous_csharp_type_list)
|
||||
);
|
||||
}
|
||||
|
||||
static function guess_language($src, $info) {
|
||||
$p = 0.0;
|
||||
if (preg_match('/^\s*#region\\b/m', $src)) $p += 0.10;
|
||||
if (preg_match('/^\s*using\s+System;/m', $src)) $p += 0.10;
|
||||
if (preg_match('/^\s*using\s+System\\..*;/m', $src)) $p += 0.10;
|
||||
if (preg_match('/partial\s+class\s+\w+/', $src)) $p += 0.05;
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* CSS scanner.
|
||||
* TODO: it would be nice if we could extend this somehow to handle
|
||||
* CSS dialects which allow rule nesting.
|
||||
*/
|
||||
class LuminousCSSScanner extends LuminousEmbeddedWebScript {
|
||||
|
||||
|
||||
private $expecting;
|
||||
|
||||
function __construct($src=null) {
|
||||
parent::__construct($src);
|
||||
|
||||
$this->rule_tag_map = array(
|
||||
'TAG' => 'KEYWORD',
|
||||
'KEY' => 'TYPE',
|
||||
'SELECTOR' => 'VARIABLE',
|
||||
'ATTR_SELECTOR' => 'OPERATOR',
|
||||
'SSTRING' => 'STRING',
|
||||
'DSTRING' => 'STRING',
|
||||
'ROUND_BRACKET_SELECTOR' => 'OPERATOR',
|
||||
);
|
||||
|
||||
$this->dirty_exit_recovery = array(
|
||||
'COMMENT' => '%.*?(?:\*/|$)%s',
|
||||
'SSTRING' => "/(?:[^\\\\']+|\\\\.)*(?:'|$)/",
|
||||
'DSTRING' => '/(?:[^\\\\"]+|\\\\.)*(?:"|$)/',
|
||||
'ATTR_SELECTOR' => '/(?: [^\\]\\\\]+ | \\\\.)* (?:\]|$)/xs',
|
||||
'ROUND_BRACKET_SELECTOR' => '/(?: [^\\)\\\\]+ | \\\\.)* (?:\)|$)/xs',
|
||||
);
|
||||
$this->state_ [] = 'global';
|
||||
}
|
||||
|
||||
|
||||
function init() {
|
||||
$this->expecting = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function main() {
|
||||
|
||||
$comment_regex = '% /\* .*? \*/ %sx';
|
||||
|
||||
|
||||
$this->start();
|
||||
|
||||
|
||||
while (!$this->eos()) {
|
||||
|
||||
if (!$this->clean_exit) {
|
||||
try {
|
||||
$tok = $this->resume();
|
||||
if ($this->server_break($tok)) break;
|
||||
$this->record($this->match(), $tok);
|
||||
} catch(Exception $e) {
|
||||
if (LUMINOUS_DEBUG) throw $e;
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
$this->skip_whitespace();
|
||||
$pos = $this->pos();
|
||||
$tok = null;
|
||||
$m = null;
|
||||
$state = $this->state();
|
||||
$in_block = $state === 'block';
|
||||
$in_media = $state === 'media';
|
||||
$get = false;
|
||||
$c = $this->peek();
|
||||
|
||||
if ($this->embedded_server && $this->check($this->server_tags)) {
|
||||
$this->interrupt = true;
|
||||
$this->clean_exit = true;
|
||||
break;
|
||||
}
|
||||
elseif ($c === '/' && $this->scan(LuminousTokenPresets::$C_COMMENT_ML))
|
||||
$tok = 'COMMENT';
|
||||
elseif($in_block && $c === '#' &&
|
||||
$this->scan('/#[a-fA-F0-9]{3}(?:[a-fA-F0-9]{3})?/'))
|
||||
$tok = 'NUMERIC';
|
||||
elseif($in_block && (ctype_digit($c) || $c === '-')
|
||||
&& $this->scan('/-?(?>\d+)(\.(?>\d+))?(?:em|px|ex|ch|mm|cm|in|pt|%)?/')
|
||||
!== null) {
|
||||
$tok = 'NUMERIC';
|
||||
}
|
||||
elseif(!$in_block && $this->scan('/(?<=[#\.:])[\w\-]+/') !== null)
|
||||
$tok = 'SELECTOR';
|
||||
// check for valid super-blocks, e.g. media {...} and @keyframes {}
|
||||
elseif(!$in_block && !$in_media && $c === '@'
|
||||
&& $this->scan('/@
|
||||
(-(moz|ms|webkit|o)-)?keyframes\\b
|
||||
|
|
||||
media\\b/x')
|
||||
) {
|
||||
$this->state_[] = 'media';
|
||||
$tok = 'TAG';
|
||||
}
|
||||
elseif(( ctype_alpha($c) || $c === '!' || $c === '@' || $c === '_' || $c === '-' )
|
||||
&& $this->scan('/(!?)[\-\w@]+/')) {
|
||||
if ($in_media) $tok = 'VALUE';
|
||||
elseif (!$in_block || $this->match_group(1) !== '') $tok = 'TAG';
|
||||
elseif($this->expecting === 'key') $tok = 'KEY';
|
||||
elseif($this->expecting === 'value') {
|
||||
$m = $this->match();
|
||||
if ($m === 'url' || $m === 'rgb' || $m === 'rgba') $tok = 'FUNCTION';
|
||||
else $tok = 'VALUE';
|
||||
}
|
||||
}
|
||||
|
||||
// TODO attr selectors should handle embedded strings, I think.
|
||||
elseif(!$in_block && $c === '['
|
||||
&& $this->scan('/\[ (?> [^\\]\\\\]+ | \\\\.)* \]/sx'))
|
||||
$tok = 'ATTR_SELECTOR';
|
||||
|
||||
elseif(!$in_block && $c === '('
|
||||
&& $this->scan('/\( (?> [^\\)\\\\]+ | \\\\.)* \) /sx')) {
|
||||
$tok = 'ROUND_BRACKET_SELECTOR';
|
||||
}
|
||||
elseif($c === '}' || $c === '{') {
|
||||
|
||||
$get = true;
|
||||
if ($c === '}' && ($in_block || $in_media)) {
|
||||
array_pop($this->state_);
|
||||
if ($in_media) {
|
||||
// @media adds a 'media' state, then the '{' begins a new global state.
|
||||
// We've just popped global, now we need to pop media.
|
||||
array_pop($this->state_);
|
||||
}
|
||||
}
|
||||
elseif (!$in_block && $c === '{') {
|
||||
if ($in_media) {
|
||||
$this->state_[] = 'global';
|
||||
}
|
||||
else {
|
||||
$this->state_[] = 'block';
|
||||
$this->expecting = 'key';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
elseif($c === '"' && $this->scan(LuminousTokenPresets::$DOUBLE_STR))
|
||||
$tok = 'DSTRING';
|
||||
elseif($c === "'" && $this->scan(LuminousTokenPresets::$SINGLE_STR))
|
||||
$tok = 'SSTRING';
|
||||
elseif($c === ':' && $in_block) {
|
||||
$this->expecting = 'value';
|
||||
$get = true;
|
||||
$tok = 'OPERATOR';
|
||||
}
|
||||
elseif($c=== ';' && $in_block) {
|
||||
$this->expecting = 'key';
|
||||
$get = true;
|
||||
$tok = 'OPERATOR';
|
||||
}
|
||||
elseif($this->embedded_html && $this->check('%<\s*/\s*style%i')) {
|
||||
$this->interrupt = false;
|
||||
$this->clean_exit = true;
|
||||
|
||||
break;
|
||||
}
|
||||
elseif($this->scan('/[:\\.#>*]+/')) $tok = 'OPERATOR';
|
||||
|
||||
else {
|
||||
$get = true;
|
||||
}
|
||||
|
||||
if ($this->server_break($tok)) break;
|
||||
|
||||
|
||||
$m = $get? $this->get() : $this->match();
|
||||
$this->record($m, $tok);
|
||||
assert($this->pos() > $pos || $this->eos());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
$p = 0;
|
||||
if (preg_match(
|
||||
"/(font-family|font-style|font-weight)\s*+:\s*+[^;\n\r]*+;/", $src))
|
||||
$p += 0.15;
|
||||
if (strpos($src, '!important') !== false) $p += 0.05;
|
||||
// generic rule
|
||||
if (preg_match("/\\b(div|span|table|body)\\b [^\n\r\{]*+ [\r\n]*+ \{/x",
|
||||
$src))
|
||||
$p += 0.10;
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
<?php
|
||||
|
||||
|
||||
/*
|
||||
* Diff is a strange one because we could just highlight the lines and be done
|
||||
* with it, but we are actually going to try to highlight the source code AND
|
||||
* the diff format
|
||||
*
|
||||
* As such, we handle formatting and tagging inside the scanner.
|
||||
*/
|
||||
class LuminousDiffScanner extends LuminousScanner {
|
||||
|
||||
public $patterns = array();
|
||||
public $pretty_mode = false; // pretty mode uses language sub-scanners
|
||||
// to try to highlight the embedded code
|
||||
|
||||
/* TODO: plug this into the language code selector in the old EasyAPI
|
||||
* when we port it across
|
||||
* This function is just a placeholder and will be implemented properly
|
||||
* later.
|
||||
*/
|
||||
function get_child_scanner($filename) {
|
||||
// HACK - pretty mode should be reflected elsewhere than here.
|
||||
if (!$this->pretty_mode) return null;
|
||||
// $luminous_ is a singleton from the main calling API. It may or may not
|
||||
// exist here, but if it does, we're going to use it.
|
||||
global $luminous_;
|
||||
if (!isset($luminous_))
|
||||
return null;
|
||||
|
||||
$spos = strrpos($filename, '.');
|
||||
if ($spos === false) {return null;}
|
||||
$ext = substr($filename, $spos+1);
|
||||
$s = $luminous_->scanners->GetScanner(strtolower($ext));
|
||||
// we actually only want the classname, not an instance.
|
||||
if ($s === null) return null;
|
||||
else return get_class($s);
|
||||
}
|
||||
|
||||
|
||||
function string($string=null) {
|
||||
if ($string !== null) {
|
||||
if (preg_match('/^[><]/m', $string)) {
|
||||
// normal rules
|
||||
$this->patterns['range'] = '/\d+.*/';
|
||||
$this->patterns['codeblock'] = "/(^([<> ]).*(\n)?)+/m";
|
||||
}
|
||||
elseif (preg_match('/^\*{3}/m', $string)) {
|
||||
// context
|
||||
$this->patterns['range'] = "/([\-\*]{3})[ \t]+\d+,\d+[ \t]+\\1.*/";
|
||||
$this->patterns['codeblock'] = "/(^([!+ ]).*(\n)?)+/m";
|
||||
}
|
||||
else {
|
||||
// unified
|
||||
$this->patterns['range'] = "/@@.*/";
|
||||
$this->patterns['codeblock'] = "/(^([+\- ]).*(\n)?)+/m";
|
||||
}
|
||||
}
|
||||
|
||||
return parent::string($string);
|
||||
|
||||
}
|
||||
|
||||
function main() {
|
||||
// we're aiming to handle context, unified and normal diff all at once here
|
||||
// because it doesn't really seem that hard.
|
||||
$child = null;
|
||||
$last_index = -1;
|
||||
while (!$this->eos()) {
|
||||
$index = $this->pos();
|
||||
assert($index > $last_index);
|
||||
$last_index = $index;
|
||||
|
||||
assert($this->bol());
|
||||
|
||||
$tok = null;
|
||||
if ($this->scan('/diff\s.*$/m') !== null) $tok = 'KEYWORD';
|
||||
// normal, context and unified ranges
|
||||
elseif($this->scan($this->patterns['range']) !== null)
|
||||
$tok = 'DIFF_RANGE';
|
||||
elseif($this->scan("/-{3}[ \t]*$/m")) $tok = null;
|
||||
|
||||
elseif($this->scan('/(?:\**|=*|\w.*)$/m') !== null) $tok = 'KEYWORD';
|
||||
// this is a header line which may contain a file path. If it does,
|
||||
// update the child scanner according to its extension.
|
||||
elseif($this->scan("@[+\-\*]{3}(\s+([^\s]*)([ \t]|$))?.*@m") !== null) {
|
||||
$m = $this->match_groups();
|
||||
// unified uses +++, context uses *
|
||||
if ($m[0][0] === '+' || $m[0][0] === '*')
|
||||
$tok = 'DIFF_HEADER_NEW';
|
||||
else $tok = 'DIFF_HEADER_OLD';
|
||||
if (isset($m[2])) {
|
||||
$filename = preg_replace('@.*\\\\/@', '', $m[2]);
|
||||
$child = self::get_child_scanner($filename);
|
||||
}
|
||||
}
|
||||
elseif($this->scan('/\\\\.*/') !== null) $tok = null;
|
||||
elseif($this->scan($this->patterns['codeblock']) !== null) {
|
||||
|
||||
// this is actual source code.
|
||||
// we're going to format this here.
|
||||
// we're going to extract the block, and try to re-assemble it as
|
||||
// verbatim code, then highlight it via a child scanner, then split up
|
||||
// the lines, re-apply the necessary prefixes (e.g. + or -) to them,
|
||||
// and store them as being a DIFF_ token.
|
||||
// we have to do it like this, rather than line by line, otherwise
|
||||
// multiline tokens aren't going to work properly. There's stilla risk
|
||||
// that the diff will be fragmented such the child scanner gets it
|
||||
// wrong but that can't be helped.
|
||||
|
||||
// TODO restructure this so the complicated bits aren't done if there's
|
||||
// no child scanner to pass it down to
|
||||
|
||||
$block = $this->match();
|
||||
if (!strlen($block)) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
$lines = explode("\n", $block);
|
||||
$verbatim = array();
|
||||
$verbatim_ = '';
|
||||
$types = array();
|
||||
$prefixes = array();
|
||||
foreach($lines as $l) {
|
||||
if (!strlen($l) || $l[0] === ' ')
|
||||
$types[]= 'DIFF_UNCHANGED';
|
||||
elseif ($l[0] === '+' || $l[0] === '>')
|
||||
$types[] = 'DIFF_NEW';
|
||||
elseif ($l[0] === '!' || $l[0] === '<' || $l[0] === '-')
|
||||
$types[] = 'DIFF_OLD';
|
||||
else assert(0);
|
||||
$prefixes[] = (isset($l[0]))? $l[0] : '';
|
||||
$verbatim_[] = substr($l, 1);
|
||||
}
|
||||
$verbatim = implode("\n", $verbatim_);
|
||||
$escaped = false;
|
||||
$tagged;
|
||||
if ($child !== null) {
|
||||
$c = new $child;
|
||||
$c->init();
|
||||
$c->string($verbatim);
|
||||
$c->main();
|
||||
$tagged = $c->tagged();
|
||||
$escaped = true;
|
||||
} else {
|
||||
$tagged = $verbatim;
|
||||
}
|
||||
$exp = explode("\n", $tagged);
|
||||
assert(count($exp) === count($prefixes));
|
||||
foreach($exp as $i=>$v) {
|
||||
$t = $types[$i];
|
||||
// if the sub-scanner escaped the line, we also need to escape the
|
||||
// prefix for consistency
|
||||
$prefix = $prefixes[$i];
|
||||
if ($escaped) $prefix = LuminousUtils::escape_string($prefix);
|
||||
$text = $prefix . $v;
|
||||
$this->record(
|
||||
$text,
|
||||
$t,
|
||||
$escaped);
|
||||
if ($i < count($exp)-1) $this->record("\n", null);
|
||||
}
|
||||
if ($this->eol()) $this->record($this->get(), null);
|
||||
continue;
|
||||
}
|
||||
else $this->scan('/.*/');
|
||||
|
||||
// previous else clause can capture empty strings
|
||||
if ($this->match() !== '')
|
||||
$this->record($this->match(), $tok);
|
||||
|
||||
assert($this->eol());
|
||||
// consume newline
|
||||
if (!$this->eos()) $this->record($this->get(), null);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static function guess_language($src, $info) {
|
||||
// diff isn't too hard. We check for 'index' and a few other things
|
||||
$p = 0.0;
|
||||
if (preg_match("/^-{3}.*+[\n\r]++\\+{3}/m", $src)) $p = 0.25;
|
||||
if (preg_match('/^@@.*@@/m', $src)) $p += 0.25;
|
||||
if (preg_match('/^(index|diff)\\b/m', $src)) $p += 0.10;
|
||||
|
||||
|
||||
// finally we look for the diff markers at the line starts
|
||||
// we're going to use the remaining 40% of the probability as so:
|
||||
// We'll say a perfect match for diff has
|
||||
// 10%+ of its lines starting with the +/- markers (</> or +/! for
|
||||
// context/original format), and we'll scale real proportion
|
||||
// to fill up the remaining 0.4
|
||||
$c = preg_match_all('/^[<>+\\-!]\s/m', $src, $m);
|
||||
$num_lines = $info['num_lines'];
|
||||
if ($num_lines > 0) {
|
||||
$proportion = $c/$num_lines;
|
||||
$proportion = min(0.1, $proportion);
|
||||
$p += 0.4 * ($proportion * 10);
|
||||
}
|
||||
return $p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class LuminousPrettyDiffScanner extends LuminousDiffScanner {
|
||||
public $pretty_mode = true;
|
||||
}
|
||||
|
|
@ -1,257 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* This is a rename of the JavaScript scanner.
|
||||
* TODO Some of these things are JS specific and should be moved into
|
||||
* the new JS scanner.
|
||||
*/
|
||||
|
||||
class LuminousECMAScriptScanner extends LuminousEmbeddedWebScript {
|
||||
|
||||
public $script_tags = '</script>';
|
||||
// regular expressions in JavaScript are delimited by '/', BUT, the slash
|
||||
// character may appear unescaped within character classes
|
||||
// we can handle this fairly easily with a single regex because the classes
|
||||
// do not nest
|
||||
// TODO:
|
||||
// I do not know if this is specific to Javascript or ECMAScript derivatives
|
||||
// as a whole, I also don't know if multi-line regexen are legal (i.e. when
|
||||
// the definition spans multiple lines)
|
||||
protected $regex_regex = "%
|
||||
/
|
||||
(?:
|
||||
[^\\[\\\\/]+ # not slash, backslash, or [
|
||||
| \\\\. # escape char
|
||||
|
|
||||
(?: # char class [..]
|
||||
\\[
|
||||
(?:
|
||||
[^\\]\\\\]+ # not slash or ]
|
||||
| \\\\. # escape
|
||||
)*
|
||||
(?: \\] | \$)
|
||||
) # close char class
|
||||
)*
|
||||
(?: /[iogmx]* | \$) #delimiter or eof
|
||||
%sx";
|
||||
|
||||
|
||||
// logs a persistent token stream so that we can lookbehind to figure out
|
||||
// operators vs regexes.
|
||||
private $tokens_ = array();
|
||||
|
||||
private $child_state = null;
|
||||
|
||||
function __construct($src=null) {
|
||||
|
||||
$this->rule_tag_map = array(
|
||||
'COMMENT_SL' => 'COMMENT',
|
||||
'SSTRING' => 'STRING',
|
||||
'DSTRING' => 'STRING',
|
||||
'OPENER' => null,
|
||||
'CLOSER' => null,
|
||||
);
|
||||
$this->dirty_exit_recovery = array(
|
||||
'COMMENT_SL' => '/.*/',
|
||||
'COMMENT' => '%.*?(\*/|$)%s',
|
||||
'SSTRING' => "/(?:[^\\\\']+|\\\\.)*('|$)/",
|
||||
'DSTRING' => '/(?:[^\\\\"]+|\\\\.)*("|$)/',
|
||||
// FIXME: Anyone using a server-side interruption to build a regex is
|
||||
// frankly insane, but we are wrong in the case that they were in a
|
||||
// character class when the server language interrupted, and we may
|
||||
// exit the regex prematurely with this
|
||||
'REGEX' => '%(?:[^\\\\/]+|\\\\.)*(?:/[iogmx]*|$)%',
|
||||
);
|
||||
|
||||
parent::__construct($src);
|
||||
$this->add_identifier_mapping('KEYWORD', array('break', 'case', 'catch',
|
||||
'comment', 'continue', 'do', 'default', 'delete', 'else', 'export',
|
||||
'for', 'function', 'if', 'import', 'in', 'instanceof', 'label', 'new',
|
||||
'null', 'return', 'switch', 'throw', 'try', 'typeof', 'var', 'void',
|
||||
'while', 'with',
|
||||
'true', 'false', 'this'
|
||||
));
|
||||
$this->add_identifier_mapping('FUNCTION', array('$', 'alert', 'confirm',
|
||||
'clearTimeout', 'clearInterval',
|
||||
'encodeURI', 'encodeURIComponent', 'eval', 'isFinite', 'isNaN',
|
||||
'parseInt', 'parseFloat', 'prompt',
|
||||
'setTimeout', 'setInterval',
|
||||
'decodeURI', 'decodeURIComponent', 'jQuery'));
|
||||
|
||||
$this->add_identifier_mapping('TYPE', array('Array', 'Boolean', 'Date',
|
||||
'Error', 'EvalError', 'Infinity', 'Image', 'Math', 'NaN', 'Number',
|
||||
'Object', 'Option', 'RangeError', 'ReferenceError', 'RegExp', 'String',
|
||||
'SyntaxError', 'TypeError', 'URIError',
|
||||
|
||||
'document',
|
||||
'undefined', 'window'));
|
||||
}
|
||||
|
||||
function is_operand() {
|
||||
for ($i = count($this->tokens) -1 ; $i>= 0; $i--) {
|
||||
$tok = $this->tokens[$i][0];
|
||||
if ($tok === null || $tok === 'COMMENT' || $tok === 'COMMENT_SL') continue;
|
||||
return ($tok === 'OPERATOR' || $tok === 'OPENER');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
||||
if ($this->embedded_server)
|
||||
$this->add_pattern('STOP_SERVER', $this->server_tags);
|
||||
if ($this->embedded_html)
|
||||
$this->add_pattern('STOP_SCRIPT', '%</script>%');
|
||||
|
||||
$op_pattern = '[=!+*%\-&^|~:?\;,.>';
|
||||
if (!($this->embedded_server || $this->embedded_html))
|
||||
$op_pattern .= '<]+';
|
||||
else {
|
||||
// build an alternation with a < followed by a lookahead
|
||||
$op_pattern .= ']|<(?![';
|
||||
// XXX this covers <? and <% but not very well
|
||||
if ($this->embedded_server) $op_pattern .= '?%';
|
||||
if ($this->embedded_html) $op_pattern .= '/';
|
||||
$op_pattern .= '])'; // closes lookahead
|
||||
$op_pattern = "(?:$op_pattern)+";
|
||||
}
|
||||
$op_pattern = "@$op_pattern@";
|
||||
|
||||
$this->add_pattern('IDENT', '/[a-zA-Z_$][_$\w]*/');
|
||||
// NOTE: slash is a special case, and </ may be a script close
|
||||
$this->add_pattern('OPERATOR', $op_pattern);
|
||||
// we care about openers for figuring out where regular expressions are
|
||||
$this->add_pattern('OPENER', '/[\[\{\(]+/');
|
||||
$this->add_pattern('CLOSER', '/[\]\}\)]+/');
|
||||
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_HEX);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_REAL);
|
||||
$this->add_pattern('SSTRING', LuminousTokenPresets::$SINGLE_STR_SL);
|
||||
$this->add_pattern('DSTRING', LuminousTokenPresets::$DOUBLE_STR_SL);
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_ML);
|
||||
$this->add_pattern('COMMENT_SL', LuminousTokenPresets::$C_COMMENT_SL);
|
||||
// special case
|
||||
$this->add_pattern('SLASH', '%/%');
|
||||
|
||||
$stop_patterns = array();
|
||||
|
||||
|
||||
$xml_scanner = new LuminousHTMLScanner($this->string());
|
||||
$xml_scanner->xml_literal = true;
|
||||
$xml_scanner->scripts = false;
|
||||
$xml_scanner->embedded_server = $this->embedded_server;
|
||||
if ($this->embedded_server)
|
||||
$xml_scanner->server_tags = $this->server_tags;
|
||||
$xml_scanner->init();
|
||||
$xml_scanner->pos($this->pos());
|
||||
$this->add_child_scanner('xml', $xml_scanner);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// c+p from HTML scanner
|
||||
function scan_child($lang) {
|
||||
assert (isset($this->child_scanners[$lang]));
|
||||
$scanner = $this->child_scanners[$lang];
|
||||
$scanner->pos($this->pos());
|
||||
$substr = $scanner->main();
|
||||
$this->record($scanner->tagged(), 'XML', true);
|
||||
$this->pos($scanner->pos());
|
||||
if ($scanner->interrupt) {
|
||||
$this->child_state = array($lang, $this->pos());
|
||||
} else {
|
||||
$this->child_state = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function main() {
|
||||
$this->start();
|
||||
$this->interrupt = false;
|
||||
while (!$this->eos()) {
|
||||
$index = $this->pos();
|
||||
$tok = null;
|
||||
$m = null;
|
||||
$escaped = false;
|
||||
|
||||
if (!$this->clean_exit) {
|
||||
try {
|
||||
$tok = $this->resume();
|
||||
} catch(Exception $e) {
|
||||
if (LUMINOUS_DEBUG) throw $e;
|
||||
else {
|
||||
$this->clean_exit = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($this->child_state !== null && $this->child_state[1] < $this->pos()) {
|
||||
$this->scan_child($this->child_state[0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
elseif (($rule = $this->next_match()) !== null) {
|
||||
$tok = $rule[0];
|
||||
if ($rule[1] > $index) {
|
||||
$this->record(substr($this->string(), $index, $rule[1] - $index), null);
|
||||
}
|
||||
} else {
|
||||
$this->record(substr($this->string(), $index), null);
|
||||
$this->clean_exit = true;
|
||||
$this->interrupt = false;
|
||||
$this->terminate();
|
||||
break;
|
||||
}
|
||||
|
||||
if ($tok === 'SLASH') {
|
||||
if ($this->is_operand()) {
|
||||
$tok = 'REGEX';
|
||||
$this->unscan();
|
||||
assert($this->peek() === '/');
|
||||
$m = $this->scan($this->regex_regex);
|
||||
if ($m === null) {
|
||||
assert(0);
|
||||
$m = $this->rest();
|
||||
$this->terminate();
|
||||
}
|
||||
|
||||
} else {
|
||||
$tok = 'OPERATOR';
|
||||
}
|
||||
}
|
||||
elseif ($tok === 'OPERATOR' && $this->match() === '<') {
|
||||
if ($this->is_operand()) {
|
||||
$this->unscan();
|
||||
$this->scan_child('xml');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
elseif ($tok === 'STOP_SERVER') {
|
||||
$this->interrupt = true;
|
||||
$this->unscan();
|
||||
break;
|
||||
}
|
||||
elseif ($tok === 'STOP_SCRIPT') {
|
||||
$this->unscan();
|
||||
break;
|
||||
}
|
||||
if ($m === null)
|
||||
$m = $this->match();
|
||||
|
||||
if ($this->server_break($tok))
|
||||
break;
|
||||
|
||||
if ($tok === 'COMMENT_SL' && $this->script_break($tok)
|
||||
)
|
||||
break;
|
||||
assert($this->pos() > $index);
|
||||
|
||||
$tag = $tok;
|
||||
|
||||
$this->record($m, $tag, $escaped);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,163 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Erlang.
|
||||
*
|
||||
* Various comments refer to section numbers in the official spec, which can
|
||||
* be found at http://www.erlang.org/download/erl_spec47.ps.gz
|
||||
*/
|
||||
class LuminousErlangScanner extends LuminousSimpleScanner {
|
||||
|
||||
// applies interpolation highlighting, can't find a proper
|
||||
// reference for this though
|
||||
static function str_filter($token) {
|
||||
if (strpos($token[1], '~') == false) return $token;
|
||||
$token = LuminousUtils::escape_token($token);
|
||||
$token[1] = preg_replace('/~(?:\d+|.)/',
|
||||
'<INTERPOLATION>$0</INTERPOLATION>', $token[1]);
|
||||
return $token;
|
||||
}
|
||||
|
||||
// helper function: generates a regex which matches only numeric strings
|
||||
// in the given base
|
||||
static function build_based_int_regex($base) {
|
||||
|
||||
assert(2 <= $base && $base <= 16);
|
||||
$regex = '/(?i:[0-';
|
||||
if ($base <= 10)
|
||||
$regex .= (string)$base-1;
|
||||
else
|
||||
$regex .= '9a-' . strtolower(dechex($base-1));
|
||||
$regex .= '])+/';
|
||||
return $regex;
|
||||
}
|
||||
|
||||
// 3.11 integers are pretty strange, you are allowed to specify base
|
||||
// 2 ><= b <= 16 arbitrarily.
|
||||
function based_int($matches) {
|
||||
$base = $matches[1];
|
||||
$match = $matches[0];
|
||||
$this->pos_shift(strlen($matches[0]));
|
||||
$number = null;
|
||||
if ($base >= 2 && $base <= 16)
|
||||
$number = $this->scan($this->build_based_int_regex((int)$base));
|
||||
if ($number !== null) {
|
||||
$match .= $number;
|
||||
}
|
||||
$this->record($match, 'NUMERIC');
|
||||
// now we're going to greedily consume any trailing numbers
|
||||
// This handles the case e.g. 2#001122,
|
||||
// we don't want the '22' to get caught as a separate literal, we want to
|
||||
// make sure it's NOT highlighted as a literal
|
||||
// so we consume it here.
|
||||
if ($this->scan('/\d+/') !== null) {
|
||||
$this->record($this->match(), null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static function oo_stream_filter($tokens) {
|
||||
$c = count($tokens)-1;
|
||||
for($i=0; $i<$c; $i++) {
|
||||
if ($tokens[$i][1] === ':') {
|
||||
if ($i > 0) {
|
||||
$behind = &$tokens[$i-1][0];
|
||||
if ($behind === 'IDENT') $behind = 'OBJ';
|
||||
}
|
||||
if ($i < $c-1) {
|
||||
$ahead = &$tokens[$i+1][0];
|
||||
if ($ahead === 'IDENT') $ahead = 'OO';
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
||||
$this->remove_stream_filter('oo-syntax');
|
||||
$this->remove_filter('comment-to-doc');
|
||||
$this->add_stream_filter('oo-syntax', array($this, 'oo_stream_filter'));
|
||||
$this->add_filter('interpolation', 'STRING', array($this, 'str_filter'));
|
||||
|
||||
|
||||
// 3.6 - technically should include the newline, but doesn't really matter
|
||||
$this->add_pattern('COMMENT', '/%.*/');
|
||||
// stuff like -module, -author
|
||||
$this->add_pattern('KEYWORD', '/^-(?:[a-z_]\w*)\\b/m');
|
||||
|
||||
// 3.11 integer with radix
|
||||
$this->add_pattern('BASED_INT', '/[+\\-]?(\d+)#/');
|
||||
$this->overrides['BASED_INT'] = array($this, 'based_int');
|
||||
// float
|
||||
$this->add_pattern('NUMERIC', '/[+\\-]?\d+\.\d+([eE][+\\-]?\d+)?/');
|
||||
// int
|
||||
$this->add_pattern('NUMERIC', '/[+\\-]?\d+/');
|
||||
|
||||
// 3.7 defines some 'separators', included are . : | || ; , ? -> and #
|
||||
// we'll capture these separately to operators
|
||||
// and map it to a keyword, for lack of anything better
|
||||
$this->add_pattern('SEPARATOR', '/\\|\\||->|[\\.:\\|;,?#]/');
|
||||
$this->rule_tag_map['SEPARATOR'] = 'KEYWORD';
|
||||
|
||||
// 3.9
|
||||
$this->add_pattern('OPERATOR', '%==|/=|=:=|=<|>=|\\+\\+|--|<-|[+\\-*=!<>/]%');
|
||||
// 3.9 named ops
|
||||
$this->add_identifier_mapping('OPERATOR', array('div', 'rem', 'or', 'xor',
|
||||
'bor', 'bxor', 'bsl', 'bsr', 'and', 'band', 'not', 'bnot'));
|
||||
|
||||
// char literals occur after a '$'
|
||||
$this->add_pattern('CHARACTER', '/\\$(?:(?:\\\\(?:\\^\w+|\d+|.))|.)/');
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$DOUBLE_STR);
|
||||
|
||||
// this looks like a string, but is in fact an 'atom'
|
||||
// we'll call it a value,
|
||||
$this->add_pattern('VALUE', LuminousTokenPresets::$SINGLE_STR);
|
||||
$this->add_pattern('IDENT', '/[a-z][@\w]*/');
|
||||
$this->add_pattern('VARIABLE', '/[A-Z][@\w]*/');
|
||||
|
||||
|
||||
// 3.8
|
||||
$this->add_identifier_mapping('KEYWORD', array('after', 'begin', 'case',
|
||||
'catch', 'cond', 'end', 'fun', 'if', 'let', 'of', 'query', 'receive',
|
||||
'when',
|
||||
// reserved, but undefined:
|
||||
'all_true', 'some_true'
|
||||
));
|
||||
$this->add_identifier_mapping('VALUE', array('true', 'false'));
|
||||
|
||||
// from the BIF section
|
||||
$this->add_identifier_mapping('FUNCTION', array(
|
||||
'atom', 'binary', 'constant', 'float', 'integer', 'function', 'list',
|
||||
'number', 'pid', 'port', 'reference', 'tuple', 'atom_to_list', 'list_to_atom',
|
||||
'abs', 'float', 'float_to_list', 'integer_to_list', 'list_to_float',
|
||||
'list_to_integer', 'round', 'trunc', 'binary_to_list', 'binary_to_term',
|
||||
'concat_binary', 'list_to_binary', 'size', 'split_binary', 'term_to_binary',
|
||||
'element', 'list_to_tuple', 'seteleemnt', 'size', 'tuple_to_list', 'hd',
|
||||
'length', 't1', 'check_process-code', 'delete_module', 'load_module',
|
||||
'preloaded', 'purge_module', 'module_loaded', 'apply', 'exit', 'group_leader',
|
||||
'link', 'list_to_pid', 'pid_to_list', 'process_flag', 'process_info',
|
||||
'processes', 'self', 'spawn', 'spawn_link', 'unlink', 'erase', 'get',
|
||||
'get_keys', 'put', 'disconnect_node', 'get_cookie', 'halt', 'is_alive',
|
||||
'monitor_node', 'node', 'nodes', 'processes', 'set_cookie', 'set_node',
|
||||
'statistics', 'register', 'registered', 'unregister', 'whereis', 'open_port',
|
||||
'port_close', 'port_info', 'ports', 'date', 'hash', 'make_ref', 'now', 'throw',
|
||||
'time', 'acos', 'asin', 'atan', 'atan2', 'cos', 'cosh', 'exp', 'log', 'log10',
|
||||
'pi', 'pow', 'sin', 'sinh', 'tan', 'tanh'));
|
||||
}
|
||||
|
||||
|
||||
static function guess_language($src, $info) {
|
||||
$p = 0.0;
|
||||
foreach(array('module', 'author', 'export', 'include') as $s) {
|
||||
if (strpos($src, '-' . $s) !== false) $p += 0.02;
|
||||
}
|
||||
if (strpos($src, ' ++ ') !== false) $p += 0.01;
|
||||
if (preg_match('/[a-zA-Z_]\w*#[a-zA-Z_]+/', $src)) $p += 0.05;
|
||||
|
||||
// doc comment
|
||||
if (preg_match('/^%%/m', $src)) $p += 0.05;
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Go.
|
||||
*
|
||||
* http://golang.org/doc/go_spec.html
|
||||
*
|
||||
* TODO: the different string formats have different escape codes, need
|
||||
* to override the generic filter to handle this
|
||||
* also, if there's a standard library API list, that would be useful.
|
||||
*
|
||||
*/
|
||||
|
||||
class LuminousGoScanner extends LuminousSimpleScanner {
|
||||
|
||||
function type_override($matches) {
|
||||
$this->record($matches[1], 'IDENT');
|
||||
$this->record($matches[2], null);
|
||||
$this->record($matches[3], 'USER_FUNCTION');
|
||||
$this->pos_shift(strlen($matches[0]));
|
||||
$this->user_defs[$matches[3]] = ($matches[1] === 'type')? 'TYPE'
|
||||
: 'FUNCTION';
|
||||
}
|
||||
|
||||
function init() {
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_ML);
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_SL);
|
||||
|
||||
$ident = '[\p{L}_][\p{L}\p{N}_]*';
|
||||
// this should be unicode for letter (\p{L}) and number (\p{N})
|
||||
$this->add_pattern('type', "/\\b(type|func)(\s+)($ident)/u");
|
||||
$this->overrides['type'] = array($this, 'type_override');
|
||||
|
||||
$this->add_pattern('IDENT', "/$ident/u");
|
||||
$this->add_pattern('OPERATOR', '/[+\\-\\*\\/%&\\|^<>&=!:\\.,;]+/');
|
||||
|
||||
$exp = '[eE][+-]?\d+';
|
||||
// note the trailing i - which denotes imaginary literals
|
||||
$this->add_pattern('NUMERIC',
|
||||
"/(?:\d+\.\d*(?:$exp)?|\d+$exp|\.\d+(?:$exp)?)i?/");
|
||||
$this->add_pattern('NUMERIC', '/(?:0(?:\d+|x[a-fA-F0-9]+)|\d+)i?/');
|
||||
|
||||
$this->add_pattern('CHARACTER',
|
||||
"/'(?:\\\\(?:\d+|[uUxX][a-fA-F0-9]+|.)|.)'/u");
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$DOUBLE_STR);
|
||||
$this->add_pattern('STRING', '/`(?:[^`\\\\]+|\\\\.)*(?:`|$)/s');
|
||||
|
||||
$this->add_identifier_mapping('KEYWORD', array('break', 'case', 'chan',
|
||||
'const', 'continue', 'default', 'defer', 'else', 'fallthrough', 'for',
|
||||
'func', 'go', 'goto', 'if', 'import', 'interface', 'map', 'package',
|
||||
'range', 'return', 'select', 'struct', 'switch', 'type', 'var'));
|
||||
|
||||
$this->add_identifier_mapping('TYPE', array('any', 'bool', 'byte',
|
||||
'complex', 'complex64', 'complex128', 'int', 'int8', 'int16', 'int32',
|
||||
'int64', 'float', 'float32', 'float64', 'string', 'struct',
|
||||
'uint', 'uint8', 'uint16', 'uint32', 'uint64', 'uintptr'));
|
||||
$this->add_identifier_mapping('VALUE', array('false', 'iota', 'true'));
|
||||
|
||||
// from the old luminous language file, don't know how sensible these are
|
||||
$this->add_identifier_mapping('FUNCTION', array('append', 'cap', 'copy',
|
||||
'cmplx', 'imag', 'len', 'make', 'new', 'panic', 'print', 'println',
|
||||
'real', 'recover', 'sizeof'));
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
$p = 0.0;
|
||||
if (strpos($src, 'func ') !== false) $p += 0.02;
|
||||
if (preg_match('/func\s*\\(\s*\w+\s*\\*\s*\w+/', $src)) $p += 0.05;
|
||||
if (preg_match('/^package\s+\w+/', $src)) $p += 0.01;
|
||||
if (preg_match('/type\s+\w+\s+struct\s*\\{/', $src)) $p += 0.03;
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Groovy is pretty much a cross between Python and Java.
|
||||
* It inherits all of Java's stuff
|
||||
* http://groovy.codehaus.org/jsr/spec/Chapter03Lexical.html
|
||||
*/
|
||||
require_once(dirname(__FILE__) . '/include/java_func_list.php');
|
||||
class LuminousGroovyScanner extends LuminousSimpleScanner {
|
||||
|
||||
|
||||
|
||||
public $interpolation = false;
|
||||
protected $brace_stack = 0;
|
||||
|
||||
function regex_override($match) {
|
||||
assert($this->peek() === '/');
|
||||
assert($match === array(0=>'/'));
|
||||
$regex = false;
|
||||
|
||||
$i = count($this->tokens);
|
||||
while ($i--) {
|
||||
list($tok, $contents) = $this->tokens[$i];
|
||||
if ($tok === 'COMMENT') continue;
|
||||
elseif ($tok === 'OPERATOR') $regex = true;
|
||||
elseif($tok !== null) $regex = false;
|
||||
else {
|
||||
$t = rtrim($contents);
|
||||
if ($t === '') continue;
|
||||
$c = $t[strlen($t)-1];
|
||||
$regex = ($c === '(' || $c === '[' || $c === '{');
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$regex) {
|
||||
$this->record($this->get(), 'OPERATOR');
|
||||
}
|
||||
else {
|
||||
$m = $this->scan('@ / (?: [^\\\\/]+ | \\\\. )* (?: /|$) @sx');
|
||||
assert($m !== null);
|
||||
$this->record($m, 'REGEX');
|
||||
}
|
||||
}
|
||||
|
||||
// string interpolation is complex and it nests, so we do that in here
|
||||
function interp_string($m) {
|
||||
// this should only be called for doubly quoted strings
|
||||
// and triple-double quotes
|
||||
//
|
||||
// interpolation is betwee ${ ... }
|
||||
$patterns = array('interp' => '/(?<!\\$)\\$\\{/');
|
||||
$start = $this->pos();
|
||||
if (preg_match('/^"""/', $m[0])) {
|
||||
$patterns['term'] = '/"""/';
|
||||
$this->pos_shift(3);
|
||||
}
|
||||
else {
|
||||
assert(preg_match('/^"/', $m[0]));
|
||||
$patterns['term'] = '/"/';
|
||||
$this->pos_shift(1);
|
||||
}
|
||||
while (1) {
|
||||
$p = $this->pos();
|
||||
list($name, $index, $matches) = $this->get_next_named($patterns);
|
||||
if ($name === null) {
|
||||
// no matches, terminate
|
||||
$this->record(substr($this->string(), $start), 'STRING');
|
||||
$this->terminate();
|
||||
break;
|
||||
}
|
||||
elseif($name === 'term') {
|
||||
// end of the string
|
||||
$range = $index + strlen($matches[0]);
|
||||
$this->record(substr($this->string(),
|
||||
$start, $range-$start), 'STRING');
|
||||
$this->pos($range);
|
||||
break;
|
||||
} else {
|
||||
// interpolation, handle this with a subscanner
|
||||
$this->record(substr($this->string(), $start, $index-$start), 'STRING');
|
||||
$this->record($matches[0], 'DELIMITER');
|
||||
$subscanner = new LuminousGroovyScanner($this->string());
|
||||
$subscanner->interpolation = true;
|
||||
$subscanner->init();
|
||||
$subscanner->pos($index + strlen($matches[0]));
|
||||
$subscanner->main();
|
||||
|
||||
$tagged = $subscanner->tagged();
|
||||
$this->record($tagged, 'INTERPOLATION', true);
|
||||
$this->pos($subscanner->pos());
|
||||
if ($this->scan('/\\}/')) $this->record($this->match(), 'DELIMITER');
|
||||
$start = $this->pos();
|
||||
}
|
||||
assert($p < $this->pos());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// brace override halts scanning if the stack is empty and we hit a '}',
|
||||
// this is for interpolated code, the top-level scanner doesn't bind to this
|
||||
function brace($m) {
|
||||
if ($m[0] === '{') $this->brace_stack++;
|
||||
elseif($m[0] === '}') {
|
||||
if ($this->brace_stack <= 0)
|
||||
return true;
|
||||
$this->brace_stack--;
|
||||
}
|
||||
else assert(0);
|
||||
$this->record($m[0], null);
|
||||
$this->pos_shift(strlen($m[0]));
|
||||
}
|
||||
|
||||
|
||||
function init() {
|
||||
$this->add_identifier_mapping('KEYWORD',
|
||||
$GLOBALS['luminous_java_keywords']);
|
||||
$this->add_identifier_mapping('TYPE', $GLOBALS['luminous_java_types']);
|
||||
$this->add_identifier_mapping('KEYWORD', array('any', 'as', 'def', 'in',
|
||||
'with', 'do', 'strictfp',
|
||||
'println'));
|
||||
|
||||
|
||||
// C+P from python
|
||||
// so it turns out this template isn't quite as readable as I hoped, but
|
||||
// it's a triple string, e.g:
|
||||
// "{3} (?: [^"\\]+ | ""[^"\\]+ | "[^"\\]+ | \\.)* (?: "{3}|$)
|
||||
$triple_str_template = '%1$s{3} (?> [^%1$s\\\\]+ | %1$s%1$s[^%1$s\\\\]+ | %1$s[^%1$s\\\\]+ | \\\\. )* (?: %1$s{3}|$)';
|
||||
$str_template = '%1$s (?> [^%1$s\\\\]+ | \\\\. )* (?: %1$s|$)';
|
||||
$triple_dstr = sprintf($triple_str_template, '"');
|
||||
$triple_sstr = sprintf($triple_str_template, "'");
|
||||
|
||||
$this->add_pattern('COMMENT', '/^#!.*/');
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_ML);
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_SL);
|
||||
$this->add_pattern('INTERP_STRING', "/$triple_dstr/sx");
|
||||
$this->add_pattern('STRING', "/$triple_sstr/xs");
|
||||
$this->add_pattern('INTERP_STRING', LuminousTokenPresets::$DOUBLE_STR);
|
||||
$this->overrides['INTERP_STRING'] = array($this, 'interp_string');
|
||||
// differs from java:
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$SINGLE_STR);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_HEX);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_REAL);
|
||||
$this->add_pattern('IDENT', '/[a-zA-Z_]\w*/');
|
||||
$this->add_pattern('OPERATOR', '/[~!%^&*\-=+:?|<>]+/');
|
||||
$this->add_pattern('SLASH', '%/%');
|
||||
$this->overrides['SLASH'] = array($this, 'regex_override');
|
||||
if ($this->interpolation) {
|
||||
$this->add_pattern('BRACE', '/[{}]/');
|
||||
$this->overrides['BRACE'] = array($this, 'brace');
|
||||
}
|
||||
}
|
||||
|
||||
static function guess_language($src, $info) {
|
||||
$p = 0.0;
|
||||
if (preg_match('/\\bdef\s+\w+\s*=/', $src)) $p += 0.04;
|
||||
if (preg_match('/println\s+[\'"\w]/', $src)) $p += 0.03;
|
||||
// Flawed check for interpolation, might match after a string
|
||||
// terminator
|
||||
if (preg_match("/\"[^\"\n\r]*\\$\\{/", $src)) $p += 0.05;
|
||||
// regex literal ~/regex/
|
||||
if (preg_match('%~/%', $src)) $p += 0.05;
|
||||
if (preg_match('/^import\s+groovy/m', $src)) $p += 0.2;
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
<?php
|
||||
|
||||
// Haskell scanner.
|
||||
// We do not yet support TemplateHaskell because it looks INSANE.
|
||||
|
||||
/*
|
||||
* TODO: Some contextual awareness would be great, Kate seems to highlight
|
||||
* things differently depending on whether they're in [..] or (...) blocks,
|
||||
* but I don't understand Haskell enough to embark on that right now.
|
||||
*
|
||||
* It would also be nice to distinguish between some different classes of
|
||||
* operator.
|
||||
*/
|
||||
|
||||
require_once(dirname(__FILE__) . '/include/haskell.php');
|
||||
|
||||
class LuminousHaskellScanner extends LuminousSimpleScanner {
|
||||
|
||||
// handles comment nesting of multiline comments.
|
||||
function comment_override() {
|
||||
$this->nestable_token('COMMENT', '/\\{-/', '/-\\}/');
|
||||
}
|
||||
|
||||
function init() {
|
||||
// import from ./include/
|
||||
global $luminous_haskell_functions;
|
||||
global $luminous_haskell_types;
|
||||
global $luminous_haskell_values;
|
||||
global $luminous_haskell_keywords;
|
||||
$this->add_identifier_mapping('KEYWORD', $luminous_haskell_keywords);
|
||||
$this->add_identifier_mapping('TYPE', $luminous_haskell_types);
|
||||
$this->add_identifier_mapping('FUNCTION', $luminous_haskell_functions);
|
||||
$this->add_identifier_mapping('VALUE', $luminous_haskell_values);
|
||||
|
||||
|
||||
// shebang
|
||||
$this->add_pattern('COMMENT', '/^#!.*/');
|
||||
|
||||
// Refer to the sections in
|
||||
// http://www.haskell.org/onlinereport/lexemes.html
|
||||
// for the rules implemented here.
|
||||
|
||||
// 2.4
|
||||
$this->add_pattern('TYPE', '/[A-Z][\'\w]*/');
|
||||
$this->add_pattern('IDENT', '/[_a-z][\'\w]*/');
|
||||
|
||||
// http://www.haskell.org/onlinereport/prelude-index.html
|
||||
$this->add_pattern('FUNCTION', '/
|
||||
(?: !!|\\$!?|&&|\\|{1,2}|\\*{1,2}|\\+{1,2}|-(?!-)|\\.|\\/=?|<=?|==|=<<|>>?=?|\\^\\^? )
|
||||
/x');
|
||||
|
||||
$op_chars = '\\+%^\\/\\*\\?#<>:;=@\\[\\]\\|\\\\~\\-!$@%&\\|=';
|
||||
|
||||
// ` is used to make a function call into an infix operator
|
||||
// CRAZY OR WHAT.
|
||||
$this->add_pattern('OPERATOR', '/`[^`]*`/');
|
||||
// some kind of function, lambda, maybe.
|
||||
$this->add_pattern('FUNCTION', "/\\\\(?![$op_chars])\S+/");
|
||||
|
||||
// Comments are hard!
|
||||
// http://www.mail-archive.com/haskell@haskell.org/msg09019.html
|
||||
// According to this, we can PROBABLY, get away with checking either side
|
||||
// for non-operator chars followed by at least 2 dashes, but I could well
|
||||
// be wrong. It'll do for now.
|
||||
$this->add_pattern('COMMENT', "/(?<![$op_chars])---*(?![$op_chars]).*/");
|
||||
// nested comments are easy!
|
||||
$this->add_pattern('NESTED_COMMENT', '/\\{-/');
|
||||
$this->overrides['NESTED_COMMENT'] = array($this, 'comment_override');
|
||||
$this->rule_tag_map['NESTED_COMMENT'] = 'COMMENT';
|
||||
$this->add_pattern('OPERATOR', "/[$op_chars]+/");
|
||||
|
||||
// FIXME: the char type is way more discriminating than this
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$DOUBLE_STR_SL);
|
||||
$this->add_pattern('CHARACTER', LuminousTokenPresets::$SINGLE_STR_SL);
|
||||
|
||||
// 2.5
|
||||
$this->add_pattern('NUMERIC', '/
|
||||
0[oO]\d+ #octal
|
||||
|
|
||||
0[xX][a-fA-F\d]+ #hex
|
||||
|
|
||||
# decimal and float can be done at once, according to the grammar
|
||||
\d+ (?: (?:\.\d+)? (?: [eE][+-]? \d+))?
|
||||
/x');
|
||||
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
$p = 0.0;
|
||||
// comments
|
||||
if (preg_match('/\\{-.*\\-}/', $src)) $p += 0.05;
|
||||
// 'import qualified' seems pretty unique
|
||||
if (preg_match('/^import\s+qualified/m', $src)) $p += 0.05;
|
||||
// "data SomeType something ="
|
||||
if (preg_match('/data\s+\w+\s+\w+\s*=/', $src)) $p += 0.05;
|
||||
return $p;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,252 +0,0 @@
|
|||
<?php
|
||||
|
||||
class LuminousHTMLScanner extends LuminousEmbeddedWebScript {
|
||||
|
||||
private $child_state = null;
|
||||
|
||||
public $scripts = true;
|
||||
|
||||
// XML literals are part of several languages. Settings this makes the scanner
|
||||
// halt as soon as it pops the its root tag from the stack, so no trailing
|
||||
// code is consumed.
|
||||
public $xml_literal = false;
|
||||
private $tag_stack = array();
|
||||
function __construct($src=null) {
|
||||
|
||||
|
||||
$this->dirty_exit_recovery = array(
|
||||
'DSTRING' => '/[^">]*+("|$|(?=[>]))/',
|
||||
'SSTRING' => "/[^'>]*+('|$|(?=[>]))/",
|
||||
'COMMENT1' => '/(?> [^\\-]+ | -(?!->))*(?:-->|$)/x',
|
||||
'COMMENT2' => '/[^>]*+(?:>|$)/s',
|
||||
'CDATA' => '/(?>[^\\]]+|\\](?!\\]>))*(?:\\]{2}>|$)/xs',
|
||||
'ESC' => '/[^;]*+(?:;|$)/',
|
||||
'TYPE' => '/[^\s]*/',
|
||||
'VALUE' => '/[^\s]*/',
|
||||
'HTMLTAG' => '/[^\s]*/',
|
||||
);
|
||||
|
||||
$this->rule_tag_map = array(
|
||||
'DSTRING' => 'STRING',
|
||||
'SSTRING' => 'STRING',
|
||||
'COMMENT1' => 'COMMENT',
|
||||
'COMMENT2' => 'COMMENT',
|
||||
'CDATA' => 'COMMENT',
|
||||
);
|
||||
|
||||
parent::__construct($src);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function scan_child($lang) {
|
||||
assert (isset($this->child_scanners[$lang]));
|
||||
$scanner = $this->child_scanners[$lang];
|
||||
$scanner->pos($this->pos());
|
||||
$substr = $scanner->main();
|
||||
$this->tokens[] = array(null, $scanner->tagged(), true);
|
||||
$this->pos($scanner->pos());
|
||||
if ($scanner->interrupt) {
|
||||
$this->child_state = array($lang, $this->pos());
|
||||
} else {
|
||||
$this->child_state = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function init() {
|
||||
$this->add_pattern('', '/&/');
|
||||
if ($this->embedded_server) {
|
||||
$this->add_pattern('TERM', $this->server_tags);
|
||||
}
|
||||
$this->add_pattern('', '/</');
|
||||
$this->state_ = 'global';
|
||||
if ($this->scripts) {
|
||||
$js = new LuminousJavaScriptScanner($this->string());
|
||||
$js->embedded_server = $this->embedded_server;
|
||||
$js->embedded_html = true;
|
||||
$js->server_tags = $this->server_tags;
|
||||
$js->init();
|
||||
|
||||
$css = new LuminousCSSScanner($this->string());
|
||||
$css->embedded_server = $this->embedded_server;
|
||||
$css->embedded_html = true;
|
||||
$css->server_tags = $this->server_tags;
|
||||
$css->init();
|
||||
|
||||
$this->add_child_scanner('js', $js);
|
||||
$this->add_child_scanner('css', $css);
|
||||
}
|
||||
}
|
||||
|
||||
private $tagname = '';
|
||||
private $expecting = '';
|
||||
|
||||
function main() {
|
||||
$this->start();
|
||||
$this->interrupt = false;
|
||||
|
||||
while (!$this->eos()) {
|
||||
$index = $this->pos();
|
||||
|
||||
if ($this->embedded_server && $this->check($this->server_tags)) {
|
||||
$this->interrupt = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$this->clean_exit) {
|
||||
try {
|
||||
$tok = $this->resume();
|
||||
if ($this->server_break($tok)) break;
|
||||
$this->record($this->match(), $tok);
|
||||
} catch (Exception $e) {
|
||||
if (LUMINOUS_DEBUG) throw $e;
|
||||
else $this->clean_exit = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->child_state !== null && $this->child_state[1] < $this->pos()) {
|
||||
$this->scan_child($this->child_state[0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$in_tag = $this->state_ === 'tag';
|
||||
if (!$in_tag) {
|
||||
$next = $this->next_match(false);
|
||||
if($next) {
|
||||
$skip = $next[1] - $this->pos();
|
||||
$this->record($this->get($skip), null);
|
||||
if ($next[0] === 'TERM') {
|
||||
$this->interrupt = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->skip_whitespace();
|
||||
if ($this->embedded_server && $this->check($this->server_tags)) {
|
||||
$this->interrupt = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$index = $this->pos();
|
||||
$c = $this->peek();
|
||||
|
||||
$tok = null;
|
||||
$get = false;
|
||||
if (!$in_tag && $c === '&'
|
||||
&& $this->scan('/&[^;\s]+;/')
|
||||
) $tok = 'ESC';
|
||||
elseif(!$in_tag && $c === '<') {
|
||||
if ($this->peek(2) === '<!') {
|
||||
if($this->scan('/(<)(!DOCTYPE)/i')) {
|
||||
// special case: doctype
|
||||
$matches = $this->match_groups();
|
||||
$this->record($matches[1], null);
|
||||
$this->record($matches[2], 'KEYWORD');
|
||||
$this->state_ = 'tag';
|
||||
continue;
|
||||
}
|
||||
// urgh
|
||||
elseif($this->scan('/
|
||||
<!\\[CDATA\\[
|
||||
(?> [^\\]]+ | \\](?!\\]>) )*
|
||||
(?: \\]\\]> | $ )
|
||||
/ixs'
|
||||
))
|
||||
$tok = 'CDATA';
|
||||
elseif($this->scan('/<!--(?> [^\\-]+ | (?:-(?!->))+)* (?:-->|$)/xs'))
|
||||
$tok = 'COMMENT1';
|
||||
elseif($this->scan('/<![^>]*+(?:>|$)/s')) $tok = 'COMMENT2';
|
||||
else assert(0);
|
||||
} else {
|
||||
// check for <script>
|
||||
$this->state_ = 'tag';
|
||||
$this->expecting = 'tagname';
|
||||
$get = true;
|
||||
}
|
||||
}
|
||||
elseif($c === '>') {
|
||||
$get = true;
|
||||
$this->state_ = 'global';
|
||||
if ($this->scripts
|
||||
&& ($this->tagname === 'script' || $this->tagname === 'style'))
|
||||
{
|
||||
$this->record($this->get(), null);
|
||||
$this->scan_child( ($this->tagname === 'script')? 'js' : 'css');
|
||||
continue;
|
||||
}
|
||||
$this->tagname = '';
|
||||
}
|
||||
elseif($in_tag && $this->scan('@/\s*>@')) {
|
||||
$this->state_ = 'global';
|
||||
array_pop($this->tag_stack);
|
||||
}
|
||||
elseif($in_tag &&
|
||||
$c === "'" && $this->scan("/' (?> [^'\\\\>]+ | \\\\.)* (?:'|$|(?=>))/xs")) {
|
||||
$tok = 'SSTRING';
|
||||
$this->expecting = '';
|
||||
}
|
||||
|
||||
elseif($in_tag &&
|
||||
$c === '"' && $this->scan('/" (?> [^"\\\\>]+ | \\\\.)* (?:"|$|(?=>))/xs')) {
|
||||
$tok = 'DSTRING';
|
||||
$this->expecting = '';
|
||||
}
|
||||
elseif($in_tag && $this->scan('@(?:(?<=<)/)?[^\s=<>/]+@') !== null) {
|
||||
if ($this->expecting === 'tagname') {
|
||||
$tok = 'HTMLTAG';
|
||||
$this->expecting = '';
|
||||
$this->tagname = strtolower($this->match());
|
||||
if ($this->tagname[0] === '/') array_pop($this->tag_stack);
|
||||
else $this->tag_stack[] = $this->tagname;
|
||||
}
|
||||
elseif($this->expecting === 'value') {
|
||||
$tok = 'VALUE'; // val as in < a href=*/index.html*
|
||||
$this->expecting = '';
|
||||
}
|
||||
else {
|
||||
$tok = 'TYPE'; // attr, as in <a *HREF*= ....
|
||||
}
|
||||
}
|
||||
elseif($in_tag && $c === '=') {
|
||||
$this->expecting = 'value';
|
||||
$get = true;
|
||||
}
|
||||
else $get = true;
|
||||
if (!$get && $this->server_break($tok)) {break; }
|
||||
|
||||
$this->record($get? $this->get(): $this->match(), $tok);
|
||||
assert ($index < $this->pos() || $this->eos());
|
||||
if ($this->xml_literal && $this->state_ !== 'tag' && empty($this->tag_stack)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
$p = 0;
|
||||
// we have to be a bit careful of XML literals nested in other
|
||||
// langauges here.
|
||||
// We also have to becareful to take precedence over embedded CSS and JS
|
||||
// but leave some room for being embedded in PHP or Rails
|
||||
// so we're not going to go over 0.75
|
||||
$doctype = strpos(ltrim($src), '<!DOCTYPE ');
|
||||
if ($doctype === 0) return 0.75;
|
||||
if (preg_match('/<(a|table|span|div)\s+class=/', $src)) $p += 0.05;
|
||||
if (preg_match('%</(a|table|span|div)>%', $src)) $p += 0.05;
|
||||
if (preg_match('/<(style|script)\\b/', $src)) $p += 0.15;
|
||||
if (preg_match('/<!\\[CDATA\\[/', $src)) $p += 0.15;
|
||||
|
||||
// look for 1 tag at least every 4 lines
|
||||
$lines = preg_match_all('/$/m',
|
||||
preg_replace('/^\s+/m', '', $src), $m);
|
||||
if (preg_match_all('%<[!?/]?[a-zA-Z_:\\-]%', $src, $m)
|
||||
> $lines/4) $p += 0.15;
|
||||
return $p;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<?php
|
||||
|
||||
// the identity scanner. Does what you expect.
|
||||
// Implemented for consistency.
|
||||
|
||||
class LuminousIdentityScanner extends LuminousScanner {
|
||||
public function main() {
|
||||
$this->record($this->string(), null);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,301 +0,0 @@
|
|||
<?php
|
||||
|
||||
|
||||
/**
|
||||
* C and C++ keywords/functions
|
||||
* Some Qt things here as well.
|
||||
*/
|
||||
|
||||
|
||||
global $luminous_c_funcs;
|
||||
global $luminous_c_types;
|
||||
global $luminous_c_keywords;
|
||||
|
||||
$luminous_c_keywords = array(
|
||||
'asm', 'auto', 'break', 'case', 'catch', 'class', 'continue', 'const',
|
||||
'const_cast', 'connect', 'default', 'delete', 'do', 'dynamic_cast',
|
||||
'else', 'explicit', 'extern', 'for', 'for_each', 'friend', 'goto',
|
||||
'if', 'inline', 'mutable', 'namespace', 'new', 'operator', 'private',
|
||||
'protected', 'public', 'register', 'reinterpret_cast', 'return',
|
||||
'static', 'static_cast', 'switch', 'sizeof', 'signed',
|
||||
'template', 'this',
|
||||
'throw', 'try', 'typedef', 'typeid', 'typename', 'using', 'unsigned',
|
||||
'while',
|
||||
'NULL', 'SIGNAL', 'SLOT', 'TRUE', 'FALSE', 'true', 'false');
|
||||
|
||||
$luminous_c_types = array(
|
||||
'bool', 'char', 'clock_t', 'double', 'div_t', 'enum', 'float', 'fpos_t',
|
||||
'int', 'int8', 'int16', 'int32', 'int64', 'int8_t', 'int16_t', 'int32_t',
|
||||
'int64_t', 'long', 'ldiv_t', 'short', 'struct', 'size_t', 'ptrdiff_t',
|
||||
'time_t', 'union', 'uint', 'uint8', 'uint16', 'uint32', 'uint64', 'uint8_t',
|
||||
'uint16_t', 'uint32_t', 'uint64_t', 'void', 'va_list', 'wchar_t',
|
||||
// C++ std stuff
|
||||
'pair', 'list', 'deque', 'queue', 'priority_queue', 'set', 'stack', 'string',
|
||||
'map', 'multiset', 'multimap', 'hash_set', 'hash_multiset', 'hash_map',
|
||||
'hash_multimap', 'bitset', 'vector', 'valarray', 'iterator'
|
||||
);
|
||||
|
||||
// http://en.wikipedia.org/wiki/List_of_C_functions
|
||||
// inb4 deletionists
|
||||
$luminous_c_funcs = array(
|
||||
'assert',
|
||||
'cabs',
|
||||
'cacos',
|
||||
'cacosh',
|
||||
'carg',
|
||||
'casin',
|
||||
'casinh',
|
||||
'catan',
|
||||
'catanh',
|
||||
'ccos',
|
||||
'ccosh',
|
||||
'cexp',
|
||||
'cimag',
|
||||
'cis',
|
||||
'clog',
|
||||
'conj',
|
||||
'cpow',
|
||||
'cproj',
|
||||
'creal',
|
||||
'csin',
|
||||
'csinh',
|
||||
'csqrt',
|
||||
'ctan',
|
||||
'ctanh',
|
||||
'digittoint',
|
||||
'isalnum',
|
||||
'isalpha',
|
||||
'isascii',
|
||||
'isblank',
|
||||
'iscntrl',
|
||||
'isdigit',
|
||||
'isgraph',
|
||||
'islower',
|
||||
'isprint',
|
||||
'ispunct',
|
||||
'isspace',
|
||||
'isupper',
|
||||
'isxdigit',
|
||||
'toascii',
|
||||
'tolower',
|
||||
'toupper',
|
||||
'imaxabs',
|
||||
'imaxdiv',
|
||||
'strtoimax',
|
||||
'strtoumax',
|
||||
'wcstoimax',
|
||||
'wcstoumax',
|
||||
'localeconv',
|
||||
'setlocale',
|
||||
'acos',
|
||||
'asin',
|
||||
'atan',
|
||||
'atan2',
|
||||
'atof',
|
||||
'ceil',
|
||||
'cos',
|
||||
'cosh',
|
||||
'exp',
|
||||
'fabs',
|
||||
'floor',
|
||||
'frexp',
|
||||
'ldexp',
|
||||
'log',
|
||||
'log10',
|
||||
'modf',
|
||||
'pow',
|
||||
'sin',
|
||||
'sinh',
|
||||
'sqrt',
|
||||
'tan',
|
||||
'tanh',
|
||||
'longjmp',
|
||||
'setjmp',
|
||||
'raise',
|
||||
'va_arg',
|
||||
'va_copy',
|
||||
'va_end',
|
||||
'va_start',
|
||||
'offsetof',
|
||||
'clearerr',
|
||||
'fclose',
|
||||
'feof',
|
||||
'ferror',
|
||||
'fflush',
|
||||
'fgetc',
|
||||
'fgetpos',
|
||||
'fgets',
|
||||
'fopen',
|
||||
'freopen',
|
||||
'fdopen',
|
||||
'fprintf',
|
||||
'fputc',
|
||||
'fputs',
|
||||
'fread',
|
||||
'fscanf',
|
||||
'fseek',
|
||||
'fsetpos',
|
||||
'ftell',
|
||||
'fwrite',
|
||||
'getc',
|
||||
'getchar',
|
||||
'gets',
|
||||
'perror',
|
||||
'printf',
|
||||
'fprintf',
|
||||
'sprintf',
|
||||
'snprintf',
|
||||
'putc',
|
||||
'putchar',
|
||||
'fputchar',
|
||||
'puts',
|
||||
'remove',
|
||||
'rename',
|
||||
'rewind',
|
||||
'scanf',
|
||||
'fscanf',
|
||||
'sscanf',
|
||||
'vfscanf',
|
||||
'vscanf',
|
||||
'vsscanf',
|
||||
'setbuf',
|
||||
'setvbuf',
|
||||
'tmpfile',
|
||||
'tmpnam',
|
||||
'ungetc',
|
||||
'vprintf',
|
||||
'vfprintf',
|
||||
'vsprintf',
|
||||
'abort',
|
||||
'abs',
|
||||
'labs',
|
||||
'atexit',
|
||||
'atof',
|
||||
'atoi',
|
||||
'atol',
|
||||
'bsearch',
|
||||
'div',
|
||||
'ldiv',
|
||||
'exit',
|
||||
'free',
|
||||
'itoa',
|
||||
'getenv',
|
||||
'ldiv',
|
||||
'ltoa',
|
||||
'malloc',
|
||||
'alloc',
|
||||
'realloc',
|
||||
'qsort',
|
||||
'rand',
|
||||
'srand',
|
||||
'strtod',
|
||||
'strtol',
|
||||
'strtoul',
|
||||
'system',
|
||||
'memchr',
|
||||
'memcmp',
|
||||
'memcpy',
|
||||
'memmove',
|
||||
'memset',
|
||||
'strcat',
|
||||
'strncat',
|
||||
'strchr',
|
||||
'strcmp',
|
||||
'strncmp',
|
||||
'strcoll',
|
||||
'strcpy',
|
||||
'strncpy',
|
||||
'strcspn',
|
||||
'strerror',
|
||||
'strlen',
|
||||
'strpbrk',
|
||||
'strrchr',
|
||||
'strspn',
|
||||
'strstr',
|
||||
'strtok',
|
||||
'strxfrm',
|
||||
'asctime',
|
||||
'clock',
|
||||
'ctime',
|
||||
'difftime',
|
||||
'gmtime',
|
||||
'localtime',
|
||||
'mktime',
|
||||
'strftime',
|
||||
'time',
|
||||
'btowc',
|
||||
'fgetwc',
|
||||
'fgetws',
|
||||
'fputwc',
|
||||
'fputws',
|
||||
'fwide',
|
||||
'fwprintf',
|
||||
'fwscanf',
|
||||
'getwc',
|
||||
'getwchar',
|
||||
'mbrlen',
|
||||
'mbrtowc',
|
||||
'mbsinit',
|
||||
'mbsrtowcs',
|
||||
'putwc',
|
||||
'putwchar',
|
||||
'swprintf',
|
||||
'swscanf',
|
||||
'ungetwc',
|
||||
'vfwprintf',
|
||||
'vswprintf',
|
||||
'vwprintf',
|
||||
'wcrtomb',
|
||||
'wcscat',
|
||||
'wcschr',
|
||||
'wcscmp',
|
||||
'wcscoll',
|
||||
'wcscpy',
|
||||
'wcscspn',
|
||||
'wcsftime',
|
||||
'wcslen',
|
||||
'wcsncat',
|
||||
'wcsncmp',
|
||||
'wcsncpy',
|
||||
'wcspbrk',
|
||||
'wcsrchr',
|
||||
'wcsrtombs',
|
||||
'wcsspn',
|
||||
'wcsstr',
|
||||
'wcstod',
|
||||
'wcstok',
|
||||
'wcstol',
|
||||
'wcstoul',
|
||||
'wcsxfrm',
|
||||
'wctob',
|
||||
'wmemchr',
|
||||
'wmemcmp',
|
||||
'wmemcpy',
|
||||
'wmemmove',
|
||||
'wmemset',
|
||||
'wprintf',
|
||||
'wscanf',
|
||||
'iswalnum',
|
||||
'iswalpha',
|
||||
'iswcntrl',
|
||||
'iswctype',
|
||||
'iswdigit',
|
||||
'iswgraph',
|
||||
'iswlower',
|
||||
'iswprint',
|
||||
'iswpunct',
|
||||
'iswspace',
|
||||
'iswupper',
|
||||
'iswxdigit',
|
||||
'towctrans',
|
||||
'towlower',
|
||||
'towupper',
|
||||
'wctrans',
|
||||
'wctype',
|
||||
'farmalloc',
|
||||
'getch',
|
||||
'getche',
|
||||
'gotoxy',
|
||||
'getaddrinfo',
|
||||
'getnameinfo',
|
||||
);
|
||||
|
|
@ -1,261 +0,0 @@
|
|||
<?php
|
||||
$luminous_csharp_type_list = array(
|
||||
// system
|
||||
'ArgIterator',
|
||||
'ArraySegment',
|
||||
'Boolean',
|
||||
'Byte',
|
||||
'Char',
|
||||
'ConsoleKeyInfo',
|
||||
'DateTime',
|
||||
'DateTimeOffset',
|
||||
'Decimal',
|
||||
'Double',
|
||||
'Guid',
|
||||
'Int16',
|
||||
'Int32',
|
||||
'Int64',
|
||||
'IntPtr',
|
||||
'ModuleHandle',
|
||||
'Nullable',
|
||||
'RuntimeArgumentHandle',
|
||||
'RuntimeFieldHandle',
|
||||
'RuntimeMethodHandle',
|
||||
'RuntimeTypeHandle',
|
||||
'SByte',
|
||||
'Single',
|
||||
'TimeSpan',
|
||||
'TimeZoneInfo',
|
||||
'TypedReference',
|
||||
'UInt16',
|
||||
'UInt32',
|
||||
'UInt64',
|
||||
'UIntPtr',
|
||||
'Void',
|
||||
|
||||
// also system
|
||||
'AccessViolationException',
|
||||
'ActivationContext',
|
||||
'Activator',
|
||||
'AggregateException',
|
||||
'AppDomain',
|
||||
'AppDomainManager',
|
||||
'AppDomainSetup',
|
||||
'AppDomainUnloadedException',
|
||||
'ApplicationException',
|
||||
'ApplicationId',
|
||||
'ApplicationIdentity',
|
||||
'ArgumentException',
|
||||
'ArgumentNullException',
|
||||
'ArgumentOutOfRangeException',
|
||||
'ArithmeticException',
|
||||
'Array',
|
||||
'ArrayTypeMismatchException',
|
||||
'AssemblyLoadEventArgs',
|
||||
'Attribute',
|
||||
'AttributeUsageAttribute',
|
||||
'BadImageFormatException',
|
||||
'BitConverter',
|
||||
'Buffer',
|
||||
'CannotUnloadAppDomainException',
|
||||
'CharEnumerator',
|
||||
'CLSCompliantAttribute',
|
||||
'Console',
|
||||
'ConsoleCancelEventArgs',
|
||||
'ContextBoundObject',
|
||||
'ContextMarshalException',
|
||||
'ContextStaticAttribute',
|
||||
'Convert',
|
||||
'DataMisalignedException',
|
||||
'DBNull',
|
||||
'Delegate',
|
||||
'DivideByZeroException',
|
||||
'DllNotFoundException',
|
||||
'DuplicateWaitObjectException',
|
||||
'EntryPointNotFoundException',
|
||||
'Enum',
|
||||
'Environment',
|
||||
'EventArgs',
|
||||
'Exception',
|
||||
'ExecutionEngineException',
|
||||
'FieldAccessException',
|
||||
'FileStyleUriParser',
|
||||
'FlagsAttribute',
|
||||
'FormatException',
|
||||
'FtpStyleUriParser',
|
||||
'GC',
|
||||
'GenericUriParser',
|
||||
'GopherStyleUriParser',
|
||||
'HttpStyleUriParser',
|
||||
'IndexOutOfRangeException',
|
||||
'InsufficientExecutionStackException',
|
||||
'InsufficientMemoryException',
|
||||
'InvalidCastException',
|
||||
'InvalidOperationException',
|
||||
'InvalidProgramException',
|
||||
'InvalidTimeZoneException',
|
||||
'Lazy',
|
||||
'LdapStyleUriParser',
|
||||
'LoaderOptimizationAttribute',
|
||||
'LocalDataStoreSlot',
|
||||
'MarshalByRefObject',
|
||||
'Math',
|
||||
'MemberAccessException',
|
||||
'MethodAccessException',
|
||||
'MissingFieldException',
|
||||
'MissingMemberException',
|
||||
'MissingMethodException',
|
||||
'MTAThreadAttribute',
|
||||
'MulticastDelegate',
|
||||
'MulticastNotSupportedException',
|
||||
'NetPipeStyleUriParser',
|
||||
'NetTcpStyleUriParser',
|
||||
'NewsStyleUriParser',
|
||||
'NonSerializedAttribute',
|
||||
'NotFiniteNumberException',
|
||||
'NotImplementedException',
|
||||
'NotSupportedException',
|
||||
'Nullable',
|
||||
'NullReferenceException',
|
||||
'Object',
|
||||
'ObjectDisposedException',
|
||||
'ObsoleteAttribute',
|
||||
'OperatingSystem',
|
||||
'OperationCanceledException',
|
||||
'OutOfMemoryException',
|
||||
'OverflowException',
|
||||
'ParamArrayAttribute',
|
||||
'PlatformNotSupportedException',
|
||||
'Random',
|
||||
'RankException',
|
||||
'ResolveEventArgs',
|
||||
'SerializableAttribute',
|
||||
'StackOverflowException',
|
||||
'STAThreadAttribute',
|
||||
'String',
|
||||
'StringComparer',
|
||||
'SystemException',
|
||||
'ThreadStaticAttribute',
|
||||
'TimeoutException',
|
||||
'TimeZone',
|
||||
'TimeZoneInfo',
|
||||
'TimeZoneInfo',
|
||||
'TimeZoneNotFoundException',
|
||||
'Tuple',
|
||||
'Type',
|
||||
'TypeAccessException',
|
||||
'TypeInitializationException',
|
||||
'TypeLoadException',
|
||||
'TypeUnloadedException',
|
||||
'UnauthorizedAccessException',
|
||||
'UnhandledExceptionEventArgs',
|
||||
'Uri',
|
||||
'UriBuilder',
|
||||
'UriFormatException',
|
||||
'UriParser',
|
||||
'UriTemplate',
|
||||
'UriTemplateEquivalenceComparer',
|
||||
'UriTemplateMatch',
|
||||
'UriTemplateMatchException',
|
||||
'UriTemplateTable',
|
||||
'UriTypeConverter',
|
||||
'ValueType',
|
||||
'Version',
|
||||
'WeakReference',
|
||||
// system.collections
|
||||
'ArrayList',
|
||||
'BitArray',
|
||||
'CaseInsensitiveComparer',
|
||||
'CaseInsensitiveHashCodeProvider',
|
||||
'CollectionBase',
|
||||
'Comparer',
|
||||
'DictionaryBase',
|
||||
'DictionaryEntry',
|
||||
'Hashtable',
|
||||
'ICollection',
|
||||
'IComparer',
|
||||
'IDictionary',
|
||||
'IDictionaryEnumerator',
|
||||
'IEnumerable',
|
||||
'IEnumerator',
|
||||
'IEqualityComparer',
|
||||
'IHashCodeProvider',
|
||||
'IList',
|
||||
'IStructuralComparable',
|
||||
'IStructuralEquatable',
|
||||
'Queue',
|
||||
'ReadOnlyCollectionBase',
|
||||
'SortedList',
|
||||
'Stack',
|
||||
'StructuralComparisons',
|
||||
|
||||
// System.Collections.Generic
|
||||
'Comparer',
|
||||
'Dictionary',
|
||||
'EqualityComparer',
|
||||
'HashSet',
|
||||
'ICollection',
|
||||
'IComparer',
|
||||
'IDictionary',
|
||||
'IEnumerable',
|
||||
'IEnumerator',
|
||||
'IEqualityComparer',
|
||||
'IList',
|
||||
'IReadOnlyCollection',
|
||||
'IReadOnlyDictionary',
|
||||
'IReadOnlyList',
|
||||
'ISet',
|
||||
'KeyedByTypeCollection',
|
||||
'KeyNotFoundException',
|
||||
'KeyValuePair',
|
||||
'LinkedList',
|
||||
'LinkedListNode',
|
||||
'List',
|
||||
'Queue',
|
||||
'SortedDictionary',
|
||||
'SortedList',
|
||||
'SortedSet',
|
||||
'Stack',
|
||||
'SynchronizedCollection',
|
||||
'SynchronizedKeyedCollection',
|
||||
'SynchronizedReadOnlyCollection',
|
||||
|
||||
// system.io
|
||||
'BinaryReader',
|
||||
'BinaryWriter',
|
||||
'BufferedStream',
|
||||
'Directory',
|
||||
'DirectoryInfo',
|
||||
'DirectoryNotFoundException',
|
||||
'DriveInfo',
|
||||
'DriveNotFoundException',
|
||||
'EndOfStreamException',
|
||||
'ErrorEventArgs',
|
||||
'File',
|
||||
'FileFormatException',
|
||||
'FileInfo',
|
||||
'FileLoadException',
|
||||
'FileNotFoundException',
|
||||
'FileStream',
|
||||
'FileSystemEventArgs',
|
||||
'FileSystemInfo',
|
||||
'FileSystemWatcher',
|
||||
'InternalBufferOverflowException',
|
||||
'InvalidDataException',
|
||||
'IODescriptionAttribute',
|
||||
'IOException',
|
||||
'MemoryStream',
|
||||
'Path',
|
||||
'PathTooLongException',
|
||||
'PipeException',
|
||||
'RenamedEventArgs',
|
||||
'Stream',
|
||||
'StreamReader',
|
||||
'StreamWriter',
|
||||
'StringReader',
|
||||
'StringWriter',
|
||||
'TextReader',
|
||||
'TextWriter',
|
||||
'UnmanagedMemoryAccessor',
|
||||
'UnmanagedMemoryStream',
|
||||
);
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
<?php
|
||||
|
||||
|
||||
require_once (dirname(__FILE__) . '/../ecmascript.php');
|
||||
require_once (dirname(__FILE__) . '/../javascript.php');
|
||||
require_once (dirname(__FILE__) . '/../html.php');
|
||||
|
|
@ -1,265 +0,0 @@
|
|||
<?php
|
||||
|
||||
// http://www.haskell.org/onlinereport/prelude-index.html
|
||||
|
||||
|
||||
global $luminous_haskell_functions;
|
||||
global $luminous_haskell_types;
|
||||
global $luminous_haskell_values;
|
||||
global $luminous_haskell_keywords;
|
||||
|
||||
$luminous_haskell_keywords = array('as',
|
||||
'case',
|
||||
'of',
|
||||
'class',
|
||||
'data',
|
||||
'family',
|
||||
'instance',
|
||||
'default',
|
||||
'deriving',
|
||||
'do',
|
||||
'forall',
|
||||
'foreign',
|
||||
'hiding',
|
||||
'if',
|
||||
'then',
|
||||
'else',
|
||||
'import',
|
||||
'infix',
|
||||
'infixl',
|
||||
'infixr',
|
||||
'let',
|
||||
'in',
|
||||
'mdo',
|
||||
'module',
|
||||
'newtype',
|
||||
'proc',
|
||||
'qualified',
|
||||
'rec',
|
||||
'type',
|
||||
'where');
|
||||
|
||||
|
||||
|
||||
$luminous_haskell_types = array(
|
||||
'Bool',
|
||||
'Char',
|
||||
'Double',
|
||||
'Either',
|
||||
'FilePath',
|
||||
'Float',
|
||||
'Int',
|
||||
'Integer',
|
||||
'IO',
|
||||
'IOError',
|
||||
'Maybe',
|
||||
'Ordering',
|
||||
'ReadS',
|
||||
'ShowS',
|
||||
'String',
|
||||
|
||||
'Bounded',
|
||||
'Enum',
|
||||
'Eq',
|
||||
'Floating',
|
||||
'Fractional',
|
||||
'Functor',
|
||||
'Integral',
|
||||
'Monad',
|
||||
'Num',
|
||||
'Ord',
|
||||
'Read',
|
||||
'Real',
|
||||
'RealFloat',
|
||||
'RealFrac',
|
||||
'Show'
|
||||
);
|
||||
|
||||
$luminous_haskell_values = array(
|
||||
'EQ',
|
||||
'False',
|
||||
'GT',
|
||||
'Just',
|
||||
'Left',
|
||||
'LT',
|
||||
'Nothing',
|
||||
'Right',
|
||||
'True',
|
||||
);
|
||||
|
||||
|
||||
|
||||
$luminous_haskell_functions = array(
|
||||
'abs',
|
||||
'acos',
|
||||
'acosh',
|
||||
'all',
|
||||
'and',
|
||||
'any',
|
||||
'appendFile',
|
||||
'applyM',
|
||||
'asTypeOf',
|
||||
'asin',
|
||||
'asinh',
|
||||
'atan',
|
||||
'atan2',
|
||||
'atanh',
|
||||
'break',
|
||||
'catch',
|
||||
'ceiling',
|
||||
'compare',
|
||||
'concat',
|
||||
'concatMap',
|
||||
'const',
|
||||
'cos',
|
||||
'cosh',
|
||||
'curry',
|
||||
'cycle',
|
||||
'decodeFloat',
|
||||
'div',
|
||||
'divMod',
|
||||
'drop',
|
||||
'dropWhile',
|
||||
'elem',
|
||||
'encodeFloat',
|
||||
'enumFrom',
|
||||
'enumFromThen',
|
||||
'enumFromThenTo',
|
||||
'enumFromTo',
|
||||
'error',
|
||||
'even',
|
||||
'exp',
|
||||
'exponent',
|
||||
'fail',
|
||||
'filter',
|
||||
'flip',
|
||||
'floatDigits',
|
||||
'floatRadix',
|
||||
'floatRange',
|
||||
'floor',
|
||||
'fmap',
|
||||
'foldl',
|
||||
'foldl1',
|
||||
'foldr',
|
||||
'foldr1',
|
||||
'fromEnum',
|
||||
'fromInteger',
|
||||
'fromIntegral',
|
||||
'fromRational',
|
||||
'fst',
|
||||
'gcd',
|
||||
'getChar',
|
||||
'getContents',
|
||||
'getLine',
|
||||
'head',
|
||||
'id',
|
||||
'init',
|
||||
'interact',
|
||||
'ioError',
|
||||
'isDenormalized',
|
||||
'isIEEE',
|
||||
'isInfinite',
|
||||
'isNaN',
|
||||
'isNegativeZero',
|
||||
'iterate',
|
||||
'last',
|
||||
'lcm',
|
||||
'length',
|
||||
'lex',
|
||||
'lines',
|
||||
'log',
|
||||
'logBase',
|
||||
'lookup',
|
||||
'map',
|
||||
'mapM',
|
||||
'mapM_',
|
||||
'max',
|
||||
'maxBound',
|
||||
'maximum',
|
||||
'maybe',
|
||||
'min',
|
||||
'minBound',
|
||||
'minimum',
|
||||
'mod',
|
||||
'negate',
|
||||
'not',
|
||||
'notElem',
|
||||
'null',
|
||||
'odd',
|
||||
'or',
|
||||
'otherwise',
|
||||
'pi',
|
||||
'pred',
|
||||
'print',
|
||||
'product',
|
||||
'properFraction',
|
||||
'putChar',
|
||||
'putStr',
|
||||
'putStrLn',
|
||||
'quot',
|
||||
'quotRem',
|
||||
'read',
|
||||
'readFile',
|
||||
'readIO',
|
||||
'readList',
|
||||
'readLn',
|
||||
'readParen',
|
||||
'reads',
|
||||
'readsPrec',
|
||||
'realToFrac',
|
||||
'recip',
|
||||
'rem',
|
||||
'repeat',
|
||||
'replicate',
|
||||
'return',
|
||||
'reverse',
|
||||
'round',
|
||||
'scaleFloat',
|
||||
'scanl',
|
||||
'scanl1',
|
||||
'scanr',
|
||||
'scanr1',
|
||||
'seq',
|
||||
'sequence',
|
||||
'sequence_',
|
||||
'show',
|
||||
'showChar',
|
||||
'showList',
|
||||
'showParen',
|
||||
'showString',
|
||||
'shows',
|
||||
'showsPrec',
|
||||
'significand',
|
||||
'signum',
|
||||
'sin',
|
||||
'sinh',
|
||||
'snd',
|
||||
'span',
|
||||
'splitAt',
|
||||
'sqrt',
|
||||
'subtract',
|
||||
'succ',
|
||||
'sum',
|
||||
'tail',
|
||||
'take',
|
||||
'takeWhile',
|
||||
'tan',
|
||||
'tanh',
|
||||
'toEnum',
|
||||
'toInteger',
|
||||
'toRational',
|
||||
'truncate',
|
||||
'uncurry',
|
||||
'undefined',
|
||||
'unlines',
|
||||
'until',
|
||||
'unwords',
|
||||
'unzip',
|
||||
'unzip3',
|
||||
'userError',
|
||||
'words',
|
||||
'writeFile',
|
||||
'zip',
|
||||
'zip3',
|
||||
'zipWith',
|
||||
'zipWith3',);
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,268 +0,0 @@
|
|||
<?php
|
||||
|
||||
// TODO: These are MySQL specific
|
||||
|
||||
$keywords = array(
|
||||
'ABORT', 'ACTION', 'ADD', 'AFTER', 'ALL', 'ALTER', 'ANALYZE', 'AS',
|
||||
'ASC', 'ATTACH', 'AUTOINCREMENT', 'AUTO_INCREMENT', 'BEFORE', 'BEGIN',
|
||||
'BY', 'CASCADE', 'CAST', 'CHECK', 'COLLATE', 'COLUMN',
|
||||
'COMMIT', 'CONFLICT', 'CONSTRAINT', 'CREATE', 'CROSS', 'CURRENT_DATE',
|
||||
'CURRENT_TIME', 'CURRENT_TIMESTAMP','DATABASE', 'DEFAULT', 'DEFERRABLE',
|
||||
'DEFERRED', 'DELETE', 'DESC', 'DETACH', 'DISTINCT', 'DROP', 'EACH', 'ELSE',
|
||||
'END', 'ESCAPE', 'EXCEPT', 'EXCLUSIVE', 'EXISTS', 'EXPLAIN', 'FAIL', 'FOR',
|
||||
'FOREIGN', 'FROM', 'FULL', 'GLOB', 'GROUP', 'HAVING', 'IF', 'IGNORE',
|
||||
'IMMEDIATE', 'IN', 'INDEX', 'INDEXED', 'INITITIALLY', 'INNER', 'INSERT',
|
||||
'INSTEAD', 'INTERSECT', 'INTO', 'ISNULL', 'JOIN', 'KEY', 'LEFT', 'LIKE',
|
||||
'LIMIT', 'MATCH', 'NATURAL', 'NO', 'NOTNULL', 'OF', 'OFFSET',
|
||||
'ON', 'OR', 'ORDER', 'OUTER', 'PLAN', 'PRAGMA', 'PRIMARY', 'QUERY', 'RAISE',
|
||||
'REFERENCES', 'REGEXP', 'REINDEX', 'RELEASE', 'RENAME', 'REPLACE', 'RESTRICT',
|
||||
'RIGHT', 'ROLLBACK', 'ROW', 'SAVEPOINT', 'SELECT', 'SET', 'TABLE', 'TEMP',
|
||||
'TEMPORARY', 'THEN', 'TO', 'TRANSACTION', 'TRIGGER', 'UNION', 'UNIQUE',
|
||||
'UPDATE', 'USING', 'VACUUM', 'VALUES', 'VIEW', 'VIRTUAL', 'WHEN', 'WHERE',
|
||||
'WITH',
|
||||
|
||||
// type qualifier stuff
|
||||
'SIGNED', 'UNSIGNED', 'ZEROFILL',
|
||||
|
||||
// seem to be missing these, probably not standard
|
||||
'MINVALUE', 'MAXVALUE', 'START'
|
||||
);
|
||||
|
||||
$types = array(
|
||||
'BINARY', 'BIT', 'BIGINT', 'BIGINTEGER', 'BLOB',
|
||||
'CHAR', 'CLOB',
|
||||
'DATE', 'DATETIME', 'DEC', 'DECIMAL', 'DOUBLE', 'DOUBLE_PRECISION',
|
||||
'ENUM',
|
||||
'FIXED', 'FLOAT',
|
||||
'INT', 'INTEGER',
|
||||
'MEDIUMINT', 'MEDIUMINTEGER',
|
||||
'NUMERIC',
|
||||
'REAL',
|
||||
'SMALLINT', 'SMALLINTEGER',
|
||||
'SET', 'TEXT', 'TIME', 'TIMESTAMP', 'TINYINT',
|
||||
'TINYINTEGER',
|
||||
'VARBINARY', 'VARCHAR',
|
||||
'YEAR',
|
||||
'ZONE' // for time zone
|
||||
);
|
||||
|
||||
|
||||
$values = array('NULL');
|
||||
|
||||
|
||||
// http://dev.mysql.com/doc/refman/5.0/en/func-op-summary-ref.html
|
||||
|
||||
$operators = array('AND', 'BETWEEN', 'BINARY', 'CASE', 'DIV', 'IS',
|
||||
'LIKE', 'NOT', 'SOUNDS', 'XOR');
|
||||
|
||||
$functions = array(
|
||||
'ABS',
|
||||
'ACOS',
|
||||
'ADDDATE',
|
||||
'ADDTIME',
|
||||
'AES_DECRYPT',
|
||||
'AES_ENCRYPT',
|
||||
'ASCII',
|
||||
'ASIN',
|
||||
'ATAN2',
|
||||
'ATAN',
|
||||
'AVG',
|
||||
'BENCHMARK',
|
||||
'BIN',
|
||||
'BIT_AND',
|
||||
'BIT_COUNT',
|
||||
'BIT_LENGTH',
|
||||
'BIT_OR',
|
||||
'BIT_XOR',
|
||||
'CAST',
|
||||
'CEIL',
|
||||
'CEILING',
|
||||
'CHAR_LENGTH',
|
||||
'CHAR',
|
||||
'CHARACTER_LENGTH',
|
||||
'CHARSET',
|
||||
'COALESCE',
|
||||
'COERCIBILITY',
|
||||
'COLLATION',
|
||||
'COMPRESS',
|
||||
'CONCAT_WS',
|
||||
'CONCAT',
|
||||
'CONNECTION_ID',
|
||||
'CONV',
|
||||
'CONVERT_TZ',
|
||||
'Convert',
|
||||
'COS',
|
||||
'COT',
|
||||
'COUNT',
|
||||
'COUNT',
|
||||
'CRC32',
|
||||
'CURDATE',
|
||||
'CURRENT_DATE',
|
||||
'CURRENT_TIME',
|
||||
'CURRENT_TIMESTAMP',
|
||||
'CURRENT_USER',
|
||||
'CURTIME',
|
||||
'DATABASE',
|
||||
'DATE_ADD',
|
||||
'DATE_FORMAT',
|
||||
'DATE_SUB',
|
||||
'DATE',
|
||||
'DATEDIFF',
|
||||
'DAY',
|
||||
'DAYNAME',
|
||||
'DAYOFMONTH',
|
||||
'DAYOFWEEK',
|
||||
'DAYOFYEAR',
|
||||
'DECODE',
|
||||
'DEFAULT',
|
||||
'DEGREES',
|
||||
'DES_DECRYPT',
|
||||
'DES_ENCRYPT',
|
||||
'ELT',
|
||||
'ENCODE',
|
||||
'ENCRYPT',
|
||||
'EXP',
|
||||
'EXPORT_SET',
|
||||
'EXTRACT',
|
||||
'FIELD',
|
||||
'FIND_IN_SET',
|
||||
'FLOOR',
|
||||
'FORMAT',
|
||||
'FOUND_ROWS',
|
||||
'FROM_DAYS',
|
||||
'FROM_UNIXTIME',
|
||||
'GET_FORMAT',
|
||||
'GET_LOCK',
|
||||
'GREATEST',
|
||||
'GROUP_CONCAT',
|
||||
'HEX',
|
||||
'HOUR',
|
||||
'IF',
|
||||
'IFNULL',
|
||||
'IN',
|
||||
'INET_ATON',
|
||||
'INET_NTOA',
|
||||
'INSERT',
|
||||
'INSTR',
|
||||
'INTERVAL',
|
||||
'IS_FREE_LOCK',
|
||||
'IS_USED_LOCK',
|
||||
'ISNULL',
|
||||
'LAST_DAY',
|
||||
'LAST_INSERT_ID',
|
||||
'LCASE',
|
||||
'LEAST',
|
||||
'LEFT',
|
||||
'LENGTH',
|
||||
'LN',
|
||||
'LOAD_FILE',
|
||||
'LOCALTIME',
|
||||
'LOCALTIMESTAMP,',
|
||||
'LOCATE',
|
||||
'LOG10',
|
||||
'LOG2',
|
||||
'LOG',
|
||||
'LOWER',
|
||||
'LPAD',
|
||||
'LTRIM',
|
||||
'MAKE_SET',
|
||||
'MAKEDATE',
|
||||
'MAKETIME',
|
||||
'MASTER_POS_WAIT',
|
||||
'MATCH',
|
||||
'MAX',
|
||||
'MD5',
|
||||
'MICROSECOND',
|
||||
'MID',
|
||||
'MIN',
|
||||
'MINUTE',
|
||||
'MOD',
|
||||
'MONTH',
|
||||
'MONTHNAME',
|
||||
'NAME_CONST',
|
||||
'NOW',
|
||||
'NULLIF',
|
||||
'OCT',
|
||||
'OCTET_LENGTH',
|
||||
'OLD_PASSWORD',
|
||||
'ORD',
|
||||
'PASSWORD',
|
||||
'PERIOD_ADD',
|
||||
'PERIOD_DIFF',
|
||||
'PI',
|
||||
'POSITION',
|
||||
'POW',
|
||||
'POWER',
|
||||
'ANALYSE',
|
||||
'QUARTER',
|
||||
'QUOTE',
|
||||
'RADIANS',
|
||||
'RAND',
|
||||
'REGEXP',
|
||||
'RELEASE_LOCK',
|
||||
'REPEAT',
|
||||
'REPLACE',
|
||||
'REVERSE',
|
||||
'RIGHT',
|
||||
'RLIKE',
|
||||
'ROUND',
|
||||
'ROW_COUNT',
|
||||
'RPAD',
|
||||
'RTRIM',
|
||||
'SCHEMA',
|
||||
'SEC_TO_TIME',
|
||||
'SECOND',
|
||||
'SESSION_USER',
|
||||
'SHA1',
|
||||
'SIGN',
|
||||
'SIN',
|
||||
'SLEEP',
|
||||
'SOUNDEX',
|
||||
'SPACE',
|
||||
'SQRT',
|
||||
'STD',
|
||||
'STDDEV_POP',
|
||||
'STDDEV_SAMP',
|
||||
'STDDEV',
|
||||
'STR_TO_DATE',
|
||||
'STRCMP',
|
||||
'SUBDATE',
|
||||
'SUBSTR',
|
||||
'SUBSTRING_INDEX',
|
||||
'SUBSTRING',
|
||||
'SUBTIME',
|
||||
'SUM',
|
||||
'SYSDATE',
|
||||
'SYSTEM_USER',
|
||||
'TAN',
|
||||
'TIME_FORMAT',
|
||||
'TIME_TO_SEC',
|
||||
'TIME',
|
||||
'TIMEDIFF',
|
||||
'TIMESTAMP',
|
||||
'TIMESTAMPADD',
|
||||
'TIMESTAMPDIFF',
|
||||
'TO_DAYS',
|
||||
'TRIM',
|
||||
'TRUNCATE',
|
||||
'UCASE',
|
||||
'UNCOMPRESS',
|
||||
'UNCOMPRESSED_LENGTH',
|
||||
'UNHEX',
|
||||
'UNIX_TIMESTAMP',
|
||||
'UPPER',
|
||||
'USER',
|
||||
'UTC_DATE',
|
||||
'UTC_TIME',
|
||||
'UTC_TIMESTAMP',
|
||||
'UUID',
|
||||
'VALUES',
|
||||
'VAR_POP',
|
||||
'VAR_SAMP',
|
||||
'VARIANCE',
|
||||
'VERSION',
|
||||
'WEEK',
|
||||
'WEEKDAY',
|
||||
'WEEKOFYEAR',
|
||||
'YEAR',
|
||||
'YEARWEEK');
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
<?php
|
||||
|
||||
$luminous_vb_values = array('False', 'Nothing', 'True');
|
||||
// http://msdn.microsoft.com/en-us/library/asfcc119.aspx
|
||||
$luminous_vb_operators = array('AddressOf', 'And', 'AndAlso', 'GetType',
|
||||
'GetXmlNamespace', 'Is', 'IsFalse', 'IsNot', 'IsTrue', 'Mod', 'Not',
|
||||
'Or', 'OrElse', 'TypeOf', 'Xor');
|
||||
|
||||
$luminous_vb_types = array('Boolean', 'Byte', 'CBool', 'Cbyte', 'CChar',
|
||||
'CDate', 'CDbl', 'CDec', 'Char', 'CInt', 'CLng', 'CObj', 'CShort', 'CSng',
|
||||
'CStr', 'CType', 'Date', 'Decimal', 'Double', 'Integer', 'Long', 'Object',
|
||||
'Short', 'String');
|
||||
|
||||
$luminous_vb_keywords = array(
|
||||
'AddHandler',
|
||||
'Alias',
|
||||
'Ansi',
|
||||
'As',
|
||||
'Assembly',
|
||||
'Auto',
|
||||
'ByRef',
|
||||
'ByVal',
|
||||
'Call',
|
||||
'Case',
|
||||
'Catch',
|
||||
'Class',
|
||||
'Const',
|
||||
'Declare',
|
||||
'Default',
|
||||
'Delegate',
|
||||
'Dim',
|
||||
'DirectCast',
|
||||
'Do',
|
||||
'Each',
|
||||
'Else',
|
||||
'ElseIf',
|
||||
'End',
|
||||
'EndIf',
|
||||
'Enum',
|
||||
'Erase',
|
||||
'Error',
|
||||
'Event',
|
||||
'Exit',
|
||||
'Finally',
|
||||
'For',
|
||||
'Friend',
|
||||
'Function',
|
||||
'Get',
|
||||
'GetType',
|
||||
'GoSub',
|
||||
'GoTo',
|
||||
'Handles',
|
||||
'If',
|
||||
'Implements',
|
||||
'Imports',
|
||||
'In',
|
||||
'Inherits',
|
||||
'Interface',
|
||||
'Let',
|
||||
'Lib',
|
||||
'Like',
|
||||
'Loop',
|
||||
'Me',
|
||||
'Module',
|
||||
'MustInherit',
|
||||
'MustOverride',
|
||||
'MyBase',
|
||||
'MyClass',
|
||||
'Namespace',
|
||||
'New',
|
||||
'Next',
|
||||
'Nothing',
|
||||
'NotInheritable',
|
||||
'NotOverridable',
|
||||
'On',
|
||||
'Option',
|
||||
'Optional',
|
||||
'OrElse',
|
||||
'Overloads',
|
||||
'Overridable',
|
||||
'Overrides',
|
||||
'ParamArray',
|
||||
'Preserve',
|
||||
'Private',
|
||||
'Property',
|
||||
'Protected',
|
||||
'Public',
|
||||
'RaiseEvent',
|
||||
'ReadOnly',
|
||||
'ReDim',
|
||||
'RemoveHandler',
|
||||
'Resume',
|
||||
'Return',
|
||||
'Select',
|
||||
'Set',
|
||||
'Shadows',
|
||||
'Shared',
|
||||
'Single',
|
||||
'Static',
|
||||
'Step',
|
||||
'Stop',
|
||||
'Structure',
|
||||
'Sub',
|
||||
'SyncLock',
|
||||
'Then',
|
||||
'Throw',
|
||||
'To',
|
||||
'Try',
|
||||
'Unicode',
|
||||
'Until',
|
||||
'Variant',
|
||||
'Wend',
|
||||
'When',
|
||||
'While',
|
||||
'With',
|
||||
'WithEvents',
|
||||
'WriteOnly'
|
||||
);
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
<?php
|
||||
global $luminous_vim_functions;
|
||||
global $luminous_vim_keywords;
|
||||
|
||||
/*
|
||||
* Credit for this list goes to `nelstrom' on github:
|
||||
* https://github.com/nelstrom/SyntaxHighlighter/blob/master/scripts/shBrushVimscript.js
|
||||
*/
|
||||
|
||||
$luminous_vim_functions = array( 'abs',
|
||||
'add', 'append', 'argc', 'argidx', 'argv', 'atan', 'browse', 'browsedir',
|
||||
'bufexists', 'buflisted', 'bufloaded', 'bufname', 'bufnr', 'bufwinnr',
|
||||
'byte2line', 'byteidx', 'call', 'ceil', 'changenr', 'char2nr', 'cindent',
|
||||
'clearmatches', 'col', 'complete', 'complete_add', 'complete_check', 'confirm',
|
||||
'copy', 'cos', 'count', 'cscope_connection', 'cursor', 'deepcopy', 'delete',
|
||||
'did_filetype', 'diff_filler', 'diff_hlID', 'empty', 'escape', 'eval',
|
||||
'eventhandler', 'executable', 'exists', 'expand', 'expr8', 'extend', 'feedkeys',
|
||||
'filereadable', 'filewritable', 'filter', 'finddir', 'findfile', 'float2nr',
|
||||
'floor', 'fnameescape', 'fnamemodify', 'foldclosed', 'foldclosedend',
|
||||
'foldlevel', 'foldtext', 'foldtextresult', 'foreground', 'function',
|
||||
'garbagecollect', 'get', 'getbufline', 'getbufvar', 'getchar', 'getcharmod',
|
||||
'getcmdline', 'getcmdpos', 'getcmdtype', 'getcwd', 'getfontname', 'getfperm',
|
||||
'getfsize', 'getftime', 'getftype', 'getline', 'getloclist', 'getmatches',
|
||||
'getpid', 'getpos', 'getqflist', 'getreg', 'getregtype', 'gettabwinvar',
|
||||
'getwinposx', 'getwinposy', 'getwinvar', 'glob', 'globpath', 'has', 'has_key',
|
||||
'haslocaldir', 'hasmapto', 'histadd', 'histdel', 'histget', 'histnr', 'hlID',
|
||||
'hlexists', 'hostname', 'iconv', 'indent', 'index', 'input', 'inputdialog',
|
||||
'inputlist', 'inputrestore', 'inputsave', 'inputsecret', 'insert',
|
||||
'isdirectory', 'islocked', 'items', 'join', 'keys', 'len', 'libcall',
|
||||
'libcallnr', 'line', 'line2byte', 'lispindent', 'localtime', 'log10', 'map',
|
||||
'maparg', 'mapcheck', 'match', 'matchadd', 'matcharg', 'matchdelete',
|
||||
'matchend', 'matchlist', 'matchstr', 'max', 'min', 'mkdir', 'mode',
|
||||
'nextnonblank', 'nr2char', 'pathshorten', 'pow', 'prevnonblank', 'printf',
|
||||
'pumvisible', 'range', 'readfile', 'reltime', 'reltimestr', 'remote_expr',
|
||||
'remote_foreground', 'remote_peek', 'remote_read', 'remote_send', 'remove',
|
||||
'rename', 'repeat', 'resolve', 'reverse', 'round', 'search', 'searchdecl',
|
||||
'searchpair', 'searchpairpos', 'searchpos', 'server2client', 'serverlist',
|
||||
'setbufvar', 'setcmdpos', 'setline', 'setloclist', 'setmatches', 'setpos',
|
||||
'setqflist', 'setreg', 'settabwinvar', 'setwinvar', 'shellescape', 'simplify',
|
||||
'sin', 'sort', 'soundfold', 'spellbadword', 'spellsuggest', 'split', 'sqrt',
|
||||
'str2float', 'str2nr', 'strftime', 'stridx', 'string', 'strlen', 'strpart',
|
||||
'strridx', 'strtrans', 'submatch', 'substitute', 'synID', 'synIDattr',
|
||||
'synIDtrans', 'synstack', 'system', 'tabpagebuflist', 'tabpagenr',
|
||||
'tabpagewinnr', 'tagfiles', 'taglist', 'tempname', 'tolower', 'toupper', 'tr',
|
||||
'trunc', 'type', 'values', 'virtcol', 'visualmode', 'winbufnr', 'wincol',
|
||||
'winheight', 'winline', 'winnr', 'winrestcmd', 'winrestview', 'winsaveview',
|
||||
'winwidth', 'writefile');
|
||||
|
||||
|
||||
|
||||
$luminous_vim_keywords = array(
|
||||
'Next',
|
||||
'Print',
|
||||
'XMLent', 'XMLns',
|
||||
'abc', 'abclear', 'abo', 'aboveleft', 'acd', 'ai', 'akm', 'al', 'aleph',
|
||||
'all',
|
||||
'allowrevins',
|
||||
'altkeymap', 'ambiwidth', 'ambw', 'anti', 'antialias', 'ar', 'arab', 'arabic',
|
||||
'arabicshape', 'arabshape', 'argadd',
|
||||
'arga', 'argdelete', 'argdo', 'arge', 'argedit', 'argg', 'argglobal',
|
||||
'arglargs', 'arglocal', 'argument', 'ari', 'arshape', 'as', 'ascii', 'au',
|
||||
'augroup', 'auto', 'autochdir', 'autocmd', 'autoindent', 'autoread',
|
||||
'autowrite', 'autowriteall', 'aw', 'awa',
|
||||
'bN', 'bNext', 'ba', 'background', 'backspace', 'backup', 'backupcopy',
|
||||
'backupdir', 'backupext', 'backupskip', 'bad', 'badd', 'ball', 'balloondelay',
|
||||
'ballooneval', 'balloonexpr', 'bd', 'bdelete', 'bdir', 'bdlay', 'bel',
|
||||
'belowright', 'beval', 'bex', 'bexpr', 'bf', 'bfirst', 'bg', 'bh', 'bin',
|
||||
'binary', 'biosk', 'bioskey', 'bk', 'bkc', 'bl', 'blast', 'bm', 'bmodified',
|
||||
'bn', 'bnext', 'bo', 'bomb', 'botright', 'bp', 'bprevious', 'br', 'brea',
|
||||
'break', 'breaka', 'breakadd', 'breakat', 'breakd', 'breakdel', 'breakl',
|
||||
'breaklist', 'brewind', 'brk', 'bro', 'browse', 'browsedir', 'bs', 'bsdir',
|
||||
'bsk', 'bt', 'bufdo', 'buffer', 'buffers', 'bufhidden', 'buflisted', 'buftype',
|
||||
'bun', 'bunload', 'bw', 'bwipeout',
|
||||
'cN', 'cNext', 'cNf', 'cNfile', 'cabc', 'cabclear', 'cad', 'caddb',
|
||||
'caddbuffer', 'caddexpr', 'caddf', 'caddfile', 'cal', 'call', 'casemap', 'cat',
|
||||
'catch', 'cb', 'cbuffer', 'cc', 'ccl', 'cclose', 'ccv', 'cd', 'cdpath', 'ce',
|
||||
'cedit', 'center', 'cex', 'cexpr', 'cf', 'cfile', 'cfir', 'cfirst', 'cfu', 'cg',
|
||||
'cgetb', 'cgetbuffer', 'cgete', 'cgetexpr', 'cgetfile', 'ch', 'change',
|
||||
'changes', 'charconvert', 'chd', 'chdir', 'che', 'checkpath', 'checkt',
|
||||
'checktime', 'ci', 'cin', 'cindent', 'cink', 'cinkeys', 'cino', 'cinoptions',
|
||||
'cinw', 'cinwords', 'cl', 'cla', 'clast', 'clipboard', 'clist', 'clo', 'close',
|
||||
'cm', 'cmap', 'cmapc', 'cmapclear', 'cmdheight', 'cmdwinheight', 'cmp', 'cms',
|
||||
'cn', 'cnew', 'cnewer', 'cnext', 'cnf', 'cnfile', 'cno', 'cnoremap', 'co',
|
||||
'col', 'colder', 'colo', 'colorscheme', 'columns', 'com', 'comc', 'comclear',
|
||||
'command', 'comments', 'commentstring', 'comp', 'compatible', 'compiler',
|
||||
'complete', 'completefunc', 'completeopt', 'con', 'conf', 'confirm', 'consk',
|
||||
'conskey', 'continue', 'cope', 'copen', 'copy', 'copyindent', 'cot', 'cp',
|
||||
'cpf', 'cpfile', 'cpo', 'cpoptions', 'cprevious', 'cpt', 'cq', 'cquit', 'cr',
|
||||
'crewind', 'cscopepathcomp', 'cscopeprg', 'cscopequickfix', 'cscopetag',
|
||||
'cscopetagorder', 'cscopeverbose', 'cspc', 'csprg', 'csqf', 'cst', 'csto',
|
||||
'csverb', 'cuc', 'cul', 'cuna', 'cunabbrev', 'cursorcolumn', 'cursorline', 'cw',
|
||||
'cwh', 'cwindow',
|
||||
'debug', 'debugg', 'debuggreedy', 'deco', 'def', 'define', 'delc', 'delcombine',
|
||||
'delcommand', 'delete', 'delf', 'delfunction', 'delm', 'delmarks', 'dex', 'dg',
|
||||
'di', 'dict', 'dictionary', 'diff', 'diffexpr', 'diffg', 'diffget', 'diffoff',
|
||||
'diffopt', 'diffpatch', 'diffpu', 'diffput', 'diffsplit', 'diffthis', 'diffu',
|
||||
'diffupdate', 'dig', 'digraph', 'digraphs', 'dip', 'dir', 'directory',
|
||||
'display', 'dj', 'djump', 'dl', 'dlist', 'do', 'doautoa', 'doautoall',
|
||||
'doautocmd', 'dr', 'drop', 'ds', 'dsearch', 'dsp', 'dsplit', 'dy',
|
||||
'ea', 'ead', 'eadirection', 'earlier', 'eb', 'echoe', 'echoerr', 'echohl',
|
||||
'echom', 'echomsg', 'echon', 'ed', 'edcompatible', 'edit', 'ef', 'efm', 'ei',
|
||||
'ek', 'el', 'else', 'elsei', 'elseif', 'em', 'emenu', 'en', 'enc', 'encoding',
|
||||
'endf', 'endfo', 'endfor', 'endfunction', 'endif', 'endofline', 'endt',
|
||||
'endtry', 'endw', 'endwhile', 'ene', 'enew', 'environment', 'eol', 'ep',
|
||||
'equalalways', 'equalprg', 'errorbells', 'errorfile', 'errorformat', 'esckeys',
|
||||
'et', 'event', 'eventignore', 'ex', 'exi', 'exit', 'expandtab', 'expression',
|
||||
'exrc', 'exu', 'exusage',
|
||||
'fcl', 'fcs', 'fdc', 'fde', 'fdi', 'fdl', 'fdls', 'fdm', 'fdn', 'fdo', 'fdt',
|
||||
'fen', 'fenc', 'fencs', 'fex', 'ff', 'ffs', 'file', 'fileencoding',
|
||||
'fileencodings', 'fileformat', 'fileformats', 'files', 'filetype', 'fillchars',
|
||||
'fin', 'fina', 'finally', 'find', 'fini', 'finish', 'fir', 'first', 'fix',
|
||||
'fixdel', 'fk', 'fkmap', 'flp', 'fml', 'fmr', 'fo', 'fold', 'foldc',
|
||||
'foldclose', 'foldcolumn', 'foldd', 'folddoc', 'folddoclosed', 'folddoopen',
|
||||
'foldenable', 'foldexpr', 'foldignore', 'foldlevel', 'foldlevelstart',
|
||||
'foldmarker', 'foldmethod', 'foldminlines', 'foldnestmax', 'foldo', 'foldopen',
|
||||
'foldtext', 'for', 'formatexpr', 'formatlistpat', 'formatoptions', 'formatprg',
|
||||
'fp', 'fs', 'fsync', 'ft', 'fu', 'function',
|
||||
'gcr', 'gd', 'gdefault', 'gfm', 'gfn', 'gfs', 'gfw', 'ghr', 'go', 'goto', 'gp',
|
||||
'gr', 'grep', 'grepa', 'grepadd', 'grepformat', 'grepprg', 'gtl', 'gtt',
|
||||
'guicursor', 'guifont', 'guifontset', 'guifontwide', 'guiheadroom',
|
||||
'guioptions', 'guipty', 'guitablabel', 'guitabtooltip',
|
||||
'ha', 'hardcopy', 'help', 'helpf', 'helpfile', 'helpfind', 'helpg', 'helpgrep',
|
||||
'helpheight', 'helplang', 'helpt', 'helptags', 'hf', 'hh', 'hi', 'hid',
|
||||
'hidden', 'hide', 'highlight', 'his', 'history', 'hk', 'hkmap', 'hkmapp', 'hkp',
|
||||
'hl', 'hlg', 'hls', 'hlsearch',
|
||||
'iabc', 'iabclear', 'ic', 'icon', 'iconstring', 'if', 'ignorecase', 'ij',
|
||||
'ijump', 'il', 'ilist', 'im', 'imactivatekey', 'imak', 'imap', 'imapc',
|
||||
'imapclear', 'imc', 'imcmdline', 'imd', 'imdisable', 'imi', 'iminsert', 'ims',
|
||||
'imsearch', 'inc', 'include', 'includeexpr', 'incsearch', 'inde', 'indentexpr',
|
||||
'indentkeys', 'indk', 'inex', 'inf', 'infercase', 'ino', 'inoremap',
|
||||
'insertmode', 'is', 'isearch', 'isf', 'isfname', 'isi', 'isident', 'isk',
|
||||
'iskeyword', 'isp', 'isplit', 'isprint', 'iuna', 'iunabbrev',
|
||||
'join', 'joinspaces', 'js', 'ju', 'jumps',
|
||||
'kee', 'keepalt', 'keepj', 'keepjumps', 'keepmarks', 'key', 'keymap',
|
||||
'keymodel', 'keywordprg', 'km', 'kmp', 'kp',
|
||||
'lN', 'lNext', 'lNf', 'lNfile', 'la', 'lad', 'laddb', 'laddbuffer', 'laddexpr',
|
||||
'laddf', 'laddfile', 'lan', 'langmap', 'langmenu', 'language', 'last',
|
||||
'laststatus', 'later', 'lazyredraw', 'lb', 'lbr', 'lbuffer', 'lc', 'lcd', 'lch',
|
||||
'lchdir', 'lcl', 'lclose', 'lcs', 'le', 'left', 'lefta', 'leftabove', 'let',
|
||||
'lex', 'lexpr', 'lf', 'lfile', 'lfir', 'lfirst', 'lg', 'lgetb', 'lgetbuffer',
|
||||
'lgete', 'lgetexpr', 'lgetfile', 'lgr', 'lgrep', 'lgrepa', 'lgrepadd', 'lh',
|
||||
'lhelpgrep', 'linebreak', 'lines', 'linespace', 'lisp', 'lispwords', 'list',
|
||||
'listchars', 'll', 'lla', 'llast', 'lli', 'llist', 'lm', 'lmak', 'lmake',
|
||||
'lmap', 'lmapc', 'lmapclear', 'ln', 'lne', 'lnew', 'lnewer', 'lnext', 'lnf',
|
||||
'lnfile', 'lnoremap', 'lo', 'loadplugins', 'loadview', 'loc', 'lockmarks',
|
||||
'lockv', 'lockvar', 'lol', 'lolder', 'lop', 'lopen', 'lp', 'lpf', 'lpfile',
|
||||
'lpl', 'lprevious', 'lr', 'lrewind', 'ls', 'lsp', 'ltag', 'lv', 'lvimgrep',
|
||||
'lvimgrepa', 'lvimgrepadd', 'lw', 'lwindow', 'lz',
|
||||
'ma', 'maca', 'macaction', 'macatsui', 'macm', 'macmenu', 'magic', 'mak',
|
||||
'make', 'makeef', 'makeprg', 'map', 'mapping', 'mark', 'marks', 'mat', 'match',
|
||||
'matchpairs', 'matchtime', 'maxcombine', 'maxfuncdepth', 'maxmapdepth',
|
||||
'maxmem', 'maxmempattern', 'maxmemtot', 'mco', 'mef', 'menu', 'menuitems',
|
||||
'menut', 'menutranslate', 'mfd', 'mh', 'mis', 'mk', 'mkexrc', 'mks',
|
||||
'mksession', 'mksp', 'mkspell', 'mkspellmem', 'mkv', 'mkvie', 'mkview',
|
||||
'mkvimrc', 'ml', 'mls', 'mm', 'mmd', 'mmp', 'mmt', 'mod', 'mode', 'modeline',
|
||||
'modelines', 'modifiable', 'modified', 'more', 'mouse', 'mousef', 'mousefocus',
|
||||
'mousehide', 'mousem', 'mousemodel', 'mouses', 'mouseshape', 'mouset',
|
||||
'mousetime', 'move', 'mp', 'mps', 'msm', 'mz', 'mzf', 'mzfile', 'mzq',
|
||||
'mzquantum', 'mzscheme',
|
||||
'nbkey', 'new', 'next', 'nf', 'nm', 'nmap', 'nmapc', 'nmapclear', 'nn',
|
||||
'nnoremap', 'no', 'noexpandtab', 'noh', 'nohlsearch', 'noremap', 'nrformats',
|
||||
'nu', 'number', 'numberwidth', 'nuw',
|
||||
'odev', 'oft', 'ofu', 'om', 'omap', 'omapc', 'omapclear', 'omnifunc', 'on',
|
||||
'only', 'ono', 'onoremap', 'open', 'opendevice', 'operatorfunc', 'opfunc',
|
||||
'opt', 'option', 'options', 'osfiletype',
|
||||
'pa', 'para', 'paragraphs', 'paste', 'pastetoggle', 'patchexpr', 'patchmode',
|
||||
'path', 'pc', 'pclose', 'pdev', 'pe', 'ped', 'pedit', 'penc', 'perl', 'perld',
|
||||
'perldo', 'pex', 'pexpr', 'pfn', 'ph', 'pheader', 'pi', 'pm', 'pmbcs', 'pmbfn',
|
||||
'po', 'pop', 'popt', 'popu', 'popup', 'pp', 'ppop', 'pre', 'preserve',
|
||||
'preserveindent', 'prev', 'previewheight', 'previewwindow', 'previous', 'print',
|
||||
'printdevice', 'printencoding', 'printexpr', 'printfont', 'printheader',
|
||||
'printmbcharset', 'printmbfont', 'printoptions', 'prof', 'profd', 'profdel',
|
||||
'profile', 'prompt', 'promptf', 'promptfind', 'promptr', 'promptrepl', 'ps',
|
||||
'psearch', 'pt', 'ptN', 'ptNext', 'pta', 'ptag', 'ptf', 'ptfirst', 'ptj',
|
||||
'ptjump', 'ptl', 'ptlast', 'ptn', 'ptnext', 'ptp', 'ptprevious', 'ptr',
|
||||
'ptrewind', 'pts', 'ptselect', 'pu', 'pumheight', 'put', 'pvh', 'pvw', 'pw',
|
||||
'pwd', 'py', 'pyf', 'pyfile', 'python',
|
||||
'qa', 'qall', 'qe', 'quit', 'quita', 'quitall', 'quoteescape',
|
||||
'rdt', 'read', 'readonly', 'rec', 'recover', 'red', 'redi', 'redir', 'redo',
|
||||
'redr', 'redraw', 'redraws', 'redrawstatus', 'redrawtime', 'reg', 'registers',
|
||||
'remap', 'report', 'res', 'resize', 'restorescreen', 'ret', 'retab', 'retu',
|
||||
'return', 'revins', 'rew', 'rewind', 'ri', 'right', 'rightb', 'rightbelow',
|
||||
'rightleft', 'rightleftcmd', 'rl', 'rlc', 'ro', 'rs', 'rtp', 'ru', 'rub',
|
||||
'ruby', 'rubyd', 'rubydo', 'rubyf', 'rubyfile', 'ruf', 'ruler', 'rulerformat',
|
||||
'runtime', 'runtimepath', 'rv', 'rviminfo',
|
||||
'sN', 'sNext', 'sa', 'sal', 'sall', 'san', 'sandbox', 'sargument', 'sav',
|
||||
'saveas', 'sb', 'sbN', 'sbNext', 'sba', 'sball', 'sbf', 'sbfirst', 'sbl',
|
||||
'sblast', 'sbm', 'sbmodified', 'sbn', 'sbnext', 'sbo', 'sbp', 'sbprevious',
|
||||
'sbr', 'sbrewind', 'sbuffer', 'sc', 'scb', 'scr', 'scrip', 'scripte',
|
||||
'scriptencoding', 'scriptnames', 'scroll', 'scrollbind', 'scrolljump',
|
||||
'scrolloff', 'scrollopt', 'scs', 'se', 'sect', 'sections', 'secure', 'sel',
|
||||
'selection', 'selectmode', 'sessionoptions', 'set', 'setf', 'setfiletype',
|
||||
'setg', 'setglobal', 'setl', 'setlocal', 'sf', 'sfind', 'sfir', 'sfirst', 'sft',
|
||||
'sh', 'shcf', 'shell', 'shellcmdflag', 'shellpipe', 'shellquote', 'shellredir',
|
||||
'shellslash', 'shelltemp', 'shelltype', 'shellxquote', 'shiftround',
|
||||
'shiftwidth', 'shm', 'shortmess', 'shortname', 'showbreak', 'showcmd',
|
||||
'showfulltag', 'showmatch', 'showmode', 'showtabline', 'shq', 'si',
|
||||
'sidescroll', 'sidescrolloff', 'sign', 'sil', 'silent', 'sim', 'simalt', 'siso',
|
||||
'sj', 'sl', 'sla', 'slast', 'sleep', 'slm', 'sm', 'smagic', 'smap', 'smapc',
|
||||
'smapclear', 'smartcase', 'smartindent', 'smarttab', 'smc', 'smd', 'sme',
|
||||
'smenu', 'sn', 'snext', 'sni', 'sniff', 'sno', 'snomagic', 'snor', 'snoremap',
|
||||
'snoreme', 'snoremenu', 'so', 'softtabstop', 'sol', 'something', 'sor', 'sort',
|
||||
'source', 'sp', 'spc', 'spe', 'spell', 'spellcapcheck', 'spelld', 'spelldump',
|
||||
'spellfile', 'spellgood', 'spelli', 'spellinfo', 'spelllang', 'spellr',
|
||||
'spellrepall', 'spellsuggest', 'spellu', 'spellundo', 'spellw', 'spellwrong',
|
||||
'spf', 'spl', 'split', 'splitbelow', 'splitright', 'spr', 'sprevious', 'sps',
|
||||
'sr', 'sre', 'srewind', 'srr', 'ss', 'ssl', 'ssop', 'st', 'sta', 'stag', 'stal',
|
||||
'star', 'startg', 'startgreplace', 'startinsert', 'startofline', 'startr',
|
||||
'startreplace', 'statusline', 'stj', 'stjump', 'stl', 'stmp', 'stop', 'stopi',
|
||||
'stopinsert', 'sts', 'stselect', 'su', 'sua', 'suffixes', 'suffixesadd', 'sun',
|
||||
'sunhide', 'sunme', 'sunmenu', 'sus', 'suspend', 'sv', 'sview', 'sw',
|
||||
'swapfile', 'swapsync', 'swb', 'swf', 'switchbuf', 'sws', 'sxq', 'syn',
|
||||
'syncbind', 'synmaxcol', 'syntax',
|
||||
'tN', 'tNext', 'ta', 'tab', 'tabN', 'tabNext', 'tabc', 'tabclose', 'tabd',
|
||||
'tabdo', 'tabe', 'tabedit', 'tabf', 'tabfind', 'tabfir', 'tabfirst', 'tabl',
|
||||
'tablast', 'tabline', 'tabm', 'tabmove', 'tabn', 'tabnew', 'tabnext', 'tabo',
|
||||
'tabonly', 'tabp', 'tabpagemax', 'tabprevious', 'tabr', 'tabrewind', 'tabs',
|
||||
'tabstop', 'tag', 'tag_listfiles', 'tagbsearch', 'taglength', 'tagrelative',
|
||||
'tags', 'tagstack', 'tal', 'tb', 'tbi', 'tbidi', 'tbis', 'tbs', 'tc', 'tcl',
|
||||
'tcld', 'tcldo', 'tclf', 'tclfile', 'te', 'tearoff', 'tenc', 'term', 'termbidi',
|
||||
'termencoding', 'terse', 'textauto', 'textmode', 'textwidth', 'tf', 'tfirst',
|
||||
'tgst', 'th', 'thesaurus', 'throw', 'tildeop', 'timeout', 'timeoutlen', 'title',
|
||||
'titlelen', 'titleold', 'titlestring', 'tj', 'tjump', 'tl', 'tlast', 'tm',
|
||||
'tmenu', 'tn', 'tnext', 'to', 'toolbar', 'toolbariconsize', 'top', 'topleft',
|
||||
'tp', 'tpm', 'tprevious', 'tr', 'trewind', 'try', 'ts', 'tselect', 'tsl', 'tsr',
|
||||
'ttimeout', 'ttimeoutlen', 'ttm', 'tty', 'ttybuiltin', 'ttyfast', 'ttym',
|
||||
'ttymouse', 'ttyscroll', 'ttytype', 'tu', 'tunmenu', 'tw', 'tx',
|
||||
'uc', 'ul', 'una', 'unabbreviate', 'undo', 'undoj', 'undojoin', 'undol',
|
||||
'undolevels', 'undolist', 'unh', 'unhide', 'unl', 'unlet', 'unlo', 'unlockvar',
|
||||
'up', 'update', 'updatecount', 'updatetime', 'ut',
|
||||
'var', 'vb', 'vbs', 'vdir', 've', 'verb', 'verbose', 'verbosefile', 'version',
|
||||
'vert', 'vertical', 'vfile', 'vi', 'vie', 'view', 'viewdir', 'viewoptions',
|
||||
'vim', 'vimgrep', 'vimgrepa', 'vimgrepadd', 'viminfo', 'virtualedit', 'visual',
|
||||
'visualbell', 'viu', 'viusage', 'vm', 'vmap', 'vmapc', 'vmapclear', 'vn', 'vne',
|
||||
'vnew', 'vnoremap', 'vop', 'vs', 'vsplit',
|
||||
'wN', 'wNext', 'wa', 'wak', 'wall', 'warn', 'wb', 'wc', 'wcm', 'wd',
|
||||
'weirdinvert', 'wfh', 'wfw', 'wh', 'whichwrap', 'while', 'wi', 'wig',
|
||||
'wildchar', 'wildcharm', 'wildignore', 'wildmenu', 'wildmode', 'wildoptions',
|
||||
'wim', 'win', 'winaltkeys', 'winc', 'wincmd', 'windo', 'window', 'winfixheight',
|
||||
'winfixwidth', 'winheight', 'winminheight', 'winminwidth', 'winp', 'winpos',
|
||||
'winsize', 'winwidth', 'wiv', 'wiw', 'wm', 'wmh', 'wmnu', 'wmw', 'wn', 'wnext',
|
||||
'wop', 'wp', 'wprevious', 'wq', 'wqa', 'wqall', 'wrap', 'wrapmargin',
|
||||
'wrapscan', 'write', 'writeany', 'writebackup', 'writedelay', 'ws', 'wsverb',
|
||||
'wv', 'wviminfo', 'ww',
|
||||
'xa', 'xall', 'xit', 'xm', 'xmap', 'xmapc', 'xmapclear', 'xmenu',
|
||||
'xn', 'xnremap', 'xnoreme', 'xnoremenu', 'xunme', 'xunmenu',
|
||||
'yank'
|
||||
|
||||
);
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
require_once(dirname(__FILE__) . '/include/java_func_list.php');
|
||||
|
||||
class LuminousJavaScanner extends LuminousSimpleScanner {
|
||||
|
||||
function init() {
|
||||
$this->add_identifier_mapping('KEYWORD',
|
||||
$GLOBALS['luminous_java_keywords']);
|
||||
$this->add_identifier_mapping('TYPE', $GLOBALS['luminous_java_types']);
|
||||
|
||||
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_ML);
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_SL);
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$DOUBLE_STR);
|
||||
$this->add_pattern('CHARACTER', LuminousTokenPresets::$SINGLE_STR);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_HEX);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_REAL);
|
||||
$this->add_pattern('IDENT', '/[a-zA-Z$_][$\w]*/');
|
||||
$this->add_pattern('OPERATOR', '/[!%^&*\-=+:?|<>]+/');
|
||||
// this is called an annotation
|
||||
// http://download.oracle.com/javase/1,5.0/docs/guide/language/annotations.html
|
||||
$this->add_pattern('FUNCTION', '/@[\w]+/');
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
$p = 0;
|
||||
if (preg_match('/^import\s+java\./m', $src)) return 1.0;
|
||||
if (preg_match('/System\.out\.print/', $src)) $p += 0.2;
|
||||
if (preg_match('/public\s+static\s+void\s+main\\b/', $src)) $p += 0.2;
|
||||
return $p;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
class LuminousJavaScriptScanner extends LuminousECMAScriptScanner {
|
||||
// mostly the same for now
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
// JavaScript is surprisingly indistinct when you think about it,
|
||||
// so these are a bit of a stretch and it's hard to ever return a
|
||||
// value more than ~40%
|
||||
$p = 0;
|
||||
// var x =
|
||||
// not amazingly distinct, but something
|
||||
if (preg_match('/var\s++\w++\s*+=/', $src)) $p += 0.05;
|
||||
// $, jquery
|
||||
if (preg_match('/\\b$\\( | jQuery/x', $src)) $p += 0.20;
|
||||
// typeof x == undefined
|
||||
if (preg_match('/typeof\s++\w++\s*+[!=]{2,3}+\s*+[\'"]?+undefined/i', $src))
|
||||
$p += 0.10;
|
||||
if (strpos($src, 'document.') !== false) $p += 0.10;
|
||||
if (strpos($src, 'Math.') !== false) $p += 0.05;
|
||||
// Anonymous functions
|
||||
if (preg_match('/function\s*+\\([^)]*+\\)\s*+\\{/', $src))
|
||||
$p += 0.05;
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
<?php
|
||||
|
||||
|
||||
class LuminousJSONScanner extends LuminousScanner {
|
||||
|
||||
private $stack = array();
|
||||
|
||||
|
||||
public function init() {
|
||||
$this->add_identifier_mapping('KEYWORD', array('true', 'false', 'null'));
|
||||
|
||||
|
||||
}
|
||||
public function state() {
|
||||
if (!empty($this->stack)) return $this->stack[count($this->stack)-1][0];
|
||||
else return null;
|
||||
}
|
||||
|
||||
private function expecting($x=null) {
|
||||
if ($x !== null) {
|
||||
if (!empty($this->stack)) $this->stack[count($this->stack)-1][1] = $x;
|
||||
}
|
||||
if (!empty($this->stack)) return $this->stack[count($this->stack)-1][1];
|
||||
else return null;
|
||||
}
|
||||
|
||||
function main() {
|
||||
while (!$this->eos()) {
|
||||
$tok = null;
|
||||
$c = $this->peek();
|
||||
|
||||
list($state, $expecting) = array($this->state(), $this->expecting());
|
||||
|
||||
$this->skip_whitespace();
|
||||
if ($this->eos()) break;
|
||||
if ($this->scan(LuminousTokenPresets::$NUM_REAL) !== null) {
|
||||
$tok = 'NUMERIC';
|
||||
}
|
||||
elseif($this->scan('/[a-zA-Z]\w*/')) {
|
||||
$tok = 'IDENT';
|
||||
}
|
||||
elseif($this->scan(LuminousTokenPresets::$DOUBLE_STR)) {
|
||||
$tok = ($state === 'obj' && $expecting === 'key')? 'TYPE' : 'STRING';
|
||||
}
|
||||
elseif($this->scan('/\[/')) {
|
||||
$this->stack[] = array('array', null);
|
||||
$tok = 'OPERATOR';
|
||||
}
|
||||
elseif($this->scan('/\]/')) {
|
||||
if ($state === 'array') {
|
||||
array_pop($this->stack);
|
||||
$tok = 'OPERATOR';
|
||||
}
|
||||
}
|
||||
elseif($this->scan('/\{/')) {
|
||||
$this->stack[] = array('obj', 'key');
|
||||
$tok = 'OPERATOR';
|
||||
}
|
||||
elseif($state === 'obj' && $this->scan('/\}/')) {
|
||||
array_pop($this->stack);
|
||||
$tok = 'OPERATOR';
|
||||
}
|
||||
elseif($state === 'obj' && $this->scan('/:/')) {
|
||||
$this->expecting('value');
|
||||
$tok = 'OPERATOR';
|
||||
}
|
||||
elseif($this->scan('/,/')) {
|
||||
if ($state === 'obj') {
|
||||
$this->expecting('key');
|
||||
$tok = 'OPERATOR';
|
||||
}
|
||||
elseif($state === 'array') $tok = 'OPERATOR';
|
||||
}
|
||||
else $this->scan('/./');
|
||||
|
||||
$this->record($this->match(), $tok);
|
||||
}
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
// JSON is fairly hard to guess
|
||||
$p = 0;
|
||||
$src_ = trim($src);
|
||||
if (!empty($src_)) {
|
||||
$char = $src_[0];
|
||||
$char2 = $src_[strlen($src_)-1];
|
||||
$str = '"(?>[^"\\\\]+|\\\\.)"';
|
||||
// looks like an object or array
|
||||
if ( ($char === '[' && $char2 === ']')
|
||||
|| ($char === '{' && $char2 === '}'))
|
||||
{
|
||||
$p += 0.05;
|
||||
}
|
||||
elseif(preg_match("/^(?:$str|(\d+(\.\d+)?([eE]\d+)?)|true|false|null)$/",
|
||||
$src_))
|
||||
{
|
||||
// just a string or number or value
|
||||
$p += 0.1;
|
||||
}
|
||||
}
|
||||
return $p;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
* LaTeX scanner,
|
||||
* brief explanation: we're using the stateful scanner to handle marginally
|
||||
* different rulesets in math blocks.
|
||||
* We could add in an awful lot of detail, everything is pretty generic right
|
||||
* now, we don't look for any specific names or anything, but it'll suffice
|
||||
* for basic highlighting.
|
||||
*/
|
||||
class LuminousLatexScanner extends LuminousStatefulScanner {
|
||||
|
||||
function init() {
|
||||
|
||||
|
||||
// math states
|
||||
$this->add_pattern('displaymath', '/\\$\\$/', '/\\$\\$/');
|
||||
// literal '\[' and '\]'
|
||||
$this->add_pattern('displaymath', '/\\\\\\[/', '/\\\\\\]/');
|
||||
$this->add_pattern('mathmode', '/\\$/', '/\\$/');
|
||||
|
||||
// terminals
|
||||
$this->add_pattern('COMMENT', '/%.*/');
|
||||
$this->add_pattern('NUMERIC', '/\d+(\.\d+)?\w*/');
|
||||
$this->add_pattern('MATH_FUNCTION', '/\\\\(?:[a-z_]\w*|[^\]])/i');
|
||||
$this->add_pattern('MATHOP', '/[\\*^\\-=+]+/');
|
||||
|
||||
$this->add_pattern('FUNCTION', '/\\\\(?:[a-z_]\w*|.)/i');
|
||||
$this->add_pattern('IDENT', '/[a-z_]\w*/i');
|
||||
|
||||
$this->add_pattern('OPERATOR', '/[\[\]\{\}]+/');
|
||||
|
||||
$math_transition = array('NUMERIC', 'MATH_FUNCTION', 'MATHOP');
|
||||
|
||||
$this->transitions = array(
|
||||
'initial' => array('COMMENT', 'OPERATOR', 'displaymath', 'mathmode',
|
||||
'FUNCTION', 'IDENT'),
|
||||
// omitting initial state defn. makes it transition to everything
|
||||
'displaymath' => $math_transition,
|
||||
'mathmode' => $math_transition,
|
||||
);
|
||||
|
||||
$this->rule_tag_map = array(
|
||||
'displaymath' => 'INTERPOLATION',
|
||||
'mathmode' => 'INTERPOLATION',
|
||||
'MATHOP' => 'OPERATOR',
|
||||
'MATH_FUNCTION' => 'VALUE', // arbitrary way to distinguish it from non
|
||||
// math mode functions
|
||||
);
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
$p = 0.0;
|
||||
foreach(array('documentclass', 'usepackage', 'title',
|
||||
'maketitle', 'end') as $cmd)
|
||||
{
|
||||
if (strpos($src, '\\' . $cmd) !== false) $p += 0.1;
|
||||
}
|
||||
// count the number of backslashes
|
||||
$bslashes = substr_count($src, '\\');
|
||||
if ($bslashes > $info['num_lines']) {
|
||||
$p += 0.1;
|
||||
}
|
||||
if (substr_count($src, '%') > $info['num_lines']/10) {
|
||||
$p += 0.02;
|
||||
}
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
<?PHP
|
||||
|
||||
/*
|
||||
* HAI
|
||||
* I HAS PERSONAL INTEREST IN LOLCODE THATS WHY ITS HERE KTHX.
|
||||
* BTW PHP IS MOSTLY CASE INSENSITIVE
|
||||
*/
|
||||
CLASS LUMINOUSLOLCODESCANNER EXTENDS LUMINOUSSIMPLESCANNER {
|
||||
|
||||
FUNCTION FUNCDEF_OVERRIDE($MATCHES) {
|
||||
$this->RECORD($MATCHES[0], 'KEYWORD');
|
||||
$this->POS_SHIFT(STRLEN($MATCHES[0]));
|
||||
$this->skip_whitespace();
|
||||
IF ($this->SCAN('/[a-z_]\w*/i')) {
|
||||
$this->RECORD($this->MATCH(), 'USER_FUNCTION');
|
||||
$this->user_defs[$this->MATCH()] = 'FUNCTION';
|
||||
}
|
||||
}
|
||||
FUNCTION STR_FILTER($TOKEN) {
|
||||
$TOKEN = LUMINOUSUTILS::ESCAPE_TOKEN($TOKEN);
|
||||
$STR = &$TOKEN[1];
|
||||
$STR = PREG_REPLACE('/:
|
||||
(?:
|
||||
(?:[\)o":]|>)
|
||||
|\([a-fA-F0-9]*\)
|
||||
|\[[A-Z ]*\]
|
||||
|\{\w*\}
|
||||
)/x', '<VARIABLE>$0</VARIABLE>', $STR);
|
||||
|
||||
RETURN $TOKEN;
|
||||
}
|
||||
|
||||
FUNCTION INIT() {
|
||||
$this->ADD_FILTER('STRING', array($this, 'STR_FILTER'));
|
||||
$this->REMOVE_FILTER('constant');
|
||||
|
||||
$this->ADD_PATTERN('COMMENT', '/(?s:OBTW.*?TLDR)|BTW.*/');
|
||||
$this->ADD_PATTERN('STRING', '/" (?> [^":]+ | :.)* "/x');
|
||||
$this->ADD_PATTERN('STRING', "/' (?> [^':]+ | :.)* '/x");
|
||||
$this->ADD_PATTERN('OPERATOR',
|
||||
'/
|
||||
\\b
|
||||
(?:
|
||||
(?:ALL|ANY|BIGGR|BOTH|DIFF|EITHER|PRODUKT|QUOSHUNT
|
||||
|MOD|SMALLR|SUM|WON)\s+OF\\b
|
||||
|
|
||||
BOTH\s+SAEM\\b
|
||||
|
|
||||
(?:BIGGR|SMALLR)\s+THAN\\b
|
||||
|
|
||||
(?:AN|NOT)\\b
|
||||
)
|
||||
/x');
|
||||
$this->ADD_PATTERN('FUNC_DEF', '/how\s+duz\s+i\\b/i');
|
||||
$this->overrides['FUNC_DEF'] = array($this, 'FUNCDEF_OVERRIDE');
|
||||
$this->ADD_PATTERN('NUMERIC', LUMINOUSTOKENPRESETS::$NUM_REAL);
|
||||
$this->ADD_PATTERN('IDENT', '/[a-zA-Z_]\w*\\??/');
|
||||
|
||||
$this->ADD_IDENTIFIER_MAPPING('VALUE', array('FAIL', 'WIN'));
|
||||
$this->ADD_IDENTIFIER_MAPPING('TYPE', array('NOOB', 'NUMBAR', 'NUMBR',
|
||||
'TROOF', 'YARN'));
|
||||
$this->ADD_IDENTIFIER_MAPPING('KEYWORD', array('A', 'CAN',
|
||||
'DUZ', 'HAI',
|
||||
'KTHX', 'KTHXBYE', 'HAS', 'HOW', 'I', 'IM', 'IN', 'IS', 'IZ',
|
||||
'ITS', 'ITZ',
|
||||
'IF', 'FOUND', 'GTFO', 'MAEK', 'MEBBE', 'NO', 'NOW', 'O', 'OIC',
|
||||
'OMG', 'OMGWTF', 'RLY', 'RLY?', 'R', 'SAY', 'SO', 'TIL', 'YA', 'YR', 'U',
|
||||
'WAI', 'WILE', 'WTF?'));
|
||||
$this->ADD_IDENTIFIER_MAPPING('FUNCTION', array('GIMMEH', 'VISIBLE',
|
||||
'UPPIN', 'NERFIN'));
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
$p = 0.0;
|
||||
foreach(array('OMGWTF', 'I CAN HAS', 'GTFO', 'HOW DUZ I', 'IM IN YR',
|
||||
'IM IN UR', 'I HAS A', 'I HAZ A', ' UPPIN', 'NERFIN', 'TROOF', 'NUMBAR',
|
||||
'NUMBR') as $str)
|
||||
{
|
||||
if (strpos($src, " $str ") !== false) $p += 0.1;
|
||||
}
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Matlab's pretty simple. Hoorah
|
||||
*/
|
||||
|
||||
|
||||
class LuminousMATLABScanner extends LuminousSimpleScanner {
|
||||
|
||||
// Comments can nest. This beats a PCRE recursive regex, because they are
|
||||
// pretty flimsy and crash/stack overflow easily
|
||||
function comment_override($matches) {
|
||||
$this->nestable_token('COMMENT', '/%\\{/', '/%\\}/');
|
||||
}
|
||||
|
||||
function init() {
|
||||
// these can nest so we override this
|
||||
$this->add_pattern('COMMENT_ML', '/%\\{/');
|
||||
$this->add_pattern('COMMENT', '/%.*/');
|
||||
$this->add_pattern('IDENT', '/[a-z_]\w*/i');
|
||||
// stray single quotes are a unary operator when they're attached to
|
||||
// an identifier or return value, or something. so we're going to
|
||||
// use a lookbehind to exclude those
|
||||
$this->add_pattern('STRING',
|
||||
"/(?<![\w\)\]\}']) ' (?: [^']+ | '')* ($|')/x");
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_HEX);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_REAL);
|
||||
$this->add_pattern('OPERATOR', "@[¬!%^&*\-+=~;:|<>,./?]+|'@");
|
||||
|
||||
$this->overrides = array('COMMENT_ML' => array($this, 'comment_override'));
|
||||
|
||||
include(dirname(__FILE__) . '/include/matlab_func_list.php');
|
||||
$this->add_identifier_mapping('KEYWORD', $luminous_matlab_keywords);
|
||||
$this->add_identifier_mapping('VALUE', $luminous_matlab_values);
|
||||
$this->add_identifier_mapping('FUNCTION', $luminous_matlab_functions);
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
$p = 0;
|
||||
// matlab comments are quite distinctive
|
||||
if (preg_match('/%\\{.*%\\}/s', $src)) $p += 0.25;
|
||||
return $p;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,525 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Like ruby, I think it's impossible to fully tokenize Perl without
|
||||
* executing some of the code to disambiguate some symbols. As such, we're
|
||||
* going to settle for 'probably right' rather than 'definitely right'.
|
||||
*
|
||||
* TODO: I think this is mostly complete but it needs interpolation
|
||||
* highlighting in strings and heredoc, and a regex highlighting filter,
|
||||
* probably a stream filter
|
||||
*/
|
||||
|
||||
class LuminousPerlScanner extends LuminousSimpleScanner {
|
||||
|
||||
// keeps track of heredocs we need to handle
|
||||
private $heredoc = null;
|
||||
|
||||
// helper function:
|
||||
// consumes a string until the given delimiter (which may be balanced).
|
||||
// will handle nested balanced delimiters.
|
||||
// this is used as the general case for perl quote-operators like:
|
||||
// q/somestring/ q"somestring", q@somestring@, q[some[]string]
|
||||
// it can be called twice for s/someregex/somereplacement/
|
||||
// expects the initial opening delim to already have been consumed
|
||||
function consume_string($delimiter, $type) {
|
||||
$close = LuminousUtils::balance_delimiter($delimiter);
|
||||
|
||||
$balanced = $close !== $delimiter;
|
||||
$patterns = array( '/(?<!\\\\)((?:\\\\\\\\)*)('
|
||||
. preg_quote($close, '/') . ')/');
|
||||
|
||||
if ($balanced) {
|
||||
$patterns[] = '/(?<!\\\\)((?:\\\\\\\\)*)('
|
||||
. preg_quote($delimiter, '/') . ')/';
|
||||
}
|
||||
|
||||
$stack = 1; // we're already inside the string
|
||||
$start = $this->pos();
|
||||
$close_delimiter_match = null;
|
||||
while($stack) {
|
||||
$next = $this->get_next($patterns);
|
||||
if ($next[0] === -1) {
|
||||
$this->terminate();
|
||||
$finish = $this->pos();
|
||||
break;
|
||||
}
|
||||
elseif($balanced && $next[1][2] === $delimiter) {
|
||||
$stack++;
|
||||
$finish = $next[0] + strlen($next[1][0]);
|
||||
}
|
||||
elseif($next[1][2] === $close) {
|
||||
$stack--;
|
||||
if (!$stack)
|
||||
$close_delimiter_match = $next[1][2];
|
||||
$finish = $next[0] + strlen($next[1][1]);
|
||||
}
|
||||
else assert(0);
|
||||
$this->pos($next[0] + strlen($next[1][0]));
|
||||
}
|
||||
$substr = substr($this->string(), $start, $finish-$start);
|
||||
// special case for qw, the string is not a 'STRING', it is actually
|
||||
// a whitespace separated list of strings. So we need to split it and
|
||||
// record them separately
|
||||
if ($type === 'SPLIT_STRING') {
|
||||
foreach(preg_split('/(\s+)/',
|
||||
$substr, -1, PREG_SPLIT_DELIM_CAPTURE) as $token) {
|
||||
if (preg_match('/^\s/', $token)) {
|
||||
$this->record($token, null);
|
||||
} else {
|
||||
$this->record($token, 'STRING');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->record($substr, $type);
|
||||
}
|
||||
if ($close_delimiter_match !== null) {
|
||||
$this->record($close_delimiter_match, 'DELIMITER');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Helper function: guesses whether or not a slash is a regex delimiter
|
||||
// by looking behind in the token stream.
|
||||
function is_delimiter() {
|
||||
for($i = count($this->tokens) - 1; $i >= 0; $i--) {
|
||||
$t = $this->tokens[$i];
|
||||
if ($t[0] === null || $t[0] === 'COMMENT') continue;
|
||||
elseif ($t[0] === 'OPENER' || $t[0] === 'OPERATOR') return true;
|
||||
elseif ($t[0] === 'IDENT') {
|
||||
switch($t[1]) {
|
||||
// named operators
|
||||
case 'lt':
|
||||
case 'gt':
|
||||
case 'le':
|
||||
case 'ge':
|
||||
case 'eq':
|
||||
case 'ne':
|
||||
case 'cmp':
|
||||
case 'and':
|
||||
case 'or':
|
||||
case 'xor':
|
||||
// other keywords/functions
|
||||
case 'if':
|
||||
case 'elsif':
|
||||
case 'while':
|
||||
case 'unless':
|
||||
case 'split':
|
||||
case 'print':
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// override function for slashes, to disambiguate regexen from division
|
||||
// operators.
|
||||
function slash_override($matches) {
|
||||
$this->pos( $this->pos() + strlen($matches[0]) );
|
||||
// this can catch '//', which I THINK is an operator but I could be wrong.
|
||||
if (strlen($matches[0]) === 2 || !$this->is_delimiter()) {
|
||||
$this->record($matches[0], 'OPERATOR');
|
||||
} else {
|
||||
$this->record($matches[0], 'DELIMITER');
|
||||
$this->consume_string($matches[0], 'REGEX');
|
||||
if ($this->scan('/[cgimosx]+/')) {
|
||||
$this->record($this->match(), 'KEYWORD');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// override function for 'quote-like operators'
|
||||
// e.g. m"hello", m'hello', m/hello/, m(hello), m(he()l()o())
|
||||
function str_override($matches) {
|
||||
|
||||
$this->pos( $this->pos() + strlen($matches[0]) );
|
||||
|
||||
$this->record($matches[0], 'DELIMITER');
|
||||
|
||||
$f = $matches[1];
|
||||
|
||||
$type = 'STRING';
|
||||
if ($f === 'm' || $f === 'qr' || $f === 's' || $f === 'tr'
|
||||
|| $f === 'y') $type = 'REGEX';
|
||||
elseif($f === 'qw') $type = 'SPLIT_STRING';
|
||||
|
||||
$this->consume_string($matches[3], $type);
|
||||
if ($f === 's' || $f === 'tr' || $f === 'y') {
|
||||
// s/tr/y take two strings, e.g. s/something/somethingelse/, so we
|
||||
// have to consume the next delimiter (if it exists) and consume the
|
||||
// string, again.
|
||||
|
||||
// if delims were balanced, there's a new delimiter right here, e.g.
|
||||
// s[something][somethingelse]
|
||||
$this->skip_whitespace();
|
||||
$balanced = LuminousUtils::balance_delimiter($matches[3]) !== $matches[3];
|
||||
if ($balanced) {
|
||||
$delim2 = $this->scan('/[^a-zA-Z0-9]/');
|
||||
if ($delim2 !== null) {
|
||||
$this->record($delim2, 'DELIMITER');
|
||||
$this->consume_string($delim2, 'STRING');
|
||||
}
|
||||
}
|
||||
// if they weren't balanced then the delimiter is the same, and has
|
||||
// already been consumed as the end-delim to the first pattern
|
||||
else {
|
||||
$this->consume_string($matches[3], 'STRING');
|
||||
}
|
||||
}
|
||||
if ($type === 'REGEX' && $this->scan('/[cgimosxpe]+/')) {
|
||||
$this->record($this->match(), 'KEYWORD');
|
||||
}
|
||||
}
|
||||
|
||||
// this override handles the heredoc declaration, and makes a note of it
|
||||
// it adds a new token (a newline) which is overridden to invoke the real
|
||||
// heredoc handling. This is because in Perl, heredocs declarations need not
|
||||
// be the end of the line so we can't necessarily start heredocing straight
|
||||
// away.
|
||||
function heredoc_override($matches) {
|
||||
list($group, $op, $quote1, $delim, $quote2) = $matches;
|
||||
$this->record($op, 'OPERATOR');
|
||||
// Now, if $quote1 is '\', then $quote2 is empty. If quote2 is empty
|
||||
// but quote1 is not '\', this is not a heredoc.
|
||||
if ($quote1 === '\\' && $quote2 === '') {
|
||||
$this->record($quote1 . $delim, 'DELIMITER');
|
||||
} elseif($quote2 === '' && $quote1 !== '') {
|
||||
// this is the error case
|
||||
// shift to the end of the op and break
|
||||
$this->pos_shift(strlen($op));
|
||||
return;
|
||||
} else {
|
||||
$this->record($quote1 . $delim . $quote2, 'DELIMITER');
|
||||
}
|
||||
$this->pos_shift(strlen($group));
|
||||
// TODO. the quotes (matches[2] and matches[4]) are ignored for now, but
|
||||
// they mean something w.r.t interpolation.
|
||||
|
||||
$this->heredoc = $delim;
|
||||
$this->add_pattern('HEREDOC_NL', "/\n/");
|
||||
$this->overrides['HEREDOC_NL'] = array($this, 'heredoc_real_override');
|
||||
}
|
||||
// this override handles the actual heredoc text
|
||||
function heredoc_real_override($matches) {
|
||||
$this->record($matches[0], null);
|
||||
$this->pos_shift(strlen($matches[0]));
|
||||
// don't need this anymore
|
||||
$this->remove_pattern('HEREDOC_NL');
|
||||
assert($this->heredoc !== null);
|
||||
$delim = preg_quote($this->heredoc);
|
||||
$substr = $this->scan_until('/^' . $delim . '\\b/m');
|
||||
if ($substr !== null) {
|
||||
$this->record($substr, 'HEREDOC');
|
||||
$delim_ = $this->scan('/' . $delim . '/');
|
||||
assert($delim !== null);
|
||||
$this->record($delim_, 'DELIMITER');
|
||||
} else {
|
||||
$this->record($this->rest(), 'HEREDOC');
|
||||
$this->terminate();
|
||||
}
|
||||
}
|
||||
|
||||
// halts highlighting on __DATA__ and __END__
|
||||
function term_override($matches) {
|
||||
$this->record($matches[0], 'DELIMITER');
|
||||
$this->pos( $this->pos() + strlen($matches[0]) );
|
||||
$this->record($this->rest(), null);
|
||||
$this->terminate();
|
||||
}
|
||||
// pod cuts might be very long and trigger the backtrack limit, so
|
||||
// we do it the old fashioned way
|
||||
function pod_cut_override($matches) {
|
||||
$line = $this->scan('/^=.*/m');
|
||||
assert($line !== null);
|
||||
$term = '/^=cut$|\\z/m';
|
||||
$substr = $this->scan_until($term);
|
||||
assert($substr !== null);
|
||||
$end = $this->scan($term);
|
||||
assert($end !== null);
|
||||
$this->record($line . $substr . $end, 'DOCCOMMENT');
|
||||
}
|
||||
|
||||
|
||||
function init() {
|
||||
|
||||
$this->add_pattern('COMMENT', '/#.*/');
|
||||
|
||||
// pod/cut documentation
|
||||
$this->add_pattern('podcut', '/^=[a-zA-Z_]/m');
|
||||
$this->overrides['podcut'] = array($this, 'pod_cut_override');
|
||||
|
||||
// variables
|
||||
$this->add_pattern('VARIABLE', '/[\\$%@][a-z_]\w*/i');
|
||||
// special variables http://www.kichwa.com/quik_ref/spec_variables.html
|
||||
$this->add_pattern('VARIABLE', '/\\$[\|%=\-~^\d&`\'+_\.\/\\\\,"#\\$\\?\\*O\\[\\];!@]/');
|
||||
|
||||
// `backticks` (shell cmd)
|
||||
$this->add_pattern('CMD', '/`(?: [^`\\\\]++ | \\\\ . )*+ (?:`|$)/x');
|
||||
// straight strings
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$DOUBLE_STR);
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$SINGLE_STR);
|
||||
// terminators
|
||||
$this->add_pattern('TERM', '/__(?:DATA|END)__/');
|
||||
// heredoc (overriden)
|
||||
$this->add_pattern('HEREDOC', '/(<<)([\'"`\\\\]?)([a-zA-Z_]\w*)(\\2?)/');
|
||||
// operators, slash is a special case and is overridden
|
||||
$this->add_pattern('OPERATOR', '/[!%^&*\-=+;:|,\\.?<>~\\\\]+/');
|
||||
$this->add_pattern('SLASH', '%//?%');
|
||||
// we care about 'openers' for regex-vs-division disambiguatation
|
||||
$this->add_pattern('OPENER', '%[\[\{\(]+%x');
|
||||
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_HEX);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_REAL);
|
||||
|
||||
// quote-like operators. we override these.
|
||||
// I got these out of the old luminous tree, I don't know how accurate
|
||||
// or complete they are.
|
||||
// According to psh, delimiters can be escaped?
|
||||
$this->add_pattern('DELIMETERS',
|
||||
'/(q[rqxw]?|m|s|tr|y)([\s]*)(\\\\?[^a-zA-Z0-9\s])/');
|
||||
$this->add_pattern('IDENT', '/[a-zA-Z_]\w*/');
|
||||
|
||||
|
||||
$this->overrides['DELIMETERS'] = array($this, 'str_override');
|
||||
$this->overrides['SLASH'] = array($this, 'slash_override');
|
||||
$this->overrides['HEREDOC'] = array($this, 'heredoc_override');
|
||||
$this->overrides['TERM'] = array($this, 'term_override');
|
||||
|
||||
// map cmd to a 'function' and get rid of openers
|
||||
$this->rule_tag_map = array(
|
||||
'CMD' => 'FUNCTION',
|
||||
'OPENER' => null,
|
||||
);
|
||||
|
||||
// this sort of borks with the strange regex delimiters
|
||||
$this->remove_filter('pcre');
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
// data definition follows.
|
||||
|
||||
// https://www.physiol.ox.ac.uk/Computing/Online_Documentation/Perl-5.8.6/index-functions-by-cat.html
|
||||
$this->add_identifier_mapping('KEYWORD', array( 'bless',
|
||||
'caller', 'continue', 'dbmclose', 'dbmopen',
|
||||
'defined',
|
||||
'delete', 'die', 'do', 'dump', 'else', 'elsif',
|
||||
'eval', 'exit', 'for', 'foreach', 'goto', 'import', 'if', 'last', 'local',
|
||||
'my',
|
||||
'next', 'no',
|
||||
'our', 'package', 'prototype', 'redo', 'ref', 'reset',
|
||||
'return', 'require', 'scalar', 'sub', 'tie', 'tied',
|
||||
'undef',
|
||||
'utie',
|
||||
'unless', 'use', 'wantarray', 'while'));
|
||||
$this->add_identifier_mapping('OPERATOR', array('lt', 'gt', 'le',
|
||||
'ge', 'eq', 'ne', 'cmp', 'and', 'or', 'xor'));
|
||||
|
||||
$this->add_identifier_mapping('FUNCTION', array(
|
||||
'chomp',
|
||||
'chop',
|
||||
'chr',
|
||||
'crypt',
|
||||
'hex',
|
||||
'index',
|
||||
'lc',
|
||||
'lcfirst',
|
||||
'length',
|
||||
'oct',
|
||||
'ord',
|
||||
'pack',
|
||||
'reverse',
|
||||
'rindex',
|
||||
'sprintf',
|
||||
'substr',
|
||||
'uc',
|
||||
'ucfirst',
|
||||
'pos',
|
||||
'quotemeta',
|
||||
'split',
|
||||
'study',
|
||||
'abs',
|
||||
'atan2',
|
||||
'cos',
|
||||
'exp',
|
||||
'hex',
|
||||
'int',
|
||||
'log',
|
||||
'oct',
|
||||
'rand',
|
||||
'sin',
|
||||
'sqrt',
|
||||
'srand',
|
||||
'pop',
|
||||
'push',
|
||||
'shift',
|
||||
'splice',
|
||||
'unshift',
|
||||
'grep',
|
||||
'join',
|
||||
'map',
|
||||
'reverse',
|
||||
'sort',
|
||||
'unpack',
|
||||
'delete',
|
||||
'each',
|
||||
'exists',
|
||||
'keys',
|
||||
'values',
|
||||
'binmode',
|
||||
'close',
|
||||
'closedir',
|
||||
'dbmclose',
|
||||
'dbmopen',
|
||||
'die',
|
||||
'eof',
|
||||
'fileno',
|
||||
'flock',
|
||||
'format',
|
||||
'getc',
|
||||
'print',
|
||||
'printf',
|
||||
'read',
|
||||
'readdir',
|
||||
'readline',
|
||||
'rewinddir',
|
||||
'seek',
|
||||
'seekdir',
|
||||
'select',
|
||||
'syscall',
|
||||
'sysread',
|
||||
'sysseek',
|
||||
'syswrite',
|
||||
'tell',
|
||||
'telldir',
|
||||
'truncate',
|
||||
'warn',
|
||||
'write',
|
||||
'pack',
|
||||
'read',
|
||||
'syscall',
|
||||
'sysread',
|
||||
'sysseek',
|
||||
'syswrite',
|
||||
'unpack',
|
||||
'vec',
|
||||
'chdir',
|
||||
'chmod',
|
||||
'chown',
|
||||
'chroot',
|
||||
'fcntl',
|
||||
'glob',
|
||||
'ioctl',
|
||||
'link',
|
||||
'lstat',
|
||||
'mkdir',
|
||||
'open',
|
||||
'opendir',
|
||||
'readlink',
|
||||
'rename',
|
||||
'rmdir',
|
||||
'stat',
|
||||
'symlink',
|
||||
'sysopen',
|
||||
'umask',
|
||||
'unlink',
|
||||
'utime',
|
||||
'alarm',
|
||||
'exec',
|
||||
'fork',
|
||||
'getpgrp',
|
||||
'getppid',
|
||||
'getpriority',
|
||||
'kill',
|
||||
'pipe',
|
||||
'qx/STRING/',
|
||||
'readpipe',
|
||||
'setpgrp',
|
||||
'setpriority',
|
||||
'sleep',
|
||||
'system',
|
||||
'times',
|
||||
'wait',
|
||||
'waitpid',
|
||||
'accept',
|
||||
'bind',
|
||||
'connect',
|
||||
'getpeername',
|
||||
'getsockname',
|
||||
'getsockopt',
|
||||
'listen',
|
||||
'recv',
|
||||
'send',
|
||||
'setsockopt',
|
||||
'shutdown',
|
||||
'socket',
|
||||
'socketpair',
|
||||
'msgctl',
|
||||
'msgget',
|
||||
'msgrcv',
|
||||
'msgsnd',
|
||||
'semctl',
|
||||
'semget',
|
||||
'semop',
|
||||
'shmctl',
|
||||
'shmget',
|
||||
'shmread',
|
||||
'shmwrite',
|
||||
'endgrent',
|
||||
'endhostent',
|
||||
'endnetent',
|
||||
'endpwent',
|
||||
'getgrent',
|
||||
'getgrgid',
|
||||
'getgrnam',
|
||||
'getlogin',
|
||||
'getpwent',
|
||||
'getpwnam',
|
||||
'getpwuid',
|
||||
'setgrent',
|
||||
'setpwent',
|
||||
'endprotoent',
|
||||
'endservent',
|
||||
'gethostbyaddr',
|
||||
'gethostbyname',
|
||||
'gethostent',
|
||||
'getnetbyaddr',
|
||||
'getnetbyname',
|
||||
'getnetent',
|
||||
'getprotobyname',
|
||||
'getprotobynumber',
|
||||
'getprotoent',
|
||||
'getservbyname',
|
||||
'getservbyport',
|
||||
'getservent',
|
||||
'sethostent',
|
||||
'setnetent',
|
||||
'setprotoent',
|
||||
'setservent',
|
||||
'gmtime',
|
||||
'localtime',
|
||||
'time',
|
||||
'times'));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
// check the shebang
|
||||
if (preg_match('/^#!.*\\bperl\\b/', $src)) return 1.0;
|
||||
$p = 0;
|
||||
if (preg_match('/\\$[a-zA-Z_]+/', $src)) $p += 0.02;
|
||||
if (preg_match('/@[a-zA-Z_]+/', $src)) $p += 0.02;
|
||||
if (preg_match('/%[a-zA-Z_]+/', $src)) $p += 0.02;
|
||||
if (preg_match('/\\bsub\s+\w+\s*\\{/', $src)) $p += 0.1;
|
||||
if (preg_match('/\\bmy\s+[$@%]/', $src)) $p += 0.05;
|
||||
// $x =~ s/
|
||||
if (preg_match('/\\$[a-zA-Z_]\w*\s+=~\s+s\W/', $src)) $p += 0.15;
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
<?php
|
||||
|
||||
require_once( dirname(__FILE__) . '/include/php_func_list.php');
|
||||
|
||||
/*
|
||||
* This is not a scanner called by an external interface, it's controlled
|
||||
* by LuminousPHPScanner (defined in this file).
|
||||
*
|
||||
* It should break when it sees a '?>', but it should assume it's in php
|
||||
* when it's called.
|
||||
*/
|
||||
class LuminousPHPSubScanner extends LuminousScanner {
|
||||
|
||||
protected $case_sensitive = false;
|
||||
public $snippet = false;
|
||||
|
||||
function init() {
|
||||
$this->add_pattern('TERM', '/\\?>/');
|
||||
$this->add_pattern('COMMENT', '% (?://|\#) .*? (?=\\?>|$) %xm');
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_ML);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_HEX);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_REAL);
|
||||
// this should be picked up by the LuminousPHPScanner, but in case
|
||||
// a user incorrectly calls the PHP-snippet scanner, we detect it.
|
||||
$this->add_pattern('DELIMITER', '/<\?(?:php)?/');
|
||||
$this->add_pattern('OPERATOR', '@[!%^&*\\-=+~:<>/\\|\\.;,]+|\\?(?!>)@');
|
||||
$this->add_pattern('VARIABLE', '/\\$\\$?[a-zA-Z_]\w*/');
|
||||
$this->add_pattern('IDENT', '/[a-zA-Z_]\w*/');
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$DOUBLE_STR);
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$SINGLE_STR);
|
||||
$this->add_pattern('FUNCTION', '/`(?>[^`\\\\]+|\\\\.)*(`|$)/s');
|
||||
$this->add_identifier_mapping('FUNCTION', $GLOBALS['luminous_php_functions']);
|
||||
$this->add_identifier_mapping('KEYWORD', $GLOBALS['luminous_php_keywords']);
|
||||
|
||||
$this->add_filter('STRING', array($this, 'str_filter'));
|
||||
$this->add_filter('HEREDOC', array($this, 'str_filter'));
|
||||
$this->add_filter('NOWDOC', array($this, 'nowdoc_filter'));
|
||||
}
|
||||
|
||||
static function str_filter($token) {
|
||||
if ($token[1][0] !== '"' && $token[0] !== 'HEREDOC') return $token;
|
||||
elseif(strpos($token[1], '$') === false) return $token;
|
||||
|
||||
$token = LuminousUtils::escape_token($token);
|
||||
// matches $var, ${var} and {$var} syntax
|
||||
$token[1] = preg_replace('/
|
||||
(?: \$\{ | \{\$ ) [^}]++ \}
|
||||
|
|
||||
\$\$?[a-zA-Z_]\w*
|
||||
/x', '<VARIABLE>$0</VARIABLE>',
|
||||
$token[1]);
|
||||
return $token;
|
||||
}
|
||||
|
||||
static function nowdoc_filter($token) {
|
||||
$token[0] = 'HEREDOC';
|
||||
return $token;
|
||||
}
|
||||
|
||||
function main() {
|
||||
$this->start();
|
||||
while (!$this->eos()) {
|
||||
$tok = null;
|
||||
|
||||
$index = $this->pos();
|
||||
|
||||
if (($match = $this->next_match()) !== null) {
|
||||
$tok = $match[0];
|
||||
if ($match[1] > $index) {
|
||||
$this->record(substr($this->string(), $index, $match[1] - $index), null);
|
||||
}
|
||||
} else {
|
||||
$this->record($this->rest(), null);
|
||||
$this->terminate();
|
||||
break;
|
||||
}
|
||||
|
||||
if ($tok === 'TERM') {
|
||||
$this->unscan();
|
||||
break;
|
||||
}
|
||||
|
||||
if($tok === 'IDENT') {
|
||||
// do the user defns here, i.e. class XYZ extends/implements ABC
|
||||
// or function XYZ
|
||||
$m = $this->match();
|
||||
$this->record($m, 'IDENT');
|
||||
if (($m === 'class' || $m === 'function' || $m === 'extends' || $m === 'implements')
|
||||
&& $this->scan('/(\s+)([a-zA-Z_]\w*)/') )
|
||||
{
|
||||
$this->record($this->match_group(1), null);
|
||||
$this->record($this->match_group(2), 'USER_FUNCTION');
|
||||
$this->user_defs[$this->match_group(2)] = ($m === 'function')? 'FUNCTION'
|
||||
: 'TYPE';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
elseif($tok === 'OPERATOR') {
|
||||
// figure out heredoc syntax here
|
||||
if (strpos($this->match(), '<<<') !== false) {
|
||||
$this->record($this->match(), $tok);
|
||||
$this->scan('/([\'"]?)([\w]*)((?:\\1)?)/');
|
||||
$g = $this->match_groups();
|
||||
$nowdoc = false;
|
||||
if ($g[1]) {
|
||||
// nowdocs are delimited by single quotes. Heredocs MAY be
|
||||
// delimited by double quotes, or not.
|
||||
$nowdoc = $g[1] === "'";
|
||||
$this->record($g[1], null);
|
||||
}
|
||||
$delimiter = $g[2];
|
||||
$this->record($delimiter, 'KEYWORD');
|
||||
if ($g[3]) $this->record($g[3], null);
|
||||
// bump us to the end of the line
|
||||
if (strlen($this->scan('/.*/')))
|
||||
$this->record($this->match(), null);
|
||||
if ($this->scan_until("/^$delimiter|\z/m")) {
|
||||
$this->record($this->match(), ($nowdoc)? 'NOWDOC' : 'HEREDOC');
|
||||
if ($this->scan('/\w+/'))
|
||||
$this->record($this->match(), 'KEYWORD');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
assert($this->pos() > $index);
|
||||
$this->record($this->match(), $tok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This is a controller class which handles alternating between PHP and some
|
||||
* other language (currently HTML only, TODO allow plain text as well)
|
||||
* PHP and the other language are handled by subscanners
|
||||
*/
|
||||
class LuminousPHPScanner extends LuminousScanner {
|
||||
|
||||
/// the 'non-php' scanner
|
||||
protected $subscanner;
|
||||
/// the real php scanner
|
||||
protected $php_scanner;
|
||||
|
||||
/// If it's a snippet, we assume we're starting in PHP mode.
|
||||
public $snippet = false;
|
||||
|
||||
|
||||
function __construct($src=null) {
|
||||
$this->subscanner = new LuminousHTMLScanner($src);
|
||||
$this->subscanner->embedded_server = true;
|
||||
$this->subscanner->init();
|
||||
|
||||
$this->php_scanner = new LuminousPHPSubScanner($src);
|
||||
$this->php_scanner->init();
|
||||
parent::__construct($src);
|
||||
}
|
||||
|
||||
function string($s=null) {
|
||||
if ($s !== null) {
|
||||
$this->subscanner->string($s);
|
||||
$this->php_scanner->string($s);
|
||||
}
|
||||
return parent::string($s);
|
||||
}
|
||||
|
||||
protected function scan_php($delimiter) {
|
||||
if ($delimiter !== null)
|
||||
$this->record($delimiter, 'DELIMITER');
|
||||
$this->php_scanner->pos($this->pos());
|
||||
$this->php_scanner->main();
|
||||
$this->record($this->php_scanner->tagged(),
|
||||
($delimiter === '<?=')? 'INTERPOLATION' : null, true);
|
||||
|
||||
$this->pos($this->php_scanner->pos());
|
||||
assert($this->eos() || $this->check('/\\?>/'));
|
||||
if ($this->scan('/\\?>/'))
|
||||
$this->record($this->match(), 'DELIMITER');
|
||||
}
|
||||
|
||||
protected function scan_child() {
|
||||
$this->subscanner->pos($this->pos());
|
||||
$this->subscanner->main();
|
||||
$this->pos($this->subscanner->pos());
|
||||
assert($this->eos() || $this->check('/<\\?/'));
|
||||
$this->record($this->subscanner->tagged(), null, true);
|
||||
}
|
||||
|
||||
function main() {
|
||||
while (!$this->eos()) {
|
||||
$p = $this->pos();
|
||||
if ($this->snippet)
|
||||
$this->scan_php(null);
|
||||
elseif ($this->scan('/<\\?(?:php|=)?/'))
|
||||
$this->scan_php($this->match());
|
||||
else
|
||||
$this->scan_child();
|
||||
assert($this->pos() > $p);
|
||||
}
|
||||
}
|
||||
|
||||
static function guess_language($src, $info) {
|
||||
// cache p because this function is hit by the snippet scanner as well
|
||||
static $p = 0.0;
|
||||
static $src_ = null;
|
||||
if ($src_ === $src) {
|
||||
return $p;
|
||||
}
|
||||
// look for delimiter tags
|
||||
if (strpos($src, '<?php') !== false) $p += 0.5;
|
||||
elseif (preg_match('/<\\?(?!xml)/', $src)) $p += 0.20;
|
||||
// check for $this, self:: parent::
|
||||
if (preg_match('/\\$this\\b|((?i: self|parent)::)/x', $src)) $p += 0.15;
|
||||
// check for PHP's OO notation: $somevar->something
|
||||
if (preg_match('/\\$[a-z_]\w*+->[a-z_]/i', $src)) $p += 0.05;
|
||||
// check for some common functions:
|
||||
if (preg_match('/\\b(echo|require(_once)?|include(_once)?|preg_\w)/i',
|
||||
$src)) $p += 0.05;
|
||||
$src_ = $src;
|
||||
return $p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class LuminousPHPSnippetScanner extends LuminousPHPScanner {
|
||||
public $snippet = true;
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
$p = parent::guess_language($src, $info);
|
||||
if ($p > 0.0) {
|
||||
// look for the close/open tags, if there is no open tag, or if
|
||||
// there is a close tag before an open tag, then we guess we're
|
||||
// in a snippet
|
||||
// if we are in a snippet we need to come out ahead of php, and
|
||||
// if we're not then we need to be behind it.
|
||||
$open_tag = strpos($src, '<?');
|
||||
$close_tag = strpos($src, '?>');
|
||||
if ($open_tag === false ||
|
||||
($close_tag !== false && $close_tag < $open_tag))
|
||||
{
|
||||
$p += 0.01;
|
||||
}
|
||||
else $p -= 0.01;
|
||||
}
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,412 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
* Python scanner - includes Django
|
||||
*
|
||||
* TODO: Django does not respect {% comment %} ... {% endcomment %}
|
||||
*/
|
||||
class LuminousPythonScanner extends LuminousScanner {
|
||||
|
||||
public $django = false;
|
||||
|
||||
public function init() {
|
||||
|
||||
$this->remove_filter('comment-to-doc');
|
||||
|
||||
// so it turns out this template isn't quite as readable as I hoped, but
|
||||
// it's a triple string, e.g:
|
||||
// "{3} (?: [^"\\]+ | ""[^"\\]+ | "[^"\\]+ | \\.)* (?: "{3}|$)
|
||||
|
||||
|
||||
$triple_str_template = '%1$s{3} (?> [^%1$s\\\\]+ | %1$s%1$s[^%1$s\\\\]+ | %1$s[^%1$s\\\\]+ | \\\\. )* (?: %1$s{3}|$)';
|
||||
$str_template = '%1$s (?> [^%1$s\\\\]+ | \\\\. )* (?: %1$s|$)';
|
||||
$triple_dstr = sprintf($triple_str_template, '"');
|
||||
$triple_sstr = sprintf($triple_str_template, "'");
|
||||
|
||||
$this->add_pattern('IDENT', '/[a-zA-Z_](?>\w*)(?!["\'])/');
|
||||
// I *assume* that Django tags terminate these
|
||||
$this->add_pattern('COMMENT', sprintf('/\#.*%s/',
|
||||
$this->django? '(?=[%}]\})' : ''));
|
||||
|
||||
|
||||
// decorator
|
||||
$this->add_pattern('TYPE', '/@(\w+\.?)+/');
|
||||
|
||||
// Python strings may be prefixed with r (raw) or u (unicode).
|
||||
// This affects how it handles backslashes, but I don't *think* it
|
||||
// affects escaping of quotes....
|
||||
$this->add_pattern('STRING', "/[RUru]?$triple_dstr/xs");
|
||||
$this->add_pattern('STRING', "/[RUru]?$triple_sstr/xs");
|
||||
$this->add_pattern('STRING', "/[RUru]?" . sprintf($str_template, '"') . '/sx');
|
||||
$this->add_pattern('STRING', "/[RUru]?" . sprintf($str_template, "'") . '/xs');
|
||||
|
||||
// EPIC.
|
||||
$this->add_pattern('NUMERIC', '/
|
||||
#hex
|
||||
(?:0[xX](?>[0-9A-Fa-f]+)[lL]*)
|
||||
|
|
||||
# binary
|
||||
(?:0[bB][0-1]+)
|
||||
|
|
||||
#octal
|
||||
(?:0[oO0][0-7]+)
|
||||
|
|
||||
# regular number
|
||||
(?:
|
||||
(?>[0-9]+)
|
||||
(?:
|
||||
# long identifier
|
||||
[lL]
|
||||
|
|
||||
# Or a fractional part, which may be imaginary
|
||||
(?:
|
||||
(?:\.?(?>[0-9]+)?
|
||||
(?:(?:[eE][\+\-]?)?(?>[0-9]+))?
|
||||
)[jJ]?
|
||||
)
|
||||
)?
|
||||
)
|
||||
|
|
||||
(
|
||||
# or only after the point, float x = .1;
|
||||
\.(?>[0-9]+)(?:(?:[eE][\+\-]?)?(?>[0-9]+))?[jJ]?
|
||||
)
|
||||
/x');
|
||||
|
||||
// %} and }} are django terminators
|
||||
if ($this->django) {
|
||||
$this->add_pattern('TERM', '/[%}]\}/');
|
||||
}
|
||||
|
||||
// catch the colon separately so we can use $match === ':' in figuring out
|
||||
// where docstrs occur
|
||||
$this->add_pattern('OPERATOR', '/\+=|-=|\*=|\/=|>=|<=|!=|==|\*\*|[!%^*\-=+;<>\\\\(){}\[\],\\.:]/');
|
||||
|
||||
if ($this->django) {
|
||||
// Django specific keywords
|
||||
// https://docs.djangoproject.com/en/1.3/ref/templates/builtins/
|
||||
$this->add_identifier_mapping('KEYWORD', array('autoescape',
|
||||
'endautoescape', 'cycle', 'filter', 'endfilter', 'include',
|
||||
'extends', 'firstof', 'empty', 'ifchanged', 'endifchanged',
|
||||
'ifequal', 'endifequal', 'ifnotequal', 'endifnotequal',
|
||||
'load', 'now', 'regroup', 'spaceless', 'endspaceless',
|
||||
'ssi', 'url', 'widthratio', 'endwith',
|
||||
'endfor', 'endif',
|
||||
'endwhile'));
|
||||
}
|
||||
|
||||
$this->add_identifier_mapping('KEYWORD', array('assert', 'as', 'break',
|
||||
'class', 'continue', 'del', 'def', 'elif', 'else', 'except', 'exec',
|
||||
'finally', 'for', 'from', 'global', 'if', 'import', 'lambda',
|
||||
'print', 'pass', 'raise', 'return', 'try', 'while', 'yield',
|
||||
'with',
|
||||
'and', 'not', 'in', 'is', 'or', 'print'));
|
||||
|
||||
$this->add_identifier_mapping('FUNCTION', array('all', 'abs', 'any',
|
||||
'basestring', 'bin', 'callable', 'chr', 'classmethod', 'cmp', 'compile',
|
||||
'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'file', 'filter',
|
||||
'format',
|
||||
'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex',
|
||||
'id', 'input', 'isinstance', 'issubclass', 'iter', 'len', 'locals', 'map',
|
||||
'max', 'min', 'memoryview', 'next', 'object', 'oct', 'open', 'ord', 'pow',
|
||||
'property', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed',
|
||||
'round', 'setattr', 'slice', 'sorted', 'staticmethod', 'sum', 'super',
|
||||
'type', 'unichr', 'vars', 'xrange', 'zip', '__import__',
|
||||
|
||||
'bytearray', 'complex', 'dict', 'float', 'int', 'list', 'long',
|
||||
'set', 'str', 'tuple', 'unicode', 'apply', 'buffer', 'coerce', 'intern'
|
||||
));
|
||||
|
||||
// http://docs.python.org/library/exceptions.html
|
||||
$this->add_identifier_mapping('TYPE',
|
||||
array('BaseException', 'SystemExit',
|
||||
'KeyboardInterrupt', 'GeneratorExit', 'Exception', 'StopIteration',
|
||||
'StandardError', 'BufferError', 'ArithmeticError',
|
||||
'FloatingPointError', 'OverflowError', 'ZeroDivisionError',
|
||||
'AssertionError',
|
||||
'AttributeError', 'EnvironmentError', 'IOError', 'OSError',
|
||||
'WindowsError(Windows)', 'VMSError(VMS)', 'EOFError', 'ImportError',
|
||||
'LookupError', 'IndexError', 'KeyError', 'MemoryError', 'NameError',
|
||||
'UnboundLocalError', 'ReferenceError', 'RuntimeError',
|
||||
'NotImplementedError',
|
||||
'SyntaxError', 'IndentationError', 'TabError', 'SystemError', 'TypeError',
|
||||
'ValueError', 'UnicodeError', 'UnicodeDecodeError', 'UnicodeEncodeError',
|
||||
'UnicodeTranslateError', 'Warning', 'DeprecationWarning',
|
||||
'PendingDeprecationWarning', 'RuntimeWarning', 'SyntaxWarning',
|
||||
'UserWarning',
|
||||
'FutureWarning', 'ImportWarning', 'UnicodeWarning', 'BytesWarning'));
|
||||
|
||||
$this->add_identifier_mapping('VALUE', array('False', 'None', 'self',
|
||||
'True'));
|
||||
}
|
||||
|
||||
|
||||
// mini-scanner to handle highlighting module names in import lines
|
||||
private function import_line() {
|
||||
$import = false;
|
||||
$from = false;
|
||||
while(!$this->eol()) {
|
||||
$c = $this->peek();
|
||||
$tok = null;
|
||||
$m = null;
|
||||
|
||||
if ($c === '\\') $m = $this->get(2);
|
||||
elseif($this->scan('/[,\\.;\\*]+/')) $tok = 'OPERATOR';
|
||||
elseif($this->scan("/[ \t]+/")){}
|
||||
elseif(($m = $this->scan('/import\\b|from\\b/'))){
|
||||
if ($m === 'import') $import = true;
|
||||
elseif($m === 'from') $from = true;
|
||||
else assert(0);
|
||||
$tok = 'IDENT';
|
||||
}
|
||||
elseif($this->scan('/[_a-zA-Z]\w*/')) {
|
||||
assert($from || $import);
|
||||
// from module import *item*, or just import *item*
|
||||
if ($import) {
|
||||
$tok = 'USER_FUNCTION';
|
||||
$this->user_defs[$this->match()] = 'TYPE';
|
||||
}
|
||||
// from *module* ...[import item], the module is not imported
|
||||
else $tok = 'IDENT';
|
||||
}
|
||||
else break;
|
||||
$this->record(($m !== null)? $m : $this->match(), $tok);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function main() {
|
||||
$definition = false;
|
||||
$doccstr = false;
|
||||
$expect = '';
|
||||
while (!$this->eos()) {
|
||||
$tok = null;
|
||||
$index = $this->pos();
|
||||
|
||||
if (($rule = $this->next_match()) !== null) {
|
||||
$tok = $rule[0];
|
||||
if ($rule[1] > $index) {
|
||||
$this->record(substr($this->string(), $index, $rule[1] - $index), null);
|
||||
}
|
||||
} else {
|
||||
$this->record(substr($this->string(), $index), null);
|
||||
$this->terminate();
|
||||
break;
|
||||
}
|
||||
// Django terminator tag - break to superscanner
|
||||
if ($tok === 'TERM') {
|
||||
$this->unscan();
|
||||
break;
|
||||
}
|
||||
|
||||
$m = $this->match();
|
||||
|
||||
/* python doc strs are a pain because they're actually just strings.
|
||||
* Also, I'm pretty sure a string in a non-interesting place just counts
|
||||
* as a no-op and is also used as a comment sometimes
|
||||
* So we've got something a bit complicated going on here: if we meet
|
||||
* a 'class' or a 'def' (function def) then we wait until the next ':'
|
||||
* and say "we expect a doc-str now". If the next token is not a string,
|
||||
* we discard that state.
|
||||
*
|
||||
* similarly, if we meet a string which isn't a doc-str, we look behind
|
||||
* and expect to see an operator or open bracket, else it's a comment.
|
||||
* NOTE: we class ':' as a legal string preceding char because it's used
|
||||
* as dictionary key:value separators. This will fail on the case:
|
||||
*
|
||||
* while 1:
|
||||
* "do something"
|
||||
* break
|
||||
*
|
||||
*
|
||||
* NOTE: note we're skipping whitespace.
|
||||
* NOTE: we disable the no-op detection for Django because the string
|
||||
* might be inside an output tag.
|
||||
*
|
||||
*/
|
||||
|
||||
if ($definition && $doccstr) {
|
||||
if($tok === 'STRING')
|
||||
$tok = 'COMMENT';
|
||||
}
|
||||
|
||||
elseif ($tok === 'STRING' && !$this->django) {
|
||||
$i = count($this->tokens);
|
||||
$tok = 'COMMENT';
|
||||
while ($i--) {
|
||||
$t = $this->tokens[$i][0];
|
||||
$s = $this->tokens[$i][1];
|
||||
if ($t === null || $t === 'COMMENT') continue;
|
||||
elseif ($t === 'OPERATOR' || $t === 'IDENT' || $t === 'NUMERIC') {
|
||||
$tok = 'STRING';
|
||||
}
|
||||
break;
|
||||
}
|
||||
// finally, if we can look ahead to a binary operator, or so,
|
||||
// we concede it probably is a string
|
||||
if ($tok === 'COMMENT') {
|
||||
if ($this->check('/\s*(?: [+:&.,] | (?:and|or|is|not)\\b)/x'))
|
||||
$tok = 'STRING';
|
||||
}
|
||||
}
|
||||
|
||||
// reset this; if it didn't catch above then it's not valid now.
|
||||
if ($definition && $doccstr) {
|
||||
$definition = false;
|
||||
$doccstr = false;
|
||||
}
|
||||
|
||||
if ($tok === 'IDENT') {
|
||||
if ($m === 'import' || $m === 'from') {
|
||||
$this->unscan();
|
||||
$this->import_line();
|
||||
continue;
|
||||
}
|
||||
// these are definition keywords, the next token should be an
|
||||
// identifier, which is a user-defined type or function
|
||||
if ($m === 'class' || $m === 'def') {
|
||||
$definition = true;
|
||||
$expect = 'user_def';
|
||||
}
|
||||
// this is caught on the next iteration
|
||||
elseif($expect === 'user_def') {
|
||||
$tok = 'USER_FUNCTION';
|
||||
$expect = false;
|
||||
$this->user_defs[$m] = 'FUNCTION';
|
||||
}
|
||||
}
|
||||
else {
|
||||
// if this hasn't caught, it's not valid
|
||||
$expect = false;
|
||||
}
|
||||
|
||||
if ($definition && $m === ':') {
|
||||
$doccstr = true;
|
||||
}
|
||||
|
||||
$this->record($m, $tok);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
if (strpos($info['shebang'], 'python') !== false) return 1.0;
|
||||
if ($info['shebang']) return 0.0;
|
||||
$p = 0.0;
|
||||
// let's look for some trademark pythonic constructs, although I
|
||||
// have a feeling that recent versions of ECMA also impelment some
|
||||
// of this
|
||||
if (preg_match('/^\s*+ for \s++ \w++ \s++ in \s++ \w++ \s*+ :/xm', $src))
|
||||
$p += 0.05;
|
||||
if (preg_match('/True|False|None/', $src)) $p += 0.01;
|
||||
if (preg_match('/"{3}|\'{3}/', $src)) $p += 0.05;
|
||||
// class something(object)
|
||||
//
|
||||
if (preg_match('/^\s*+ class \s++ \w++ \s*+ \( \s*+ object \s*+ \)/xm',
|
||||
$src)) $p += 0.1;
|
||||
// def __init__ (constructor)
|
||||
if (preg_match('/\\bdef \s++ __init__\\b/x', $src)) $p += 0.2;
|
||||
// method decorators
|
||||
if (preg_match("/^\s*+ @[\w\\.]++ .*+ [\n\r]++ \s*+ def\\b/mx", $src))
|
||||
$p += 0.1;
|
||||
// pmax = 0.41
|
||||
|
||||
// common imports: import os|sys|re
|
||||
if (preg_match('/^import\s++(os|sys|re)\\b/m', $src))
|
||||
$p += 0.05;
|
||||
// from x import y
|
||||
if (preg_match('/^\s*+ from \s++ (?:\w++(?:\.\w++)*+) \s++ import \s/xm',
|
||||
$src))
|
||||
$p += 0.10;
|
||||
|
||||
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class LuminousDjangoScanner extends LuminousScanner {
|
||||
// warning: some copying and pasting with the rails scanner here
|
||||
|
||||
// HTML scanner has to be persistent.
|
||||
private $html_scanner;
|
||||
|
||||
public function init() {
|
||||
$this->html_scanner = new LuminousHTMLScanner();
|
||||
$this->html_scanner->string($this->string());
|
||||
$this->html_scanner->embedded_server = true;
|
||||
$this->html_scanner->server_tags = '/\{[{%#]/';
|
||||
$this->html_scanner->init();
|
||||
}
|
||||
|
||||
public function scan_html() {
|
||||
$this->html_scanner->pos($this->pos());
|
||||
$this->html_scanner->main();
|
||||
$this->record($this->html_scanner->tagged(), null, true);
|
||||
$this->pos($this->html_scanner->pos());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function scan_python($short=false) {
|
||||
$python_scanner = new LuminousPythonScanner($this->string());
|
||||
$python_scanner->django = true;
|
||||
$python_scanner->init();
|
||||
$python_scanner->pos($this->pos());
|
||||
$python_scanner->main();
|
||||
$this->record($python_scanner->tagged(), $short? 'INTERPOLATION' : null, true);
|
||||
$this->pos($python_scanner->pos());
|
||||
}
|
||||
|
||||
|
||||
public function main() {
|
||||
while(!$this->eos()) {
|
||||
$p = $this->pos();
|
||||
// django's tags are {{ }} and {% %}
|
||||
// there's also a {# #} comment tag but we can probably handle that here
|
||||
// more easily
|
||||
// same for {% comment %} ... {% endcomment %}
|
||||
if ($this->scan('/\{([{%])/')) {
|
||||
$match = $this->match();
|
||||
$m1 = $this->match_group(1);
|
||||
// {% comment %} ... {% endcomment %}
|
||||
if ($this->scan('/\s*comment\s*%\}/')) {
|
||||
$match .= $this->match();
|
||||
$end_pattern = '/\{%\s*endcomment\s*%\}/';
|
||||
if ($this->scan_until($end_pattern) !== null) {
|
||||
$match .= $this->match();
|
||||
$match .= $this->scan($end_pattern);
|
||||
}
|
||||
else {
|
||||
$match .= $this->rest();
|
||||
$this->terminate();
|
||||
}
|
||||
$this->record($match, 'COMMENT');
|
||||
}
|
||||
// {{ ... }} or {% ... %}
|
||||
else {
|
||||
$this->record($match, 'DELIMITER');
|
||||
$this->scan_python($m1 === '{');
|
||||
if ($this->scan('/[}%]\}/')) {
|
||||
$this->record($this->match(), 'DELIMITER');
|
||||
}
|
||||
}
|
||||
// {# ... #}
|
||||
} elseif($this->scan('/\{\# (?: [^\#]++ | \#(?! \} ) )*+ (?: \#\} | $)/x')) {
|
||||
$this->record($this->match(), 'COMMENT');
|
||||
}
|
||||
else {
|
||||
$this->scan_html();
|
||||
}
|
||||
assert($p < $this->pos());
|
||||
}
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
if (($html = LuminousHTMLScanner::guess_language($src, $info)) >= 0.2) {
|
||||
if (strpos($src, '{{') !== false || strpos($src, '{%') !== false)
|
||||
return $html + 0.01;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
* Rails. Basically a wrapper around Ruby and HTML.
|
||||
*/
|
||||
|
||||
class LuminousRailsScanner extends LuminousScanner {
|
||||
|
||||
|
||||
// HTML scanner has to be persistent. Ruby doesn't.
|
||||
private $html_scanner;
|
||||
|
||||
public function init() {
|
||||
$this->html_scanner = new LuminousHTMLScanner();
|
||||
$this->html_scanner->string($this->string());
|
||||
$this->html_scanner->embedded_server = true;
|
||||
$this->html_scanner->server_tags = '/<%/';
|
||||
$this->html_scanner->init();
|
||||
}
|
||||
|
||||
public function scan_html() {
|
||||
$this->html_scanner->pos($this->pos());
|
||||
$this->html_scanner->main();
|
||||
$this->record($this->html_scanner->tagged(), null, true);
|
||||
$this->pos($this->html_scanner->pos());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function scan_ruby($short=false) {
|
||||
$ruby_scanner = new LuminousRubyScanner($this->string());
|
||||
$ruby_scanner->rails = true;
|
||||
$ruby_scanner->init();
|
||||
$ruby_scanner->pos($this->pos());
|
||||
$ruby_scanner->main();
|
||||
$this->record($ruby_scanner->tagged(), $short? 'INTERPOLATION' : null, true);
|
||||
$this->pos($ruby_scanner->pos());
|
||||
}
|
||||
|
||||
|
||||
public function main() {
|
||||
while(!$this->eos()) {
|
||||
$p = $this->pos();
|
||||
if ($this->scan('/<%#?([\-=]?)/')) {
|
||||
$this->record($this->match(), 'DELIMITER');
|
||||
$this->scan_ruby($this->match_group(1) === '=');
|
||||
if ($this->scan('/-?%>/')) {
|
||||
$this->record($this->match(), 'DELIMITER');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->scan_html();
|
||||
}
|
||||
assert($p < $this->pos());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
$p = LuminousRubyScanner::guess_language($src, $info);
|
||||
if ($p > 0) {
|
||||
if (preg_match('/<%.*%>/', $src)) $p += 0.02;
|
||||
else $p = 0.0;
|
||||
$p = min($p, 1);
|
||||
}
|
||||
return $p;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,522 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Ruby's grammar is basically insane. We're not going to aim to correctly
|
||||
* highlight all legal Ruby code because we'll be here all year and we'll still
|
||||
* get it wrong, but we're going to have a go at getting the standard stuff
|
||||
* right as well as:
|
||||
* heredocs
|
||||
* balanced AND NESTED string/regex delimiters
|
||||
* interpolation
|
||||
*
|
||||
* disclaimer: I don't actually know Ruby.
|
||||
*
|
||||
* Problem is that Ruby *appears* to have to disambiguate loads of stuff at
|
||||
* runtime, which is frankly a little optimistic for a syntax highlighter.
|
||||
* Ruby allows you to omit calling parantheses, so it's not practical (and
|
||||
* impossible if the code snippet is incomplete) to figure out operator/operand
|
||||
* position. e.g.
|
||||
* x = y %r/z/x
|
||||
* is x = y mod r div z div x, unless y is a function, in which case it's:
|
||||
* x = y( /z/x ) where /z/x is a regex
|
||||
*/
|
||||
|
||||
|
||||
class LuminousRubyScanner extends LuminousScanner {
|
||||
|
||||
|
||||
// set to true if this is a nested scanner which needs to exit if it
|
||||
// encounters a } while nothing else is on the stack, i.e. it is being
|
||||
// used to process an interpolated block
|
||||
public $interpolation = false;
|
||||
protected $curley_braces = 0; // poor man's curly brace stack.
|
||||
|
||||
public $rails = false;
|
||||
|
||||
// operators depend somewhat on whether or not rails is active, else we
|
||||
// don't want to consume a '%' if it comes right before a '>', we want
|
||||
// to leave that for the rails close-tag detection
|
||||
private $operator_regex = null;
|
||||
private $string_regex = null;
|
||||
private $comment_regex = null;
|
||||
|
||||
// gaaah
|
||||
private $numeric = '/
|
||||
(?:
|
||||
#control codes
|
||||
(?:\?(?:\\\[[:alpha:]]-)*[[:alpha:]])
|
||||
|
|
||||
#hex
|
||||
(?:0[xX](?>[0-9A-Fa-f]+)[lL]*)
|
||||
|
|
||||
# binary
|
||||
(?:0[bB][0-1]+)
|
||||
|
|
||||
#octal
|
||||
(?:0[oO0][0-7]+)
|
||||
|
|
||||
# regular number
|
||||
(?:
|
||||
(?>[0-9]+)
|
||||
(?:
|
||||
# fraction
|
||||
(?:
|
||||
(?:\.?(?>[0-9]+)?
|
||||
(?:(?:[eE][\+\-]?)?(?>[0-9]+))?
|
||||
)
|
||||
)
|
||||
)?
|
||||
)
|
||||
|
|
||||
(
|
||||
# or only after the point, float x = .1;
|
||||
\.(?>[0-9]+)(?:(?:[eE][\+\-]?)?(?>[0-9]+))?
|
||||
)
|
||||
)
|
||||
(?:_+\d+)*
|
||||
/x';
|
||||
|
||||
/// queue of heredoc declarations which will need to be handled as soon as EOL is reached
|
||||
/// each element is a tuple: (delimiter(str), identable?, interpolatable?)
|
||||
private $heredocs = array();
|
||||
|
||||
|
||||
public function init() {
|
||||
$this->comment_regex =
|
||||
$this->rails? "/ \# (?: [^\n%]*+ | %(?!>))* /x"
|
||||
: '/#.*/';
|
||||
// http://www.zenspider.com/Languages/Ruby/QuickRef.html#23
|
||||
$this->operator_regex = '/
|
||||
\? | ;
|
||||
| ::? | \*[=\*]? | \/=? | -=? | %=? | ^=? | &&? | \|\|? | \.{2,3}
|
||||
| \^=?
|
||||
| < (?:=>|<|=)? | >=?
|
||||
| =[>~] | ={1,3}
|
||||
| \+=? | ![=~]?
|
||||
/x';
|
||||
// $this->operator_regex = '/(?: [~!^&*\-+=:;|<>\/?';
|
||||
// if ($this->rails) $this->operator_regex .= ']+|%(?!>))+';
|
||||
// else $this->operator_regex .= '%]+)';
|
||||
// $this->operator_regex .= '/x';
|
||||
|
||||
$this->add_identifier_mapping('KEYWORD', array('BEGIN', 'END', 'alias',
|
||||
'begin', 'break', 'case', 'class', 'def', 'defined?', 'do',
|
||||
'else', 'elsif', 'end', 'ensure', 'for', 'if', 'module', 'next',
|
||||
'redo', 'rescue', 'retry', 'return', 'self', 'super', 'then',
|
||||
'undef', 'unless', 'until', 'when', 'while', 'yield',
|
||||
'false', 'nil', 'self', 'true', '__FILE__', '__LINE__', 'TRUE', 'FALSE',
|
||||
'NIL', 'STDIN', 'STDERR', 'ENV', 'ARGF', 'ARGV', 'DATA', 'RUBY_VERSION',
|
||||
'RUBY_RELEASE_DATE', 'RUBY_PLATFORM',
|
||||
'and', 'in', 'not', 'or',
|
||||
'public', 'private', 'protected'
|
||||
));
|
||||
|
||||
// http://www.tutorialspoint.com/ruby/ruby_builtin_functions.htm
|
||||
// don't know how reliable that is... doesn't look incredibly inspiring
|
||||
$this->add_identifier_mapping('FUNCTION', array('abord', 'Array',
|
||||
'at_exit', 'autoload', 'binding', 'block_given?', 'callcc', 'caller',
|
||||
'catch', 'chomp', 'chomp!', 'chop', 'chop!', 'eval', 'exec', 'exit',
|
||||
'exit!', 'fail', 'Float', 'fork', 'format', 'gets', 'global_variables',
|
||||
'gsub', 'gsub!', 'Integer', 'lambda', 'proc', 'load', 'local_variables',
|
||||
'loop', 'open', 'p', 'print', 'printf', 'proc', 'puts', 'raise', 'fail',
|
||||
'rand', 'readlines', 'require', 'scan', 'select', 'set_trace_func',
|
||||
'sleep', 'split', 'sprintf', 'srand', 'String', 'syscall', 'system',
|
||||
'sub', ',sub!', 'test', 'throw', 'trace_var', 'trap', 'untrace_var',
|
||||
'abs', 'ceil', 'coerce', 'divmod', 'floor', 'integer?', 'modulo',
|
||||
'nonzero?', 'remainder', 'round', 'truncate', 'zero?', 'chr', 'size',
|
||||
'step', 'times', 'to_f', 'to_int', 'to_i', 'finite?', 'infinite?',
|
||||
'nan?', 'atan2', 'cos', 'exp', 'frexp', 'ldexp', 'log', 'log10', 'sin',
|
||||
'sqrt', 'tan'));
|
||||
|
||||
|
||||
// this can break a bit with Ruby's whacky syntax
|
||||
$this->remove_filter('pcre');
|
||||
// don't want this.
|
||||
$this->remove_filter('comment-to-doc');
|
||||
|
||||
$this->add_filter('REGEX', create_function('$tok',
|
||||
'return LuminousFilters::pcre($tok, (isset($tok[1][0]) && $tok[1][0] === "/"));'));
|
||||
}
|
||||
|
||||
|
||||
protected function is_regex() {
|
||||
/*
|
||||
* Annoyingly I don't really know exactly what rules Ruby uses for
|
||||
* disambiguating regular expressions. There might be some incorrect
|
||||
* assumptions in here.
|
||||
*/
|
||||
|
||||
if ($this->check('%/=\s%'))
|
||||
return false;
|
||||
$following_space = (bool)$this->check("%/[ \t]%");
|
||||
$space = false;
|
||||
for($i=count($this->tokens)-1; $i>=0; $i--) {
|
||||
$tok = $this->tokens[$i];
|
||||
if ($tok[0] === 'COMMENT') continue;
|
||||
elseif ($tok[0] === 'OPERATOR') return true;
|
||||
elseif($tok[0] === 'STRING') return true;
|
||||
elseif ($tok[1] === '(' || $tok[1] === ',' || $tok[1] === '{' ||
|
||||
$tok[1] === '[') {
|
||||
// this is definitely an operand
|
||||
return true;
|
||||
}
|
||||
elseif($tok[0] === null) {
|
||||
$space = true;
|
||||
continue;
|
||||
}
|
||||
elseif($tok[0] === 'NUMERIC') {
|
||||
// this is definitely an operator
|
||||
return false;
|
||||
}
|
||||
elseif ($tok[0] === 'IDENT'
|
||||
|| $tok[0] === 'CONSTANT'
|
||||
|| $tok[0] === 'VALUE' // aka :symbols
|
||||
) {
|
||||
// this could be an operator or operand
|
||||
// Kate's syntax engine seems to operate on the following basis:
|
||||
if ($space && $following_space) return false;
|
||||
return $space;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true; // no preceding tokens, presumably a code fragment.
|
||||
}
|
||||
|
||||
|
||||
protected function interpolate() {
|
||||
$interpolation_scanner = new LuminousRubyScanner();
|
||||
$interpolation_scanner->string($this->string());
|
||||
$interpolation_scanner->pos($this->pos());
|
||||
$interpolation_scanner->interpolation = true;
|
||||
$interpolation_scanner->init();
|
||||
$interpolation_scanner->main();
|
||||
$this->record($interpolation_scanner->tagged(), 'INTERPOLATION', true);
|
||||
$this->pos($interpolation_scanner->pos());
|
||||
}
|
||||
|
||||
|
||||
// handles the heredoc array. Call at eol/bol when the heredoc queue is
|
||||
// not empty
|
||||
protected function do_heredoc() {
|
||||
|
||||
assert (!empty($this->heredocs));
|
||||
|
||||
$start = $this->pos();
|
||||
|
||||
for($i=0; $i<count($this->heredocs) ; ) {
|
||||
$top = $this->heredocs[$i];
|
||||
list($ident, $identable, $interpolatable) = $top;
|
||||
$searches = array(
|
||||
sprintf('/^%s%s\\b/m', $identable? "[ \t]*" : '',
|
||||
preg_quote($ident, '/'))
|
||||
);
|
||||
if ($interpolatable)
|
||||
$searches[] = '/\#\{/';
|
||||
list($next, $matches) = $this->get_next($searches);
|
||||
if ($next === -1) {
|
||||
// no match for end delim, run to EOS
|
||||
$this->record(substr($this->string(), $start), 'HEREDOC');
|
||||
$this->terminate();
|
||||
break;
|
||||
}
|
||||
assert($matches !== null);
|
||||
if ($matches[0] === '#{') { // interpolation, break heredoc and do that.
|
||||
$this->pos($next);
|
||||
$this->record(substr($this->string(), $start, $this->pos()-$start), 'HEREDOC');
|
||||
$this->record($matches[0], 'DELIMITER');
|
||||
$this->pos_shift(strlen($matches[0]));
|
||||
$this->interpolate();
|
||||
if ($this->peek() === '}')
|
||||
$this->record($this->get(), 'DELIMITER');
|
||||
$start = $this->pos();
|
||||
}
|
||||
else {
|
||||
//
|
||||
$this->pos($next);
|
||||
$this->record(substr($this->string(), $start, $this->pos()-$start), 'HEREDOC');
|
||||
$this->record($matches[0], 'DELIMITER');
|
||||
$this->pos($next + strlen($matches[0]));
|
||||
$start = $this->pos();
|
||||
$i++;
|
||||
}
|
||||
// subscanner might have consumed all the string, in which case there's
|
||||
// no point continuing
|
||||
if ($this->eos()) break;
|
||||
|
||||
}
|
||||
// we may or may not have technically addressed all the heredocs in the
|
||||
// queue, but we do want to clear them out now
|
||||
$this->heredocs = array();
|
||||
}
|
||||
|
||||
|
||||
private function record_string_range($from, $to, $type, $split) {
|
||||
if ($to === $from) return;
|
||||
$substr = substr($this->string(), $from, $to-$from);
|
||||
if ($split) {
|
||||
foreach(preg_split('/(\s+)/', $substr, -1, PREG_SPLIT_DELIM_CAPTURE) as $s) {
|
||||
$type_ = preg_match('/^\s+$/', $s)? null : $type;
|
||||
$this->record($s, $type_);
|
||||
}
|
||||
} else {
|
||||
$this->record($substr, $type);
|
||||
}
|
||||
}
|
||||
|
||||
// handles string types (inc regexes), which may have nestable delimiters or
|
||||
// interpolation.
|
||||
// strdata is defined in the big ugly block in main()
|
||||
// TODO: proper docs
|
||||
protected function do_string($str_data) {
|
||||
list($type, $open_delimiter, $close_delimiter, $pos, $interpolation,
|
||||
$fancy_delim, $split) = $str_data;
|
||||
$balanced = $open_delimiter !== $close_delimiter;
|
||||
$template = '/(?<!\\\\)((?:\\\\\\\\)*)(%s)/';
|
||||
$patterns = array();
|
||||
$patterns['term'] = sprintf($template, preg_quote($close_delimiter, '/'));
|
||||
if ($balanced) {
|
||||
// for nesting balanced delims
|
||||
$patterns['nest'] = sprintf($template, preg_quote($open_delimiter, '/'));
|
||||
}
|
||||
if ($interpolation) {
|
||||
$patterns['interp'] = sprintf($template, preg_quote('#{', '/'));
|
||||
}
|
||||
$nesting_level = 0;
|
||||
$break = false;
|
||||
while (!$break) {
|
||||
list($name, $index, $matches) = $this->get_next_named($patterns);
|
||||
|
||||
if ($name === null) {
|
||||
// special case, no matches, record the rest of the string and break
|
||||
// immediately
|
||||
$this->record_string_range($pos, strlen($this->string()), $type, $split);
|
||||
$this->terminate();
|
||||
break;
|
||||
}
|
||||
elseif ($name === 'nest') {
|
||||
// nestable opener
|
||||
$nesting_level++;
|
||||
$this->pos( $index + strlen($matches[0]) );
|
||||
}
|
||||
elseif($name === 'term') {
|
||||
// terminator, may be nested
|
||||
if ($nesting_level === 0) {
|
||||
// wasn't nested, real terminator.
|
||||
if ($fancy_delim) {
|
||||
// matches[1] is either empty or a sequence of backslashes
|
||||
$this->record_string_range($pos, $index+strlen($matches[1]), $type, $split);
|
||||
$this->record($matches[2], 'DELIMITER');
|
||||
} else {
|
||||
$this->record_string_range($pos, $index+strlen($matches[0]), $type, $split);
|
||||
}
|
||||
$break = true;
|
||||
}
|
||||
else {
|
||||
// pop a nesting level
|
||||
$nesting_level--;
|
||||
}
|
||||
$this->pos( $index + strlen($matches[0]) );
|
||||
|
||||
}
|
||||
elseif($name === 'interp') {
|
||||
// interpolation - temporarily break string highlighting, then
|
||||
// do interpolation, then resume.
|
||||
$this->record_string_range($pos, $index + strlen($matches[1]), $type, $split);
|
||||
$this->record($matches[2], 'DELIMITER');
|
||||
$this->pos( $index + strlen($matches[0]) );
|
||||
|
||||
$this->interpolate();
|
||||
if (($c = $this->peek()) === '}')
|
||||
$this->record($this->get(), 'DELIMITER');
|
||||
$pos = $this->pos();
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
}
|
||||
if ($break) break;
|
||||
}
|
||||
if ($type === 'REGEX' && $this->scan('/[iomx]+/'))
|
||||
$this->record($this->match(), 'KEYWORD');
|
||||
}
|
||||
|
||||
|
||||
public function main() {
|
||||
|
||||
while (!$this->eos()) {
|
||||
|
||||
if ($this->bol() && !empty($this->heredocs)) {
|
||||
$this->do_heredoc();
|
||||
}
|
||||
|
||||
if ($this->interpolation) {
|
||||
$c = $this->peek();
|
||||
if ($c === '{') $this->curley_braces++;
|
||||
elseif($c === '}') {
|
||||
$this->curley_braces--;
|
||||
if ($this->curley_braces <= 0) { break;}
|
||||
}
|
||||
}
|
||||
if ($this->rails && $this->check('/-?%>/')) {
|
||||
break;
|
||||
}
|
||||
|
||||
$c = $this->peek();
|
||||
if ($c === '=' && $this->scan('/^=begin .*? (^=end|\\z)/msx')) {
|
||||
$this->record($this->match(), 'DOCCOMMENT');
|
||||
}
|
||||
elseif($c === '#' && $this->scan($this->comment_regex))
|
||||
$this->record($this->match(), 'COMMENT');
|
||||
|
||||
elseif($this->scan($this->numeric) !== null) {
|
||||
$this->record($this->match(), 'NUMERIC');
|
||||
}
|
||||
elseif( $c === '$' && $this->scan('/\\$
|
||||
(?:
|
||||
(?:[!@`\'\+1~=\/\\\,;\._0\*\$\?:"&<>])
|
||||
|
|
||||
(?: -[0adFiIlpvw])
|
||||
|
|
||||
(?:DEBUG|FILENAME|LOAD_PATH|stderr|stdin|stdout|VERBOSE)
|
||||
)/x') || $this->scan('/(\\$|@@?)\w+/')) {
|
||||
$this->record($this->match(), 'VARIABLE');
|
||||
}
|
||||
elseif($this->scan('/:\w+/')) {
|
||||
$this->record($this->match(), 'VALUE');
|
||||
}
|
||||
elseif ( $c === '<' && $this->scan('/(<<(-?))([\'"`]?)([A-Z_]\w*)(\\3)/i')) {
|
||||
$m = $this->match_groups();
|
||||
$this->record($m[0], 'DELIMITER');
|
||||
$hdoc = array($m[4], $m[2] === '-', $m[3] !== "'");
|
||||
$this->heredocs[] = $hdoc;
|
||||
}
|
||||
|
||||
// TODO: "% hello " is I think a valid string, using whitespace as
|
||||
// delimiters. We're going to disallow this for now because
|
||||
// we're not disambiguating between that and modulus
|
||||
elseif (($c === '"' || $c === "'" || $c === '`' || $c === '%') &&
|
||||
$this->scan('/[\'"`]|%( [qQrswWx](?![[:alnum:]]|$) | (?![[:alnum:]\s]|$))/xm')
|
||||
|| ($c === '/' && $this->is_regex())
|
||||
)
|
||||
{
|
||||
$interpolation = false;
|
||||
$type = 'STRING';
|
||||
$delimiter;
|
||||
$pos;
|
||||
$fancy_delim = false;
|
||||
$split = false;
|
||||
|
||||
if ($c === '/') {
|
||||
$interpolation = true;
|
||||
$type = 'REGEX';
|
||||
$delimiter = $c;
|
||||
$pos = $this->pos();
|
||||
$this->get();
|
||||
} else {
|
||||
$pos = $this->match_pos();
|
||||
$delimiter = $this->match();
|
||||
if ($delimiter === '"') {
|
||||
$interpolation = true;
|
||||
} elseif($delimiter === "'") {}
|
||||
elseif($delimiter === '`') {
|
||||
$type = 'FUNCTION';
|
||||
}
|
||||
else {
|
||||
$delimiter = $this->get();
|
||||
$m1 = $this->match_group(1);
|
||||
if ($m1 === 'Q' || $m1 === 'r' || $m1 === 'W' || $m1 === 'x')
|
||||
$interpolation = true;
|
||||
if ($m1 === 'w' || $m1 === 'W')
|
||||
$split = true;
|
||||
if ($m1 === 'x') $type = 'FUNCTION';
|
||||
elseif($m1 === 'r') $type = 'REGEX';
|
||||
|
||||
$fancy_delim = true;
|
||||
$this->record($this->match() . $delimiter, 'DELIMITER');
|
||||
$pos = $this->pos();
|
||||
}
|
||||
}
|
||||
$data = array($type, $delimiter, LuminousUtils::balance_delimiter($delimiter),
|
||||
$pos, $interpolation, $fancy_delim, $split);
|
||||
$this->do_string($data);
|
||||
}
|
||||
elseif( (ctype_alpha($c) || $c === '_') &&
|
||||
($m = $this->scan('/[_a-zA-Z]\w*[!?]?/')) !== null) {
|
||||
$this->record($m, ctype_upper($m[0])? 'CONSTANT' : 'IDENT');
|
||||
if ($m === '__END__') {
|
||||
if (!$this->interpolation) {
|
||||
$this->record($this->rest(), null);
|
||||
$this->terminate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
elseif($this->scan($this->operator_regex))
|
||||
$this->record($this->match(), 'OPERATOR');
|
||||
elseif($this->scan("/[ \t]+/")) $this->record($this->match(), null);
|
||||
else {
|
||||
$this->record($this->get(), null);
|
||||
}
|
||||
}
|
||||
// In case not everything was popped
|
||||
if (isset($this->state_[0])) {
|
||||
$this->record(
|
||||
substr($this->string(), $this->state_[0][3],
|
||||
$this->pos() - $this->state_[0][3]),
|
||||
$this->state_[0][0]
|
||||
);
|
||||
$this->terminate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
if (strpos($info['shebang'], 'ruby') !== false) return 1.0;
|
||||
elseif($info['shebang']) return 0;
|
||||
$p = 0;
|
||||
if (strpos($src, 'nil')) $p += 0.05;
|
||||
if (strpos($src, '.nil?')) $p += 0.02;
|
||||
if (strpos($src, '.empty?')) $p += 0.02;
|
||||
// interpolation
|
||||
if (strpos($src, '#{$')) $p += 0.02;
|
||||
// @ and $ vars
|
||||
if (preg_match('/@[a-zA-Z_]/', $src) && preg_match('/\\$[a-zA-Z_]/', $src))
|
||||
$p += 0.02;
|
||||
// symbols
|
||||
if (preg_match('/:[a-zA-Z_]/', $src)) $p += 0.01;
|
||||
// func def - no args
|
||||
if (preg_match("/^\s*+def\s++[a-zA-Z_]\w*+[ \t]*+[\n\r]/m", $src))
|
||||
$p += 0.1;
|
||||
// {|x[,y[,z...]]| is a very ruby-like construct
|
||||
if (preg_match('/ \\{ \\|
|
||||
\s*+ [a-zA-Z_]\w*+ \s*+
|
||||
(,\s*+[a-zA-Z_]\w*+\s*+)*+
|
||||
\\|/x', $src))
|
||||
$p += 0.15;
|
||||
// so is 'do |x|'
|
||||
if (preg_match("/\\bdo\s*+\\|[^\\|\r\n]++\\|/", $src))
|
||||
$p += 0.05;
|
||||
|
||||
// class defs with inheritance has quite distinct syntax
|
||||
// class x < y
|
||||
if (preg_match(
|
||||
"/^ \s* class \s+ \w+ \s* < \s* \w+(::\w+)* [\t ]*+ [\r\n] /mx",
|
||||
$src))
|
||||
$p += 0.1;
|
||||
|
||||
$num_lines = $info['num_lines'];
|
||||
// let's say if 5% of lines are hash commented that's a good thing
|
||||
if (substr_count($src, '#') > $num_lines/20) $p += 0.05;
|
||||
// =~ /regex/
|
||||
if (preg_match('%=~\s++/%', $src)) $p += 0.02;
|
||||
|
||||
if (preg_match('/unless\s+[^\?]++\?/', $src)) $p += 0.05;
|
||||
|
||||
if (preg_match('/^(\s*+)def\s+.*^\1end\s/ms', $src)) $p += 0.05;
|
||||
|
||||
if (preg_match('/\.to_\w+(?=\s|$)/', $src)) $p += 0.01;
|
||||
|
||||
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Scala
|
||||
*
|
||||
* Direct port of old luminous language file.
|
||||
*
|
||||
* TODO: The XML literals may contain embedded scala code. This is bad
|
||||
* because we ignore that currently, and we may, in rare circumstances,
|
||||
* incorrectly pop a tag when in fact it's inside a scala expression
|
||||
*
|
||||
* Some comments reference section numbers of the scala spec:
|
||||
* http://www.scala-lang.org/sites/default/files/linuxsoft_archives/docu/files/ScalaReference.pdf
|
||||
*
|
||||
*/
|
||||
|
||||
// scala inherits some stuff from Java
|
||||
require_once(dirname(__FILE__) . '/include/java_func_list.php');
|
||||
class LuminousScalaScanner extends LuminousSimpleScanner {
|
||||
|
||||
/**
|
||||
* Multiline comments nest
|
||||
*/
|
||||
function comment_override() {
|
||||
$this->nestable_token('COMMENT', '%/\\*%', '%\\*/%');
|
||||
}
|
||||
|
||||
/**
|
||||
* Scala has XML literals.
|
||||
*/
|
||||
function xml_override($matches) {
|
||||
// this might just be an inequality, so we first need to disambiguate
|
||||
// that
|
||||
|
||||
// 1.5 - the disambiguation is pretty simple, an XML tag must
|
||||
// follow either whitespace, (, or {, and the '<' must be followed
|
||||
// by '[!?_a-zA-Z]
|
||||
// I'm not sure if a comment is a special case, or if it's treated as
|
||||
// whitespace...
|
||||
$xml = false;
|
||||
for($i=count($this->tokens)-1; $i>=0; $i--) {
|
||||
$tok = $this->tokens[$i];
|
||||
$name = $tok[0];
|
||||
// ... but we're going treat it as a no-op and skip over it
|
||||
if ($name === 'COMMENT') continue;
|
||||
$last_char = $tok[1][strlen($tok[1])-1];
|
||||
if (!(ctype_space($last_char) || $last_char === '(' ||
|
||||
$last_char === '{')) break;
|
||||
if (!$this->check('/<[!?a-zA-Z0-9_]/')) break;
|
||||
$xml = true;
|
||||
}
|
||||
if (!$xml) {
|
||||
$this->record($matches[0], 'OPERATOR');
|
||||
$this->pos_shift(strlen($matches[0]));
|
||||
return;
|
||||
}
|
||||
$subscanner = new LuminousXMLScanner();
|
||||
$subscanner->string($this->string());
|
||||
$subscanner->pos($this->pos());
|
||||
$subscanner->xml_literal = true;
|
||||
$subscanner->init();
|
||||
$subscanner->main();
|
||||
$tagged = $subscanner->tagged();
|
||||
$this->record($tagged, 'XML', true);
|
||||
$this->pos($subscanner->pos());
|
||||
}
|
||||
|
||||
function init() {
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_SL);
|
||||
$this->add_pattern('COMMENT_ML', '%/\\*%');
|
||||
$this->overrides['COMMENT_ML'] = array($this, 'comment_override');
|
||||
|
||||
|
||||
// 1.3.1 integer literals, 1.3.2 floatingPointLiteral
|
||||
// Do the float first so it takes precedence, our scanner does not follow
|
||||
// the max-munch rule
|
||||
$digit = '\d';
|
||||
$exp = '(?:[eE][+-]?\d+)';
|
||||
$suffix = '[FfDd]';
|
||||
$this->add_pattern('NUMERIC', "/(?: \d+\\.\d* | \\.\d+) $exp? $suffix? /x");
|
||||
$this->add_pattern('NUMERIC', "/\d+($exp $suffix? |$exp?$suffix)/x");
|
||||
$this->add_pattern('NUMERIC', '/(?:0x[a-fA-F0-9]+|\d+)[lL]?/');
|
||||
|
||||
// 1.3.4 character literals
|
||||
// we can't really parse the unicode and work out what's printable,
|
||||
// so we'll just allow any unicode sequence
|
||||
$this->add_pattern('CHARACTER',
|
||||
"/'
|
||||
(
|
||||
(?:\\\\ (?:u[a-f0-9]{1,4}|\d+|.))
|
||||
| .
|
||||
)'/sx");
|
||||
// 1.3.5 - 1.3.6
|
||||
// strings are kind of pythonic, triple quoting makes them multiline
|
||||
$this->add_pattern('STRING', '/"""
|
||||
(?: [^"\\\\]+ | \\\\. | ""[^"] | "[^"])*
|
||||
(?:"""|$)/sx');
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$DOUBLE_STR_SL);
|
||||
|
||||
$this->add_pattern('lt', '/</');
|
||||
$this->overrides['lt'] = array($this, 'xml_override');
|
||||
$this->add_pattern('OPERATOR', '/[¬!%^&*-=+~;:|>\\/?\\\\]+/');
|
||||
|
||||
$this->add_pattern('IDENT', '/[a-z_]\w*/i');
|
||||
|
||||
|
||||
|
||||
// 1.3.3 boolean literals
|
||||
$this->add_identifier_mapping('VALUE', array('true', 'false', 'null', 'None'));
|
||||
|
||||
// from old luminous file
|
||||
$this->add_identifier_mapping('KEYWORD', array('abstract', 'case',
|
||||
'catch', 'class', 'def', 'do', 'else', 'extends', 'final', 'finally',
|
||||
'for', 'forSome', 'if', 'implicit', 'import', 'lazy', 'match',
|
||||
'new', 'object', 'override', 'package', 'private', 'protected',
|
||||
'return', 'sealed', 'super', 'this', 'throw', 'trait', 'try', 'type',
|
||||
'val', 'var', 'while', 'with', 'yield'));
|
||||
$this->add_identifier_mapping('TYPE', array('boolean', 'byte', 'char',
|
||||
'dobule', 'float', 'int', 'long', 'string', 'short', 'unit',
|
||||
'Boolean', 'Byte', 'Char', 'Double', 'Float', 'Int', 'Long', 'String',
|
||||
'Short', 'Unit'));
|
||||
// from Kate's syntax file
|
||||
$this->add_identifier_mapping('TYPE', array('ActorProxy', 'ActorTask',
|
||||
'ActorThread', 'AllRef', 'Any', 'AnyRef', 'Application', 'AppliedType',
|
||||
'Array', 'ArrayBuffer', 'Attribute', 'BoxedArray', 'BoxedBooleanArray',
|
||||
'BoxedByteArray', 'BoxedCharArray', 'Buffer', 'BufferedIterator', 'Char',
|
||||
'Console', 'Enumeration', 'Fluid', 'Function', 'IScheduler',
|
||||
'ImmutableMapAdaptor', 'ImmutableSetAdaptor', 'Int', 'Iterable', 'List',
|
||||
'ListBuffer', 'None', 'Option', 'Ordered', 'Pair', 'PartialFunction',
|
||||
'Pid', 'Predef', 'PriorityQueue', 'PriorityQueueProxy', 'Reaction',
|
||||
'Ref', 'Responder', 'RichInt', 'RichString', 'Rule', 'RuleTransformer',
|
||||
'Script', 'Seq', 'SerialVersionUID', 'Some', 'Stream', 'Symbol',
|
||||
'TcpService', 'TcpServiceWorker', 'Triple', 'Unit', 'Value',
|
||||
'WorkerThread', 'serializable', 'transient', 'volatile'));
|
||||
|
||||
$this->add_identifier_mapping('TYPE', $GLOBALS['luminous_java_types']);
|
||||
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
$p = 0;
|
||||
// func def, a lot like python
|
||||
if (preg_match('/\\bdef\s+\w+\s*\(/', $src)) $p += 0.05;
|
||||
// val x = y
|
||||
if (preg_match('/\\bval\s+\w+\s*=/', $src)) $p += 0.1;
|
||||
// argument types
|
||||
if (preg_match('/\\(\s*\w+\s*:\s*(String|Int|Array)/', $src)) $p += 0.05;
|
||||
// tripled quoted strings, like python
|
||||
if (preg_match('/\'{3}|"{3}/', $src)) $p += 0.05;
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,335 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* The SCSS scanner is quite complex, having to deal with nested rules
|
||||
* and so forth and some disambiguation is non-trivial, so we are employing
|
||||
* a two-pass approach here - we first tokenize the source as normal with a
|
||||
* scanner, then we parse the token stream with a parser to figure out
|
||||
* what various things really are.
|
||||
*/
|
||||
class LuminousSCSSScanner extends LuminousScanner {
|
||||
private $regexen = array();
|
||||
|
||||
public $rule_tag_map = array(
|
||||
'PROPERTY' => 'TYPE',
|
||||
'COMMENT_SL' => 'COMMENT',
|
||||
'COMMENT_ML' => 'COMMENT',
|
||||
'ELEMENT_SELECTOR' => 'KEYWORD',
|
||||
'STRING_S' => 'STRING',
|
||||
'STRING_D' => 'STRING',
|
||||
'CLASS_SELECTOR' => 'VARIABLE',
|
||||
'ID_SELECTOR' => 'VARIABLE',
|
||||
'PSEUDO_SELECTOR' => 'OPERATOR',
|
||||
'ATTR_SELECTOR' => 'OPERATOR',
|
||||
'WHITESPACE' => null,
|
||||
'COLON' => 'OPERATOR',
|
||||
'SEMICOLON' => 'OPERATOR',
|
||||
'COMMA' => 'OPERATOR',
|
||||
'R_BRACE' => 'OPERATOR',
|
||||
'R_BRACKET' => 'OPERATOR',
|
||||
'R_SQ_BRACKET' => 'OPERATOR',
|
||||
'L_BRACE' => 'OPERATOR',
|
||||
'L_BRACKET' => 'OPERATOR',
|
||||
'L_SQ_BRACKET' => 'OPERATOR',
|
||||
'OTHER_OPERATOR' => 'OPERATOR',
|
||||
'GENERIC_IDENTIFIER' => null,
|
||||
'AT_IDENTIFIER' => 'KEYWORD',
|
||||
'IMPORTANT' => 'KEYWORD',
|
||||
);
|
||||
|
||||
public function init() {
|
||||
$this->regexen = array(
|
||||
// For the first pass we just feed in a bunch of tokens.
|
||||
// Some of these are generic and will require disambiguation later
|
||||
'COMMENT_SL' => LuminousTokenPresets::$C_COMMENT_SL,
|
||||
'COMMENT_ML' => LuminousTokenPresets::$C_COMMENT_ML,
|
||||
'STRING_S' => LuminousTokenPresets::$SINGLE_STR,
|
||||
'STRING_D' => LuminousTokenPresets::$DOUBLE_STR,
|
||||
// TODO check var naming, is $1 a legal variable?
|
||||
'VARIABLE' => '%\$[\-a-z_0-9]+ | \#\{\$[\-a-z_0-9]+\} %x',
|
||||
'AT_IDENTIFIER' => '%@[a-zA-Z0-9]+%',
|
||||
|
||||
// This is generic - it may be a selector fragment, a rule, or
|
||||
// even a hex colour.
|
||||
'GENERIC_IDENTIFIER' => '@
|
||||
\\#[a-fA-F0-9]{3}(?:[a-fA-F0-9]{3})?
|
||||
|
|
||||
[0-9]+(\.[0-9]+)?(\w+|%|in|cm|mm|em|ex|pt|pc|px|s)?
|
||||
|
|
||||
-?[a-zA-Z_\-0-9]+[a-zA-Z_\-0-9]*
|
||||
|&
|
||||
@x',
|
||||
'IMPORTANT' => '/!important/',
|
||||
'L_BRACE' => '/\{/',
|
||||
'R_BRACE' => '/\}/',
|
||||
'L_SQ_BRACKET' => '/\[/',
|
||||
'R_SQ_BRACKET' => '/\]/',
|
||||
'L_BRACKET' => '/\(/',
|
||||
'R_BRACKET' => '/\)/',
|
||||
|
||||
'DOUBLE_COLON' => '/::/',
|
||||
'COLON' => '/:/',
|
||||
'SEMICOLON' => '/;/',
|
||||
|
||||
'DOT' => '/\./',
|
||||
'HASH' => '/#/',
|
||||
|
||||
'COMMA' => '/,/',
|
||||
|
||||
'OTHER_OPERATOR' => '@[+\-*/%&>=!]@',
|
||||
|
||||
'WHITESPACE' => '/\s+/'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function main() {
|
||||
while (!$this->eos()) {
|
||||
$m = null;
|
||||
foreach($this->regexen as $token=>$pattern) {
|
||||
if ( ($m = $this->scan($pattern)) !== null) {
|
||||
$this->record($m, $token);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($m === null) {
|
||||
$this->record($this->get(), null);
|
||||
}
|
||||
}
|
||||
$parser = new LuminousSASSParser();
|
||||
$parser->tokens = $this->tokens;
|
||||
$parser->parse();
|
||||
$this->tokens = $parser->tokens;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* The parsing class
|
||||
*/
|
||||
class LuminousSASSParser {
|
||||
|
||||
public $tokens;
|
||||
public $index;
|
||||
public $stack;
|
||||
static $delete_token = 'delete';
|
||||
|
||||
/**
|
||||
* Returns true if the next token is the given token name
|
||||
* optionally skipping whitespace
|
||||
*/
|
||||
function next_is($token_name, $ignore_whitespace = false) {
|
||||
$i = $this->index+1;
|
||||
$len = count($this->tokens);
|
||||
while($i<$len) {
|
||||
$tok = $this->tokens[$i][0];
|
||||
if ($ignore_whitespace && $tok === 'WHITESPACE') {
|
||||
$i++;
|
||||
}
|
||||
else {
|
||||
return $tok === $token_name;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns the index of the next match of the sequence of tokens
|
||||
* given, optionally ignoring ertain tokens
|
||||
*/
|
||||
function next_sequence($sequence, $ignore=array()) {
|
||||
$i = $this->index+1;
|
||||
$len = count($this->tokens);
|
||||
$seq_len = count($sequence);
|
||||
$seq = 0;
|
||||
$seq_start = 0;
|
||||
while ($i<$len) {
|
||||
$tok = $this->tokens[$i][0];
|
||||
if ($tok === $sequence[$seq]) {
|
||||
if ($seq === 0) $seq_start = $i;
|
||||
$seq++;
|
||||
$i++;
|
||||
if ($seq === $seq_len) {
|
||||
return $seq_start;
|
||||
}
|
||||
} else {
|
||||
if (in_array($tok, $ignore)) {}
|
||||
else {
|
||||
$seq = 0;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
return $len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first token which occurs out of the set of given tokens
|
||||
*/
|
||||
function next_of($token_names) {
|
||||
$i = $this->index+1;
|
||||
$len = count($this->tokens);
|
||||
while ($i<$len) {
|
||||
$tok = $this->tokens[$i][0];
|
||||
if (in_array($tok, $token_names)) {
|
||||
return $tok;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
/**
|
||||
* Returns the index of the next token with the given token name
|
||||
*/
|
||||
function next_of_type($token_name) {
|
||||
$i = $this->index+1;
|
||||
$len = count($this->tokens);
|
||||
while($i<$len) {
|
||||
$tok = $this->tokens[$i][0];
|
||||
if ($tok === $token_name) {
|
||||
return $i;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
return $len;
|
||||
}
|
||||
|
||||
private function _parse_identifier($token) {
|
||||
$val = $token[1];
|
||||
$c = isset($val[0])? $val[0] : '';
|
||||
if (ctype_digit($c) || $c === '#') {
|
||||
$token[0] = 'NUMERIC';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a selector rule
|
||||
*/
|
||||
private function _parse_rule() {
|
||||
$new_token = $this->tokens[$this->index];
|
||||
$set = false;
|
||||
if ($this->index > 0) {
|
||||
$prev_token = &$this->tokens[$this->index-1];
|
||||
$prev_token_type = &$prev_token[0];
|
||||
$prev_token_text = &$prev_token[1];
|
||||
$concat = false;
|
||||
|
||||
$map = array(
|
||||
'DOT' => 'CLASS_SELECTOR',
|
||||
'HASH' => 'ID_SELECTOR',
|
||||
'COLON' => 'PSEUDO_SELECTOR',
|
||||
'DOUBLE_COLON' => 'PSEUDO_SELECTOR'
|
||||
);
|
||||
if (isset($map[$prev_token_type])) {
|
||||
// mark the prev token for deletion and concat into one.
|
||||
$new_token[0] = $map[$prev_token_type];
|
||||
$prev_token_type = self::$delete_token;
|
||||
$new_token[1] = $prev_token_text . $new_token[1];
|
||||
$set = true;
|
||||
}
|
||||
}
|
||||
if (!$set) {
|
||||
// must be an element
|
||||
$new_token[0] = 'ELEMENT_SELECTOR';
|
||||
}
|
||||
$this->tokens[$this->index] = $new_token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the token stream by deleting any tokens marked for
|
||||
* deletion, and makes sure the array is continuous afterwards.
|
||||
*/
|
||||
private function _cleanup() {
|
||||
foreach($this->tokens as $i=>$t) {
|
||||
if ($t[0] === self::$delete_token) {
|
||||
unset($this->tokens[$i]);
|
||||
}
|
||||
}
|
||||
$this->tokens = array_values($this->tokens);
|
||||
}
|
||||
/**
|
||||
* Main parsing function
|
||||
*/
|
||||
public function parse() {
|
||||
$new_tokens = array();
|
||||
$len = count($this->tokens);
|
||||
$this->stack = array();
|
||||
$prop_value = 'PROPERTY';
|
||||
$pushes = array(
|
||||
'L_BRACKET' => 'bracket',
|
||||
'L_BRACE' => 'brace',
|
||||
'AT_IDENTIFIER' => 'at',
|
||||
'L_SQ_BRACKET' => 'square'
|
||||
);
|
||||
$pops = array(
|
||||
'R_BRACKET' => 'bracket',
|
||||
'R_BRACE' => 'brace',
|
||||
'R_SQ_BRACKET' => 'square'
|
||||
);
|
||||
$this->index = 0;
|
||||
while($this->index < $len) {
|
||||
$token = &$this->tokens[$this->index];
|
||||
$stack_size = count($this->stack);
|
||||
$state = !$stack_size? null : $this->stack[$stack_size-1];
|
||||
$tok_name = &$token[0];
|
||||
$in_brace = in_array('brace', $this->stack);
|
||||
$in_bracket = in_array('bracket', $this->stack);
|
||||
$in_sq = in_array('square', $this->stack);
|
||||
$in_at = in_array('at', $this->stack);
|
||||
if ($tok_name === self::$delete_token) continue;
|
||||
|
||||
if ($tok_name === 'L_BRACE') {
|
||||
if ($state === 'at') {
|
||||
array_pop($this->stack);
|
||||
}
|
||||
$this->stack[] = $pushes[$tok_name];
|
||||
$prop_value = 'PROPERTY';
|
||||
}
|
||||
elseif (isset($pushes[$tok_name])) {
|
||||
$this->stack[] = $pushes[$tok_name];
|
||||
} else if (isset($pops[$tok_name]) && $state === $pops[$tok_name]) {
|
||||
array_pop($this->stack);
|
||||
}
|
||||
elseif (!$in_bracket && $tok_name === 'COLON') {
|
||||
$prop_value = 'VALUE';
|
||||
}
|
||||
elseif ($tok_name === 'SEMICOLON') {
|
||||
$prop_value = 'PROPERTY';
|
||||
if ($state === 'at') array_pop($this->stack);
|
||||
}
|
||||
elseif ($tok_name === 'GENERIC_IDENTIFIER') {
|
||||
// this is where the fun starts.
|
||||
// we have to figure out exactly what this is
|
||||
// if we can look ahead and find a '{' before we find a
|
||||
// ';', then this is part of a selector.
|
||||
// Otherwise it's part of a property/value pair.
|
||||
// the exception is when we have something like:
|
||||
// font : { family : sans-serif; }
|
||||
// then we need to check for ':{'
|
||||
if ($in_sq) {
|
||||
$token[0] = 'ATTR_SELECTOR';
|
||||
}
|
||||
else if ($in_bracket) {
|
||||
$this->_parse_identifier($token);
|
||||
}
|
||||
elseif(!$in_at) {
|
||||
$semi = $this->next_of_type('SEMICOLON');
|
||||
$colon_brace = $this->next_sequence(array('COLON', 'L_BRACE'),
|
||||
array('WHITESPACE'));
|
||||
$brace = $this->next_of_type('L_BRACE');
|
||||
|
||||
$rule_terminator = min($semi, $colon_brace);
|
||||
if ($brace < $rule_terminator) {
|
||||
$this->_parse_rule();
|
||||
$prop_value = 'PROPERTY';
|
||||
} else {
|
||||
$this->tokens[$this->index][0] = $prop_value;
|
||||
if ($prop_value === 'VALUE') {
|
||||
$this->_parse_identifier($token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
$this->index++;
|
||||
}
|
||||
$this->_cleanup();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
<?php
|
||||
|
||||
class LuminousSQLScanner extends LuminousSimpleScanner {
|
||||
public function init() {
|
||||
$this->case_sensitive = false;
|
||||
// $this->remove_stream_filter('oo-syntax');
|
||||
$this->remove_filter('comment-to-doc');
|
||||
$this->remove_filter('constant');
|
||||
include(dirname(__FILE__) . '/include/sql.php');
|
||||
$this->add_identifier_mapping('KEYWORD', $keywords);
|
||||
$this->add_identifier_mapping('TYPE', $types);
|
||||
$this->add_identifier_mapping('VALUE', $values);
|
||||
$this->add_identifier_mapping('OPERATOR', $operators);
|
||||
$this->add_identifier_mapping('FUNCTION', $functions);
|
||||
|
||||
|
||||
$this->add_pattern('IDENT', '/[a-zA-Z_]+\w*/');
|
||||
$this->add_pattern('COMMENT', LuminousTokenPresets::$C_COMMENT_ML);
|
||||
// # is for MySQL.
|
||||
$this->add_pattern('COMMENT', '/(?:\#|--).*/');
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$SQL_SINGLE_STR_BSLASH);
|
||||
$this->add_pattern('STRING', LuminousTokenPresets::$DOUBLE_STR);
|
||||
$this->add_pattern('STRING', '/ ` (?> [^\\\\`]+ | \\\\. )* (?: `|$)/x');
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_HEX);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_REAL);
|
||||
|
||||
$this->add_pattern('OPERATOR', '/[¬!%^&*\\-=+~:<>\\|\\/]+/');
|
||||
|
||||
$this->add_pattern('KEYWORD', '/\\?/');
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
// we have to be careful not to assign too much weighting to
|
||||
// generic SQL keywords, which will often appear in other languages
|
||||
// when those languages are executing SQL statements
|
||||
//
|
||||
// All in all, SQL is pretty hard to recognise because generally speaking,
|
||||
// an SQL dump will probably contain only a tiny fraction of SQL keywords
|
||||
// with the majority of the text just being data.
|
||||
$p = 0.0;
|
||||
// if we're lucky, the top line will be a comment containing the phrase
|
||||
// 'SQL' or 'dump'
|
||||
if (strpos($info['trimmed'], '--') === 0 && isset($info['lines'][0])
|
||||
&& (
|
||||
stripos($info['lines'][0], 'sql') !== false)
|
||||
|| stripos($info['lines'][0], 'dump' !== false)
|
||||
)
|
||||
$p = 0.5;
|
||||
|
||||
|
||||
foreach(array('SELECT', 'CREATE TABLE', 'INSERT INTO', 'DROP TABLE',
|
||||
'INNER JOIN', 'OUTER JOIN') as $str)
|
||||
{
|
||||
if (strpos($src, $str) !== false) $p += 0.01;
|
||||
}
|
||||
// single line comments --
|
||||
if (preg_match_all('/^--/m', $src, $m) > 5)
|
||||
$p += 0.05;
|
||||
if (preg_match('/VARCHAR\(\d+\)/', $src)) $p += 0.05;
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* VB.NET
|
||||
*
|
||||
* Language spec:
|
||||
* http://msdn.microsoft.com/en-us/library/aa712050(v=vs.71).aspx
|
||||
*
|
||||
* TODO: IIRC vb can be embedded in asp pages like php or ruby on rails,
|
||||
* and XML literals: these are a little bit confusing, something
|
||||
* like "<xyz>.something" appears to be a valid XML fragment (i.e. the <xyz>
|
||||
* is a complete fragment), but at other times, the fragment would run until
|
||||
* the root tag is popped. Need to find a proper description of the grammar
|
||||
* to figure it out
|
||||
*/
|
||||
class LuminousVBScanner extends LuminousSimpleScanner {
|
||||
|
||||
public $case_sensitive = false;
|
||||
|
||||
public function init() {
|
||||
|
||||
$this->add_pattern('PREPROCESSOR', "/^[\t ]*#.*/m");
|
||||
$this->add_pattern('COMMENT', "/'.*/");
|
||||
|
||||
$this->add_pattern('COMMENT', '/\\bREM\\b.*/i');
|
||||
// float
|
||||
$this->add_pattern('NUMERIC', '/ (?<!\d)
|
||||
\d+\.\d+ (?: e[+\\-]?\d+)?
|
||||
|\.\d+ (?: e[+\\-]?\d+)?
|
||||
| \d+ e[+\\-]?\d+
|
||||
/xi');
|
||||
// int
|
||||
$this->add_pattern('NUMERIC', '/ (?:
|
||||
&H[0-9a-f]+
|
||||
| &O[0-7]+
|
||||
| (?<!\d)\d+
|
||||
) [SIL]*/ix');
|
||||
|
||||
$this->add_pattern('CHARACTER', '/"(?:""|.)"c/i');
|
||||
|
||||
$this->add_pattern('STRING', '/" (?> [^"]+ | "" )* ($|")/x');
|
||||
// in theory we should also match unicode quote chars
|
||||
// in reality, well, I read the php docs and I have no idea if it's
|
||||
// even possible.
|
||||
// The chars are:
|
||||
// http://www.fileformat.info/info/unicode/char/201c/index.htm
|
||||
// and
|
||||
// http://www.fileformat.info/info/unicode/char/201d/index.htm
|
||||
|
||||
// date literals, this isn't as discriminating as the grammar specifies.
|
||||
$this->add_pattern('VALUE', "/#[ \t][^#\n]*[ \t]#/");
|
||||
|
||||
$this->add_pattern('OPERATOR', '/[&*+\\-\\/\\\\^<=>,\\.]+/');
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/aa711645(v=VS.71).aspx
|
||||
// XXX: it warns about ! being ambiguous but I don't see how it can be
|
||||
// ambiguous if we use this regex?
|
||||
$this->add_pattern('IDENT', '/[a-z_]\w*[%&@!#$]?/i');
|
||||
|
||||
// we'll borrow C#'s list of types (ie modules, classes, etc)
|
||||
include(dirname(__FILE__) . '/include/vb.php');
|
||||
include(dirname(__FILE__) . '/include/csharp_list.php');
|
||||
$this->add_identifier_mapping('VALUE', $luminous_vb_values);
|
||||
$this->add_identifier_mapping('OPERATOR', $luminous_vb_operators);
|
||||
$this->add_identifier_mapping('TYPE', $luminous_vb_types);
|
||||
$this->add_identifier_mapping('KEYWORD', $luminous_vb_keywords);
|
||||
$this->add_identifier_mapping('TYPE', $luminous_csharp_type_list);
|
||||
}
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
$p = 0.0;
|
||||
if (preg_match('/^Imports\s+System/i', $src)) $p += 0.1;
|
||||
if (preg_match('/Dim\s+\w+\s+As\s+/i', $src)) $p += 0.2;
|
||||
if (preg_match('/(Public|Private|Protected)\s+Sub\s+/i', $src)) $p += 0.1;
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
<?php
|
||||
|
||||
// I can't find some formal definition of vimscript's grammar.
|
||||
// I'm pretty sure it's more complex than this, but, who knows.
|
||||
|
||||
require_once(dirname(__FILE__) . '/include/vim_list.php');
|
||||
|
||||
class LuminousVimScriptScanner extends LuminousSimpleScanner {
|
||||
|
||||
public function string_override() {
|
||||
$comment = $this->bol();
|
||||
$this->skip_whitespace();
|
||||
assert($this->peek() === '"');
|
||||
if ($comment) {
|
||||
$this->record($this->scan("/.*/"), 'COMMENT');
|
||||
} else {
|
||||
if ($this->scan("/ \" (?> [^\n\"\\\\]+ | \\\\. )*$ /mx")) {
|
||||
$this->record($this->match(), 'COMMENT');
|
||||
}
|
||||
else {
|
||||
$m = $this->scan(LuminousTokenPresets::$DOUBLE_STR);
|
||||
assert($m !== null);
|
||||
$this->record($m, 'STRING');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static function comment_filter($token) {
|
||||
$token = LuminousUtils::escape_token($token);
|
||||
$str = &$token[1];
|
||||
// It pays to run the strpos checks first.
|
||||
if (strpos(substr($str, 1), '"') !== false)
|
||||
$str = preg_replace('/(?<!^)"(?>[^"]*)"/', "<STRING>$0</STRING>", $str);
|
||||
|
||||
if (strpos($str, ':') !== false)
|
||||
$str = preg_replace('/(?<=^")((?>\W*))((?>[A-Z]\w+(?>(?>\s+\w+)*)))(:\s*)(.*)/',
|
||||
'$1<DOCTAG>$2</DOCTAG>$3<DOCSTR>$4</DOCSTR>', $str);
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
||||
$this->add_pattern('COMMENT_STRING', "/[\t ]*\"/");
|
||||
$this->add_pattern('STRING', "/'(?>[^\n\\\\']+ | \\\\. )*'/x");
|
||||
$this->add_pattern('NUMERIC','/\#[a-f0-9]+/i');
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_HEX);
|
||||
$this->add_pattern('NUMERIC', LuminousTokenPresets::$NUM_REAL);
|
||||
$this->add_pattern('IDENT', '/[a-z_]\w*/i');
|
||||
$this->add_pattern('OPERATOR', '@[~¬!%^&*\-=+;:,<.>/?\|]+@');
|
||||
|
||||
$this->add_identifier_mapping('FUNCTION',
|
||||
$GLOBALS['luminous_vim_functions']);
|
||||
$this->add_identifier_mapping('KEYWORD',
|
||||
$GLOBALS['luminous_vim_keywords']);
|
||||
|
||||
$this->remove_stream_filter('oo-syntax');
|
||||
$this->remove_filter('comment-to-doc');
|
||||
$this->add_filter('comment', 'COMMENT', array($this, 'comment_filter'));
|
||||
$this->overrides = array('COMMENT_STRING' => array($this, 'string_override'));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
|
||||
|
||||
/*
|
||||
* HTML is the 'root' scanner, we just override a couple of config settings
|
||||
* here, to prevent it from looking for CSS or JS.
|
||||
*/
|
||||
class LuminousXMLScanner extends LuminousHTMLScanner {
|
||||
public $scripts = false;
|
||||
public $embedded_server = false;
|
||||
|
||||
public static function guess_language($src, $info) {
|
||||
if (strpos(ltrim($src), '<?xml') === 0) return 1.0;
|
||||
// don't catch HTML doctypes
|
||||
if (strpos($src, '<!DOCTYPE') !== false) return 0;
|
||||
$p = 0;
|
||||
// simple tag
|
||||
$lines = preg_match_all('/$/m',
|
||||
preg_replace('/^\s+/m', '', $src), $m);
|
||||
// avg 1 tag every 4 lines
|
||||
if (preg_match_all('%<[!?/]?[a-zA-Z_:\\-]%', $src, $m)
|
||||
> $lines/4) $p += 0.15;
|
||||
// self closing tag
|
||||
if (strpos($src, '/>') !== false) $p += 0.05;
|
||||
// tag with attr
|
||||
if (preg_match('/<[a-zA-Z_]\w*\s+[a-zA-Z_]\w+\s*=["\']/', $src))
|
||||
$p += 0.1;
|
||||
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* If we're running in a web environment, this is simply an include
|
||||
* file which includes everything necessary to use Luminous.
|
||||
*
|
||||
* If we're running in CLI-mode then this handles the CLI interface.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once(dirname(__FILE__) . '/src/luminous.php');
|
||||
|
||||
if (PHP_SAPI === 'cli') {
|
||||
// cli mode
|
||||
if (isset($argv[0]) && $argv[0] === basename(__FILE__))
|
||||
require(dirname(__FILE__) . '/src/cli.php');
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
Deny from all
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
<?php
|
||||
///@cond ALL
|
||||
/* command line interface */
|
||||
|
||||
class LuminousCLI {
|
||||
private $options = array(
|
||||
'input-file' => null,
|
||||
'output-file' => null,
|
||||
'lang' => null,
|
||||
'format' => 'html-full',
|
||||
'height' => 0,
|
||||
'theme' => 'geonyx',
|
||||
'code' => null,
|
||||
'line-numbers' => true,
|
||||
);
|
||||
private $cmd_option_map = array(
|
||||
'-i' => 'input-file',
|
||||
'-o' => 'output-file',
|
||||
'-l' => 'lang',
|
||||
'-f' => 'format',
|
||||
'-h' => 'height',
|
||||
'-t' => 'theme',
|
||||
);
|
||||
|
||||
static function print_help() {
|
||||
echo <<<EOF
|
||||
Usage:
|
||||
php luminous.php [OPTIONS] [SOURCE_CODE]
|
||||
|
||||
SOURCE_CODE may be omitted if you specify -i. Use '-' to read code from stdin.
|
||||
|
||||
Options:
|
||||
-f <format> Output format. This can be:
|
||||
'html' - An HTML snippet (div). CSS is not included
|
||||
on the page, the style-sheets must be included by
|
||||
hand.
|
||||
'html-full' - A full HTML page. CSS is embedded.
|
||||
'latex' - A LaTeX document.
|
||||
Default: 'html-full'
|
||||
-h <height> Constrains the height of the widget with 'html'
|
||||
formatter. Has no effect on other formatters.
|
||||
Default: 0
|
||||
-i <filename> Input file. If this is omitted, SOURCE_CODE is used.
|
||||
-l <language> Language code. If this is omitted, the language is
|
||||
guessed.
|
||||
-o <filename> Output file to write. If this is omitted, stdout is
|
||||
used.
|
||||
-t <theme> Theme to use. See --list-themes for valid themes
|
||||
--no-numbers Disables line numbering
|
||||
|
||||
--list-codes Lists valid language codes and exits
|
||||
--list-themes Lists valid themes and exits
|
||||
|
||||
--help Display this text and exit
|
||||
--version Display version number and exit
|
||||
|
||||
EOF;
|
||||
}
|
||||
|
||||
|
||||
function error($string) {
|
||||
echo "Error: $string
|
||||
see --help for help
|
||||
";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
function set_lookahead($option, $i) {
|
||||
global $argv;
|
||||
if (isset($argv[$i+1]))
|
||||
$this->options[$this->cmd_option_map[$option]] = $argv[$i+1];
|
||||
else self::error('Missing option for ' . $option);
|
||||
}
|
||||
|
||||
|
||||
function list_codes() {
|
||||
foreach(luminous::scanners() as $name=>$codes) {
|
||||
echo sprintf("%s: %s\n", $name, join(', ', $codes));
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
function list_themes() {
|
||||
echo preg_replace('/\.css$/m', '', join("\n", luminous::themes()) . "\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
function parse_args() {
|
||||
global $argv, $argc;
|
||||
for($i=1; $i<$argc; $i++) {
|
||||
$a = $argv[$i];
|
||||
|
||||
if (isset($this->cmd_option_map[$a])) {
|
||||
$this->set_lookahead($a, $i++);
|
||||
}
|
||||
elseif ($a === '--list-codes') {
|
||||
self::list_codes();
|
||||
}
|
||||
elseif ($a === '--list-themes') {
|
||||
self::list_themes();
|
||||
}
|
||||
elseif ($a === '--help') {
|
||||
self::print_help();
|
||||
exit(0);
|
||||
}
|
||||
elseif($a === '--version') {
|
||||
echo LUMINOUS_VERSION;
|
||||
echo "\n";
|
||||
exit(0);
|
||||
}
|
||||
elseif ($a === '--no-numbers') {
|
||||
$this->options['line-numbers'] = false;
|
||||
}
|
||||
else {
|
||||
if ($this->options['code'] !== null) {
|
||||
self::error('Unknown option: ' . $a);
|
||||
} else {
|
||||
$this->options['code'] = $a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function highlight() {
|
||||
$this->parse_args();
|
||||
|
||||
// figure out the code
|
||||
|
||||
// error cases are:
|
||||
// no input file or source code,
|
||||
if ($this->options['code'] === null
|
||||
&& $this->options['input-file'] === null) {
|
||||
$this->error('No input file or source code specified');
|
||||
}
|
||||
// or both input file and source code
|
||||
elseif ($this->options['code'] !== null
|
||||
&& $this->options['input-file'] !== null) {
|
||||
$this->error('Input file (-i) and source code specified. You probably '
|
||||
. 'didn\'t mean this');
|
||||
}
|
||||
|
||||
// is there an input file? use that.
|
||||
if ($this->options['input-file'] !== null) {
|
||||
$c = @file_get_contents($this->options['input-file']);
|
||||
if ($c === false) {
|
||||
$this->error('Could not read from ' . $this->options['input-file']);
|
||||
}
|
||||
else {
|
||||
$this->options['code'] = $c;
|
||||
}
|
||||
}
|
||||
// else we're expecting code to have been given on the command line,
|
||||
// but it might be '-' which means read stdin
|
||||
elseif ($this->options['code'] === '-') {
|
||||
$code = '';
|
||||
while (($line = fgets(STDIN)) !== false)
|
||||
$code .= $line;
|
||||
$this->options['code'] = $code;
|
||||
}
|
||||
|
||||
// set the formatter
|
||||
luminous::set('format', $this->options['format']);
|
||||
// lame check that the formatter is okay
|
||||
try { luminous::formatter(); }
|
||||
catch(Exception $e) {
|
||||
$this->error('Unknown formatter ' . $this->options['format']);
|
||||
}
|
||||
|
||||
// set the theme
|
||||
$valid_themes = luminous::themes();
|
||||
$theme = $this->options['theme'];
|
||||
if (!preg_match('/\.css$/', $theme)) $theme .= '.css';
|
||||
if (!luminous::theme_exists($theme)) {
|
||||
$this->error('No such theme: ' . $theme);
|
||||
} else {
|
||||
luminous::set('theme', $theme);
|
||||
}
|
||||
|
||||
|
||||
// set the language
|
||||
if ($this->options['lang'] === null) {
|
||||
// guessing
|
||||
$this->options['lang'] = luminous::guess_language($this->options['code']);
|
||||
}
|
||||
|
||||
// user provided language
|
||||
$scanners = luminous::scanners();
|
||||
$valid_scanner = false;
|
||||
foreach($scanners as $lang=>$codes) {
|
||||
if (in_array($this->options['lang'], $codes)) {
|
||||
$valid_scanner = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$valid_scanner) $this->error('No such language: '
|
||||
. $this->options['lang']);
|
||||
|
||||
|
||||
// other options
|
||||
luminous::set('max-height', $this->options['height']);
|
||||
luminous::set('line-numbers', $this->options['line-numbers']);
|
||||
|
||||
$h = luminous::highlight($this->options['lang'], $this->options['code']);
|
||||
if ($this->options['output-file'] !== null) {
|
||||
$r = @file_put_contents($this->options['output-file'], $h, LOCK_EX);
|
||||
if ($r === false)
|
||||
$this->error('Could not write to ' . $this->options['output-file']);
|
||||
} else {
|
||||
echo $h;
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
$luminous_cli = new LuminousCLI();
|
||||
$luminous_cli->highlight();
|
||||
}
|
||||
main();
|
||||
|
||||
///@endcond
|
||||
|
|
@ -1,296 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @cond CORE
|
||||
* @brief A collection of useful common filters.
|
||||
*
|
||||
* Filters are either stream filters or individual filters.
|
||||
* Stream filters operate on the entire token stream, and return the new
|
||||
* token stream. Individual filters operate on individual tokens (bound by type),
|
||||
* and return the new token. Any publicly available member here is one of those,
|
||||
* therefore the return and param documents are omitted.
|
||||
*
|
||||
*/
|
||||
// Poor man's namespace.
|
||||
class LuminousFilters {
|
||||
|
||||
/**
|
||||
* @brief Gets the expected number of arguments to a doc-comment command/tag
|
||||
* @param $command the name of the command
|
||||
* @returns The expected number of arguments for a command, this is either
|
||||
* 0 or 1 at the moment
|
||||
* @internal
|
||||
*/
|
||||
private static function doxygen_arg_length($command) {
|
||||
switch(strtolower($command)) {
|
||||
case "addtogroup":
|
||||
case "category":
|
||||
case "class":
|
||||
case "cond":
|
||||
case "def":
|
||||
case "defgroup":
|
||||
case "dir":
|
||||
case "elseif":
|
||||
case "enum":
|
||||
case "exception":
|
||||
case "example":
|
||||
case "extends":
|
||||
case "if":
|
||||
case "ifnot":
|
||||
case "file":
|
||||
case "headerfile":
|
||||
case "implements":
|
||||
case "ingroup":
|
||||
case "interface":
|
||||
case "memberof":
|
||||
case "namespace":
|
||||
case "package":
|
||||
case "page":
|
||||
case "par":
|
||||
case "param":
|
||||
case "relates":
|
||||
case "relatesalso":
|
||||
case "retval":
|
||||
case 'see':
|
||||
case 'since':
|
||||
case "tparam":
|
||||
case "throw":
|
||||
case "throws":
|
||||
case "weakgroup":
|
||||
case "xrefitem":
|
||||
return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief callback to doxygenize
|
||||
* Highlights Doxygen-esque doc-comment syntax.
|
||||
* This is a callback to doxygenize().
|
||||
* @return the highlighted string
|
||||
* @internal
|
||||
*/
|
||||
private static function doxygenize_cb($matches) {
|
||||
$lead = $matches[1];
|
||||
$tag_char = $matches[2];
|
||||
$tag = $matches[3];
|
||||
|
||||
$line = "";
|
||||
if (isset($matches[4]))
|
||||
$line = $matches[4];
|
||||
|
||||
$len = -1;
|
||||
// JSDoc-like
|
||||
$l_ = ltrim($line);
|
||||
if (isset($l_[0]) && $l_[0] === '{') {
|
||||
$line = preg_replace('/({[^}]*})/', "<DOCPROPERTY>$1</DOCPROPERTY>", $line);
|
||||
return "$lead<DOCTAG>$tag_char$tag</DOCTAG>$line";
|
||||
}
|
||||
else
|
||||
$len = self::doxygen_arg_length($tag);
|
||||
|
||||
if($len === 0)
|
||||
return "$lead<DOCTAG>$tag_char$tag</DOCTAG>$line";
|
||||
else {
|
||||
$l = explode(' ', $line);
|
||||
$start = "$lead<DOCTAG>$tag_char$tag</DOCTAG><DOCPROPERTY>";
|
||||
|
||||
$j = 0;
|
||||
$c = count($l);
|
||||
for($i=0; $j<$len && $i<$c; $i++)
|
||||
{
|
||||
$s = $l[$i];
|
||||
$start .= $s . ' ';
|
||||
unset($l[$i]);
|
||||
if (trim($s) !== '')
|
||||
$j++;
|
||||
}
|
||||
$start = preg_replace('/ $/', '', $start);
|
||||
$start .= "</DOCPROPERTY>";
|
||||
$l = array_values($l);
|
||||
if (!empty($l)) $start .= ' ';
|
||||
$start .= implode(' ', $l);
|
||||
return $start;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Highlights doc-comment tags inside a comment block.
|
||||
*
|
||||
* @see generic_doc_comment
|
||||
* @internal
|
||||
*/
|
||||
static function doxygenize($token) {
|
||||
$token = LuminousUtils::escape_token($token);
|
||||
$token[1] = preg_replace_callback("/(^(?>[\/\*#\s\{]*))([\@\\\])([\\w]*)(\}|[ \t]+.*?)?$/m",
|
||||
array('LuminousFilters', 'doxygenize_cb'), $token[1]);
|
||||
return $token;
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Generic filter to highlight JavaDoc, PHPDoc, Doxygen, JSdoc, and similar doc comment syntax.
|
||||
*
|
||||
* A cursory check will be performed to try to validate that the token
|
||||
* really is a doc-comment, it does this by checking for common formats.
|
||||
*
|
||||
* If the check is successful, the token will be switched to type
|
||||
* 'DOCCOMMENT' and its doc-tags will be highlighted
|
||||
*
|
||||
* This is a wrapper around doxygenize(). If the checks are not necessary,
|
||||
* or incorrect for your situation, you may instead choose to use
|
||||
* doxygenize() directly.
|
||||
*/
|
||||
static function generic_doc_comment($token) {
|
||||
// checks if a comment is in the form:
|
||||
// xyyz where x may = y but y != z.
|
||||
// This matches, say, /** comment but does not match /********/
|
||||
// same with /// comment but not ///////////////
|
||||
$s = $token[1];
|
||||
if (isset($s[3])
|
||||
&& ($s[2] === $s[1] || $s[2] === '!')
|
||||
&& !ctype_space($s[0])
|
||||
&& !ctype_space($s[1])
|
||||
&& $s[3] !== $s[2]
|
||||
)
|
||||
{
|
||||
$token[0] = 'DOCCOMMENT';
|
||||
$token = self::doxygenize($token);
|
||||
}
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Highlights comment notes
|
||||
* Highlights keywords in comments, i.e. "NOTE", "XXX", "FIXME", "TODO",
|
||||
* "HACK", "BUG"
|
||||
*/
|
||||
static function comment_note($token) {
|
||||
$token = LuminousUtils::escape_token($token);
|
||||
$token[1] = preg_replace('/\\b(?:NOTE|XXX|FIXME|TODO|HACK|BUG):?/',
|
||||
'<COMMENT_NOTE>$0</COMMENT_NOTE>', $token[1]);
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Highlights generic escape sequences in strings
|
||||
* Highlights escape sequences in strings. There is no checking on which
|
||||
* sequences are legal, this is simply a generic function which checks for
|
||||
* \\u... unicode, \\d... octal, \\x... hex and finally just any character
|
||||
* following a backslash.
|
||||
*/
|
||||
static function string($token) {
|
||||
if (strpos($token[1], '\\') === false) return $token;
|
||||
|
||||
$token = LuminousUtils::escape_token($token);
|
||||
$token[1] = preg_replace('/
|
||||
\\\\
|
||||
(?:
|
||||
(?:u[a-f0-9]{4,8}) # unicode
|
||||
|\d{1,3} # octal
|
||||
|x[a-fA-F0-9]{2} # hex
|
||||
|. # whatever
|
||||
)
|
||||
/xi', '<ESC>$0</ESC>', $token[1]);
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tries to highlight PCRE style regular expression syntax
|
||||
*/
|
||||
static function pcre($token, $delimited=true) {
|
||||
$token = self::string($token);
|
||||
$token = LuminousUtils::escape_token($token);
|
||||
$str = &$token[1];
|
||||
$flags = array();
|
||||
if ($delimited) {
|
||||
$str = preg_replace('/^[^[:alnum:]<>\s]/', '<DELIMITER>$0</DELIMITER>', $str);
|
||||
if (preg_match("/[[:alpha:]]+$/", $str, $matches)){
|
||||
$m = $matches[0];
|
||||
$flags = str_split($m);
|
||||
$str = preg_replace("/((?<!\A)[^[:alnum:]\s<>])([[:alpha:]]+)$/",
|
||||
"<DELIMITER>$1</DELIMITER><KEYWORD>$2</KEYWORD>", $str);
|
||||
} else
|
||||
$str = preg_replace('/[^[:alnum:]<>]$/', '<DELIMITER>$0</DELIMITER>', $str);
|
||||
|
||||
}
|
||||
|
||||
$str = preg_replace("/((?<!\\\)[\*\+\.|])|((?<![\(\\\])\?)/",
|
||||
"<REGEX_OPERATOR>$0</REGEX_OPERATOR>", $str);
|
||||
$str = preg_replace("/(?<=\()\?(?:(?:[a-zA-Z:!|=])|(?:(?:<)[=!]))/",
|
||||
"<REGEX_SUBPATTERN>$0</REGEX_SUBPATTERN>", $str);
|
||||
$str = preg_replace("/(?<!\\\)[\(\)]/",
|
||||
"<REGEX_SUBPATTERN_MARKER>$0</REGEX_SUBPATTERN_MARKER>", $str);
|
||||
$str = preg_replace("/(?<!\\\)[\[\]]/",
|
||||
"<REGEX_CLASS_MARKER>$0</REGEX_CLASS_MARKER>", $str);
|
||||
$str = preg_replace("/(?<!\\\)
|
||||
\{
|
||||
(
|
||||
((?>\d+)(,(?>\d+)?)?)
|
||||
|
|
||||
(,(?>\d+))
|
||||
)
|
||||
\}/x", "<REGEX_REPEAT_MARKER>$0</REGEX_REPEAT_MARKER>", $str);
|
||||
|
||||
// extended regex: # signifies a comment
|
||||
if (in_array('x', $flags))
|
||||
$str = preg_replace('/(?<!\\\)#.*$/m', '<COMMENT>$0</COMMENT>',
|
||||
$str);
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Translates any token type of an uppercase/numeric IDENT to 'CONSTANT'
|
||||
*/
|
||||
static function upper_to_constant($token) {
|
||||
// check for this because it may have been mapped to a function or something
|
||||
if ($token[0] === 'IDENT' && preg_match('/^[A-Z_][A-Z_0-9]{3,}$/', $token[1]))
|
||||
$token[0] = 'CONSTANT';
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Translates anything of type 'IDENT' to the null type
|
||||
*/
|
||||
static function clean_ident($token) {
|
||||
if ($token[0] === 'IDENT') $token[0] = null;
|
||||
return $token;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Attempts to apply OO syntax highlighting
|
||||
*
|
||||
* Tries to apply generic OO syntax highlighting. Any identifer immediately
|
||||
* preceding a '.', '::' or '->' token is mapped to an 'OO'.
|
||||
* Any identifer token immediatel following any of those tokens is mapped to
|
||||
* an 'OBJ'.
|
||||
* This is a stream filter.
|
||||
*/
|
||||
static function oo_stream_filter($tokens) {
|
||||
$c = count($tokens);
|
||||
for($i=0; $i<$c; $i++) {
|
||||
if ($tokens[$i][0] !== 'IDENT') continue;
|
||||
if ($i > 0) {
|
||||
$s = $tokens[$i-1][1];
|
||||
if ($s === '.' || $s === '->' || $s === '::') {
|
||||
$tokens[$i][0] = 'OO';
|
||||
$i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ($i < $c-1) {
|
||||
$s = $tokens[$i+1][1];
|
||||
if ($s === '.' || $s === '->' || $s === '::') {
|
||||
$tokens[$i][0] = 'OBJ';
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
// end CORE
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,84 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @cond CORE
|
||||
* @brief A basic preg_match wrapper which caches its results
|
||||
*
|
||||
* @note This class is used by Scanner and should not need to be used by
|
||||
* anything else.
|
||||
*
|
||||
* A class encapsulating the process of searching for a substring efficiently
|
||||
* it handles caching of results.
|
||||
*
|
||||
* @warning One instance should be used only incrementally along a string.
|
||||
* i.e. do not call it with index = 5 then index = 1.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
*/
|
||||
class LuminousStringSearch
|
||||
{
|
||||
/// A copy of the string to operate on.
|
||||
private $string;
|
||||
|
||||
/**
|
||||
* The cache is stored as a map of pattern => result,
|
||||
* the result is an array of:
|
||||
* (0=>index, 1=>match_groups), OR, it is false if there are no more results
|
||||
* left in the string.
|
||||
*/
|
||||
private $cache = array();
|
||||
|
||||
public function __construct($str) {
|
||||
$this->string = $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs a search for the given pattern past the given index.
|
||||
* @param $search the pattern to search for
|
||||
* @param $index the minimum string index (offset) of a result
|
||||
* @param $matches a reference to the return location of the match groups
|
||||
* @return the index or false if no match is found.
|
||||
*/
|
||||
public function
|
||||
match($search, $index, &$matches) {
|
||||
$r = false; // return value
|
||||
|
||||
if (isset($this->cache[$search])) {
|
||||
$a = $this->cache[$search];
|
||||
if ($a === false) return false; // no more results
|
||||
|
||||
$r = $a[0];
|
||||
$matches = $a[1];
|
||||
assert($matches !== null);
|
||||
|
||||
if ($r >= $index) // cache is good!
|
||||
return $r;
|
||||
}
|
||||
// cache not set, or out of date, we have to perform the match
|
||||
if (!($ret = preg_match($search, $this->string, $matches_,
|
||||
PREG_OFFSET_CAPTURE, $index))) {
|
||||
if ($ret === false && LUMINOUS_DEBUG) {
|
||||
throw new Exception('preg_match returned false for pattern: "'
|
||||
. $search . '", with code: ' . LuminousUtils::pcre_error_decode(
|
||||
preg_last_error()) . " with string length " . strlen($this->string)
|
||||
. " and offset " . $index
|
||||
);
|
||||
}
|
||||
$this->cache[$search] = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = $matches_[0][1];
|
||||
// strip the offsets from the match_groups
|
||||
foreach($matches_ as $i=>&$v)
|
||||
$v = $v[0];
|
||||
|
||||
$this->cache[$search] = array($r, $matches_);
|
||||
|
||||
$matches = $matches_;
|
||||
return $r;
|
||||
}
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @cond CORE
|
||||
* @brief A set of pre-defined patterns to match various common tokens
|
||||
*/
|
||||
abstract class LuminousTokenPresets {
|
||||
|
||||
/// multi-line double quoted string using backslash escapes
|
||||
static $DOUBLE_STR = '/" (?> [^"\\\\]+ | \\\\.)* (?:"|$)/xs';
|
||||
|
||||
/// single line double quoted string using backslash escapes
|
||||
static $DOUBLE_STR_SL = "/\"(?> [^\\\\\"\n]+ | \\\\.)*(?:\$|\")/xms";
|
||||
|
||||
/// multi-line single quote string using backslash escapes
|
||||
static $SINGLE_STR = "/' (?> [^'\\\\]+ | \\\\.)* (?:'|\$)/xs";
|
||||
|
||||
/// single line single quoted string using backslash escapes
|
||||
static $SINGLE_STR_SL = "/'(?> [^\\\\'\n]+ | \\\\.)*(?:\$|')/xms";
|
||||
|
||||
/// Single quoted c-style character
|
||||
static $CHAR = "(?: \\\\(?: x[A-F0-9]{1,2}| . ) | . ) (?: '|\$)/ixm";
|
||||
|
||||
/// hexadecimal literal
|
||||
static $NUM_HEX = '/0[Xx][a-fA-F0-9]+/';
|
||||
|
||||
/// Real number, i.e. an integer or a float, optionally with an exponent
|
||||
static $NUM_REAL = '/
|
||||
(?: \d+ (?: \.\d+ )? | \.?\d+) # int, fraction or significand
|
||||
(?:e[+-]?\d+)? # exponent
|
||||
/ix';
|
||||
|
||||
/// Single line c++ style comment
|
||||
static $C_COMMENT_SL = '% // .* %x';
|
||||
|
||||
/// Multiline C style comment
|
||||
static $C_COMMENT_ML = '% / \* (?> [^\\*]+ | \\*(?!/) )* (?: \\*/ | $) %sx';
|
||||
|
||||
/// Perl/Python/Ruby style hash-comment (single line)
|
||||
static $PERL_COMMENT = '/#.*/';
|
||||
|
||||
/// SQL style single quoted string using '' to escape
|
||||
static $SQL_SINGLE_STR = "/ ' (?> [^']+ | '' )* (?: '|\$)/x";
|
||||
|
||||
/// SQL style single quoted string using '' or \' to escape
|
||||
static $SQL_SINGLE_STR_BSLASH = "/ ' (?> [^'\\\\]+ | '' | \\\\. )* (?: '|\$)/x";
|
||||
|
||||
}
|
||||
/// @endcond
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @cond CORE
|
||||
* @brief A set of utility functions for scanners
|
||||
*/
|
||||
class LuminousUtils {
|
||||
|
||||
/**
|
||||
* @brief Tries to balance a delimiter
|
||||
*
|
||||
* Tries to 'balance' a single character delimiter, i.e:
|
||||
* '(' is mapped to ')'
|
||||
* '{' is mapped to '}',
|
||||
* '[' is mapped to ']',
|
||||
* '<' is mapped to '>'
|
||||
* Any other character is mapped to itself.
|
||||
*
|
||||
* @param $delimiter the left/opening delimiter to try to balance
|
||||
* @return The corresponding close delimiter character, or the input
|
||||
* character.
|
||||
*/
|
||||
static function balance_delimiter($delimiter) {
|
||||
switch($delimiter) {
|
||||
case '(' : return ')';
|
||||
case '{' : return '}';
|
||||
case '[' : return ']';
|
||||
case '<' : return '>';
|
||||
default: return $delimiter;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Escapes a string suitable for use in XML
|
||||
*
|
||||
* Escapes a string according to the Luminous internal escaping format
|
||||
* (this is currently htmlspecialchars with ENT_NOQUOTES.)
|
||||
* @param $string the string to escape
|
||||
* @return the escaped string
|
||||
*/
|
||||
static function escape_string($string) {
|
||||
return htmlspecialchars($string, ENT_NOQUOTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Escapes a token so its string is suitable for use in XML
|
||||
*
|
||||
* Escapes a token. If the token is already escaped, nothing changes.
|
||||
* If the token is not escaped, the escaped flag is set (index 2) and the
|
||||
* token text (index 1) is escaped according to the internal escaping format
|
||||
* @param $token the token to escape
|
||||
* @return the escaped token
|
||||
*/
|
||||
static function escape_token($token) {
|
||||
$esc = &$token[2];
|
||||
if (!$esc) {
|
||||
$str = &$token[1];
|
||||
$str = htmlspecialchars($str, ENT_NOQUOTES);
|
||||
$esc = true;
|
||||
}
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wraps a block of text in an XML tag
|
||||
*
|
||||
* Tags a block of text. The block is assumed to have been escaped correctly
|
||||
* with LuminousUtils::escape_string.
|
||||
* @param $type the type to tag the string as, this is the token name
|
||||
* @param $block the block of text
|
||||
* @param $split_multiline if this is set to true, the tags are closed at
|
||||
* the end of each line and re-opened again on the next line. This is
|
||||
* useful for output formats like HTML, where spanning multiple lines
|
||||
* could break the markup
|
||||
* @return The tagged block of text. This resembles an XML fragment.
|
||||
*/
|
||||
static function tag_block($type, $block, $split_multiline=true) {
|
||||
if ($type === null) return $block;
|
||||
$open = '<' . $type . '>';
|
||||
$close = '</' . $type . '>';
|
||||
if ($split_multiline)
|
||||
return $open . str_replace("\n", $close . "\n" . $open, $block) .
|
||||
$close;
|
||||
else
|
||||
return $open . $block . $close;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes PCRE error codes to human readable strings
|
||||
*
|
||||
* Decodes a PCRE error code, which was returned by preg_last_error(), to
|
||||
* something readable
|
||||
* @param $errcode the error code
|
||||
* @return the error description, as string. This is currently the same
|
||||
* as the constant name, so the constant PREG_NO_ERROR is mapped to the
|
||||
* string 'PREG_NO_ERROR'
|
||||
*/
|
||||
static function pcre_error_decode($errcode) {
|
||||
switch ($errcode) {
|
||||
case PREG_NO_ERROR:
|
||||
return 'PREG_NO_ERROR';
|
||||
case PREG_INTERNAL_ERROR:
|
||||
return 'PREG_INTERNAL_ERROR';
|
||||
case PREG_BACKTRACK_LIMIT_ERROR:
|
||||
return 'PREG_BACKTRACK_LIMIT_ERROR';
|
||||
case PREG_RECURSION_LIMIT_ERROR:
|
||||
return 'PREG_RECURSION_LIMIT_ERROR';
|
||||
case PREG_BAD_UTF8_ERROR:
|
||||
return 'PREG_BAD_UTF8_ERROR';
|
||||
case PREG_BAD_UTF8_OFFSET_ERROR:
|
||||
return 'PREG_BAD_UTF8_OFFSET_ERROR';
|
||||
default:
|
||||
return "Unknown error code `$errcode'";
|
||||
}
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
// ends CORE
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<?php
|
||||
|
||||
define('LUMINOUS_DEBUG', false);
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
// A few things to make Doxygen a little nicer. No code here.
|
||||
|
||||
/**
|
||||
* @mainpage
|
||||
*
|
||||
* This is the API documentation for Luminous, a PHP syntax highlighter.
|
||||
* This is mostly for development purposes, and not a lot of use to users.
|
||||
*
|
||||
* However, users may be interested in the \link luminous user's API \endlink
|
||||
* and the LuminousOptions class
|
||||
*
|
||||
*
|
||||
* Luminous site: http://luminous.asgaard.co.uk
|
||||
*
|
||||
* User's documentation: http://luminous.asgaard.co.uk/index.php/docs/show/index
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
<?php
|
||||
/// @cond ALL
|
||||
|
||||
|
||||
/**
|
||||
* \file luminous_formatter.class.php
|
||||
* \brief Formatting logic -- converts Luminous output into displayable formats
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Abstract class to convert Luminous output into a universal format.
|
||||
*
|
||||
* Abstract base class to implement an output formatter. A formatter
|
||||
* will convert Luminous's tags into some kind of output (e.g. HTML), by
|
||||
* overriding the method Format().
|
||||
*/
|
||||
abstract class LuminousFormatter {
|
||||
/// Number of chars to wrap at
|
||||
public $wrap_length = 120;
|
||||
/// Don't use this yet.
|
||||
public $language_specific_tags = false;
|
||||
/**
|
||||
* Tab width, in spaces. If this is -1 or 0, tabs will not be converted. This
|
||||
* is not recommended as browsers may render tabs as different widths which
|
||||
* will break the wrapping.
|
||||
*/
|
||||
public $tab_width = 2;
|
||||
|
||||
/// Whether or not to add line numbering
|
||||
public $line_numbers = true;
|
||||
/// Number of first line
|
||||
public $start_line = 1;
|
||||
|
||||
/// An array of lines to be highlighted initially, if the formatter supports
|
||||
/// it
|
||||
public $highlight_lines = array();
|
||||
|
||||
/// sets whether or not to link URIs.
|
||||
public $link = true;
|
||||
|
||||
/**
|
||||
* Height of the resulting output. This may or may not make any sense
|
||||
* depending on the output format.
|
||||
*
|
||||
* Use 0 or -1 for no limit.
|
||||
*/
|
||||
public $height = 0;
|
||||
|
||||
|
||||
/**
|
||||
* The language of the source code being highlighted. Formatters may choose
|
||||
* to do something with this.
|
||||
*/
|
||||
public $language = null;
|
||||
|
||||
|
||||
/**
|
||||
* The main method for interacting with formatter objects.
|
||||
* @param src the input string, which is of the form output by an instance of
|
||||
* Luminous.
|
||||
* @return The input string reformatted to some other specification.
|
||||
*/
|
||||
public abstract function format($src);
|
||||
|
||||
/**
|
||||
* If relevant, the formatter should implement this and use LuminousCSSParser
|
||||
* to port the theme.
|
||||
* @param $theme A CSS string representing the theme
|
||||
*/
|
||||
public function set_theme($theme)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Handles line wrapping.
|
||||
* @param line the line which needs to be broken. This is a reference, which
|
||||
* will be operated upon. After calling, $line will have appropriate line
|
||||
* breaks to wrap to the given width, and will contain at least one line break
|
||||
* at the end.
|
||||
* @param wrap_length the width to wrap to.
|
||||
*
|
||||
* @return the number of lines it was broken up into (1 obviously means no
|
||||
* wrapping occurred.).
|
||||
*
|
||||
* @todo wrap to indent? or not? hm.
|
||||
*
|
||||
*/
|
||||
protected static function wrap_line(&$line, $wrap_length) {
|
||||
// The vast majority of lines will not need wrapping so it pays to
|
||||
// check this first.
|
||||
if ($wrap_length <= 0 || !isset($line[$wrap_length])
|
||||
|| strlen(strip_tags($line)) < $wrap_length) {
|
||||
$line .= "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
$line_split = preg_split('/((?:<.*?>)|(?:&.*?;)|[ \t]+)/',
|
||||
$line, -1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);
|
||||
|
||||
|
||||
$strlen = 0;
|
||||
$line_cpy = "";
|
||||
$num_lines = 1;
|
||||
|
||||
$num_open = 0;
|
||||
foreach($line_split as $l) {
|
||||
|
||||
$l0 = $l[0];
|
||||
if ($l0 === '<') {
|
||||
$line_cpy .= $l;
|
||||
continue;
|
||||
}
|
||||
|
||||
$s = strlen($l);
|
||||
|
||||
if($l0 === '&') {
|
||||
// html entity codes only count as 1 char.
|
||||
if(++$strlen > $wrap_length) {
|
||||
$strlen = 1;
|
||||
$line_cpy .= "\n";
|
||||
$num_lines++;
|
||||
}
|
||||
$line_cpy .= $l;
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($s+$strlen <= $wrap_length) {
|
||||
$line_cpy .= $l;
|
||||
$strlen += $s;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($s <= $wrap_length) {
|
||||
$line_cpy .= "\n" . $l;
|
||||
$num_lines++;
|
||||
$strlen = $s;
|
||||
continue;
|
||||
}
|
||||
// at this point, the line needs wrapping.
|
||||
|
||||
// bump us up to the next line
|
||||
$diff = $wrap_length-$strlen;
|
||||
|
||||
$line_cpy .= substr($l, 0, $diff) . "\n";
|
||||
$l_ = substr($l, $diff);
|
||||
// now start copying.
|
||||
$strlen = 0;
|
||||
// this would probably be marginally faster if it did its own arithmetic
|
||||
// instead of calling strlen
|
||||
|
||||
while (strlen($l_) > 0) {
|
||||
$strl = strlen($l_);
|
||||
$num_lines++;
|
||||
|
||||
if ($strl > $wrap_length) {
|
||||
$line_cpy .= substr($l_, 0, $wrap_length) . "\n";
|
||||
$l_ = substr($l_, $wrap_length);
|
||||
} else {
|
||||
$line_cpy .= $l_;
|
||||
$strlen = $strl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$line = $line_cpy . "\n";
|
||||
|
||||
return $num_lines;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @endcond
|
||||
|
|
@ -1,344 +0,0 @@
|
|||
<?php
|
||||
/// @cond ALL
|
||||
|
||||
/**
|
||||
* Collection of templates and templating utilities
|
||||
*/
|
||||
class LuminousHTMLTemplates {
|
||||
|
||||
// NOTE Don't worry about whitespace in the templates - it gets stripped from the innerHTML,
|
||||
// so the <pre>s aren't affected. Make it readable :)
|
||||
|
||||
/// Normal container
|
||||
const container_template = '
|
||||
<div
|
||||
class="luminous"
|
||||
data-language="{language}"
|
||||
style="{height_css}"
|
||||
>
|
||||
{subelement}
|
||||
</div>';
|
||||
|
||||
/// Inline code container
|
||||
const inline_template = '
|
||||
<div
|
||||
class="luminous inline"
|
||||
data-language="{language}"
|
||||
>
|
||||
{subelement}
|
||||
</div>';
|
||||
|
||||
/// line number-less
|
||||
const numberless_template = '
|
||||
<pre
|
||||
class="code"
|
||||
>
|
||||
{code}
|
||||
</pre>';
|
||||
|
||||
/// line numbered
|
||||
// NOTE: there's a good reason we use tables here and that's because
|
||||
// nothing else works reliably.
|
||||
const numbered_template = '
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<pre class="line-numbers">
|
||||
{line_numbers}
|
||||
</pre>
|
||||
</td>
|
||||
|
||||
<td class="code-container">
|
||||
<pre class="code numbered"
|
||||
data-startline="{start_line}"
|
||||
data-highlightlines="{highlight_lines}"
|
||||
>
|
||||
{code}
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>';
|
||||
|
||||
|
||||
|
||||
|
||||
private static function _strip_template_whitespace_cb($matches) {
|
||||
return ($matches[0][0] === '<')? $matches[0] : '';
|
||||
}
|
||||
private static function _strip_template_whitespace($string) {
|
||||
return preg_replace_callback('/\s+|<[^>]++>/',
|
||||
array('self', '_strip_template_whitespace_cb'),
|
||||
$string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a string with a given set of values
|
||||
* The format syntax uses {xyz} as a placeholder, which will be
|
||||
* substituted from the 'xyz' key from $variables
|
||||
*
|
||||
* @param $template The template string
|
||||
* @param $variables An associative (keyed) array of values to be substituted
|
||||
* @param $strip_whitespace_from_template If @c TRUE, the template's whitespace is removed.
|
||||
* This allows templates to be written to be easeier to read, without having to worry about
|
||||
* the pre element inherting any unintended whitespace
|
||||
*/
|
||||
public static function format($template, $variables, $strip_whitespace_from_template = true) {
|
||||
|
||||
if ($strip_whitespace_from_template) {
|
||||
$template = self::_strip_template_whitespace($template);
|
||||
}
|
||||
|
||||
foreach($variables as $search => $replace) {
|
||||
$template = str_replace("{" . $search . "}", $replace, $template);
|
||||
}
|
||||
return $template;
|
||||
}
|
||||
}
|
||||
|
||||
class LuminousFormatterHTML extends LuminousFormatter {
|
||||
|
||||
// overridden by inline formatter
|
||||
protected $inline = false;
|
||||
public $height = 0;
|
||||
/**
|
||||
* strict HTML standards: the target attribute won't be used in links
|
||||
* \since 0.5.7
|
||||
*/
|
||||
public $strict_standards = false;
|
||||
|
||||
private function height_css() {
|
||||
$height = trim('' . $this->height);
|
||||
$css = '';
|
||||
if (!empty($height) && (int)$height > 0) {
|
||||
// look for units, use px is there are none
|
||||
if (!preg_match('/\D$/', $height)) $height .= 'px';
|
||||
$css = "max-height: {$height};";
|
||||
}
|
||||
else
|
||||
$css = '';
|
||||
return $css;
|
||||
}
|
||||
|
||||
private static function template_cb($matches) {
|
||||
|
||||
}
|
||||
|
||||
// strips out unnecessary whitespace from a template
|
||||
private static function template($t, $vars=array()) {
|
||||
$t = preg_replace_callback('/\s+|<[^>]++>/',
|
||||
array('self', 'template_cb'),
|
||||
$t);
|
||||
array_unshift($vars, $t);
|
||||
$code = call_user_func_array('sprintf', $vars);
|
||||
return $code;
|
||||
}
|
||||
|
||||
private function lines_numberless($src) {
|
||||
$lines = array();
|
||||
$lines_original = explode("\n", $src);
|
||||
foreach($lines_original as $line) {
|
||||
$l = $line;
|
||||
$num = $this->wrap_line($l, $this->wrap_length);
|
||||
// strip the newline if we're going to join it. Seems the easiest way to
|
||||
// fix http://code.google.com/p/luminous/issues/detail?id=10
|
||||
$l = substr($l, 0, -1);
|
||||
$lines[] = $l;
|
||||
}
|
||||
$lines = implode("\n", $lines);
|
||||
return $lines;
|
||||
}
|
||||
|
||||
private function format_numberless($src) {
|
||||
return LuminousHTMLTemplates::format(
|
||||
LuminousHTMLTemplates::numberless_template,
|
||||
array(
|
||||
'height_css' => $this->height_css(),
|
||||
'code' => $this->lines_numberless($src)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function format($src) {
|
||||
|
||||
$line_numbers = false;
|
||||
|
||||
if ($this->link) $src = $this->linkify($src);
|
||||
|
||||
$code_block = null;
|
||||
if ($this->line_numbers) {
|
||||
$code_block = $this->format_numbered($src);
|
||||
}
|
||||
else {
|
||||
$code_block = $this->format_numberless($src);
|
||||
}
|
||||
|
||||
// convert </ABC> to </span>
|
||||
$code_block = preg_replace('/(?<=<\/)[A-Z_0-9]+(?=>)/S', 'span',
|
||||
$code_block);
|
||||
// convert <ABC> to <span class=ABC>
|
||||
$cb = create_function('$matches',
|
||||
'$m1 = strtolower($matches[1]);
|
||||
return "<span class=\'" . $m1 . "\'>";
|
||||
');
|
||||
$code_block = preg_replace_callback('/<([A-Z_0-9]+)>/', $cb, $code_block);
|
||||
|
||||
$format_data = array(
|
||||
'language' => ($this->language === null)? '' : htmlentities($this->language),
|
||||
'subelement' => $code_block,
|
||||
'height_css' => $this->height_css()
|
||||
);
|
||||
return LuminousHTMLTemplates::format(
|
||||
$this->inline? LuminousHTMLTemplates::inline_template :
|
||||
LuminousHTMLTemplates::container_template,
|
||||
$format_data
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects and links URLs - callback
|
||||
*/
|
||||
protected function linkify_cb($matches) {
|
||||
$uri = (isset($matches[1]) && strlen(trim($matches[1])))? $matches[0]
|
||||
: "http://" . $matches[0];
|
||||
|
||||
// we dont want to link if it would cause malformed HTML
|
||||
$open_tags = array();
|
||||
$close_tags = array();
|
||||
preg_match_all("/<(?!\/)([^\s>]*).*?>/", $matches[0], $open_tags,
|
||||
PREG_SET_ORDER);
|
||||
preg_match_all("/<\/([^\s>]*).*?>/", $matches[0], $close_tags,
|
||||
PREG_SET_ORDER);
|
||||
|
||||
if (count($open_tags) != count($close_tags))
|
||||
return $matches[0];
|
||||
if (isset($open_tags[0])
|
||||
&& trim($open_tags[0][1]) !== trim($close_tags[0][1])
|
||||
)
|
||||
return $matches[0];
|
||||
|
||||
$uri = strip_tags($uri);
|
||||
|
||||
$target = ($this->strict_standards)? '' : ' target="_blank"';
|
||||
return "<a href='{$uri}' class='link'{$target}>{$matches[0]}</a>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects and links URLs
|
||||
*/
|
||||
protected function linkify($src) {
|
||||
if (stripos($src, "http") === false && stripos($src, "www") === false)
|
||||
return $src;
|
||||
|
||||
$chars = "0-9a-zA-Z\$\-_\.+!\*,%";
|
||||
$src_ = $src;
|
||||
// everyone stand back, I know regular expressions
|
||||
$src = preg_replace_callback(
|
||||
"@(?<![\w])
|
||||
(?:(https?://(?:www[0-9]*\.)?) | (?:www\d*\.) )
|
||||
|
||||
# domain and tld
|
||||
(?:[$chars]+)+\.[$chars]{2,}
|
||||
# we don't include tags at the EOL because these are likely to be
|
||||
# line-enclosing tags.
|
||||
(?:[/$chars/?=\#;]+|&|<[^>]+>(?!$))*
|
||||
@xm",
|
||||
array($this, 'linkify_cb'), $src);
|
||||
// this can hit a backtracking limit, in which case it nulls our string
|
||||
// FIXME: see if we can make the above regex more resiliant wrt
|
||||
// backtracking
|
||||
if (preg_last_error() !== PREG_NO_ERROR) {
|
||||
$src = $src_;
|
||||
}
|
||||
return $src;
|
||||
}
|
||||
|
||||
|
||||
private function format_numbered($src) {
|
||||
|
||||
$lines = '<span>' .
|
||||
str_replace("\n", "\n</span><span>", $src, $num_replacements) .
|
||||
"\n</span>";
|
||||
$num_lines = $num_replacements + 1;
|
||||
|
||||
$line_numbers = '<span>' . implode('</span><span>',
|
||||
range($this->start_line, $this->start_line + $num_lines - 1, 1)
|
||||
) . '</span>';
|
||||
|
||||
|
||||
$format_data = array(
|
||||
'line_number_digits' => strlen( (string)($this->start_line) + $num_lines ), // max number of digits in the line - this is used by the CSS
|
||||
'start_line' => $this->start_line,
|
||||
'height_css' => $this->height_css(),
|
||||
'highlight_lines' => implode(',', $this->highlight_lines),
|
||||
'code' => $lines,
|
||||
'line_numbers' => $line_numbers
|
||||
);
|
||||
|
||||
return LuminousHTMLTemplates::format(
|
||||
LuminousHTMLTemplates::numbered_template,
|
||||
$format_data
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class LuminousFormatterHTMLInline extends LuminousFormatterHTML {
|
||||
|
||||
public function format($src) {
|
||||
$this->line_numbers = false;
|
||||
$this->height = 0;
|
||||
$this->inline = true;
|
||||
return parent::format($src);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class LuminousFormatterHTMLFullPage extends LuminousFormatterHTML {
|
||||
protected $theme_css = null;
|
||||
protected $css = null;
|
||||
public function set_theme($css) {
|
||||
$this->theme_css = $css;
|
||||
}
|
||||
protected function get_layout() {
|
||||
// this path info shouldn't really be here
|
||||
$path = luminous::root() . '/style/luminous.css';
|
||||
$this->css = file_get_contents($path);
|
||||
}
|
||||
public function format($src) {
|
||||
$this->height = 0;
|
||||
$this->get_layout();
|
||||
$fmted = parent::format($src);
|
||||
return <<<EOF
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title></title>
|
||||
<style type='text/css'>
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
/* luminous.css */
|
||||
{$this->css}
|
||||
/* End luminous.css */
|
||||
/* Theme CSS */
|
||||
{$this->theme_css}
|
||||
/* End theme CSS */
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Begin luminous code //-->
|
||||
$fmted
|
||||
<!-- End Luminous code //-->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
EOF;
|
||||
}
|
||||
}
|
||||
/// @endcond
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<?php
|
||||
|
||||
/// @cond ALL
|
||||
|
||||
/**
|
||||
* Identity formatter. Returns what it's given. Implemented for consistency.
|
||||
*/
|
||||
class LuminousIdentityFormatter extends LuminousFormatter {
|
||||
public function format($str) {
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
|
@ -1,200 +0,0 @@
|
|||
<?php
|
||||
/// @cond ALL
|
||||
require_once(dirname(__FILE__) . '/../utils/cssparser.class.php');
|
||||
|
||||
/**
|
||||
* LaTeX output formatter for Luminous.
|
||||
*
|
||||
* \since 0.5.4
|
||||
*/
|
||||
class LuminousFormatterLatex extends LuminousFormatter {
|
||||
|
||||
private $css = null;
|
||||
function __construct() { }
|
||||
|
||||
function set_theme($theme) {
|
||||
$this->css = new LuminousCSSParser();
|
||||
$this->css->convert($theme);
|
||||
}
|
||||
/// Converts a hexadecimal string in the form #ABCDEF to an RGB array
|
||||
/// where each element is normalised to the range 0-1
|
||||
static function hex2rgb($hex) {
|
||||
$x = hexdec(substr($hex, 1));
|
||||
$b = $x % 256;
|
||||
$g = ($x >> 8) % 256;
|
||||
$r = ($x >> 16) % 256;
|
||||
|
||||
$b /= 255.0;
|
||||
$g /= 255.0;
|
||||
$r /= 255.0;
|
||||
|
||||
$b = round($b, 2);
|
||||
$g = round($g, 2);
|
||||
$r = round($r, 2);
|
||||
|
||||
$rgb = array($r, $g, $b);
|
||||
return $rgb;
|
||||
}
|
||||
protected function linkify($src) {
|
||||
return $src;
|
||||
}
|
||||
/// Defines all the styling commands, these are obtained from the css parser
|
||||
function define_style_commands() {
|
||||
if ($this->css === null)
|
||||
throw new Exception('LaTeX formatter has not been set a theme');
|
||||
$cmds = array();
|
||||
foreach($this->css->rules() as $name=>$properties) {
|
||||
if (!preg_match('/^\w+$/', $name))
|
||||
continue;
|
||||
$cmd = "{#1}" ;
|
||||
if ($this->css->value($name, 'bold', false) === true)
|
||||
$cmd = "{\\textbf$cmd}";
|
||||
if ($this->css->value($name, 'italic', false) === true)
|
||||
$cmd = "{\\emph$cmd}";
|
||||
if (($col = $this->css->value($name, 'color', null)) !== null) {
|
||||
if (preg_match('/^#[a-f0-9]{6}$/i', $col)) {
|
||||
$rgb = self::hex2rgb($col);
|
||||
$col_str = "{$rgb[0]}, {$rgb[1]}, $rgb[2]";
|
||||
$cmd = "{\\textcolor[rgb]{{$col_str}}$cmd}";
|
||||
}
|
||||
}
|
||||
$name = str_replace('_', '', $name);
|
||||
$name = strtoupper($name);
|
||||
$cmds[] = "\\newcommand{\\lms{$name}}[1]$cmd";
|
||||
}
|
||||
|
||||
if ($this->line_numbers &&
|
||||
($col = $this->css->value('code', 'color', null)) !== null) {
|
||||
if (preg_match('/^#[a-f0-9]{6}$/i', $col)) {
|
||||
$rgb = self::hex2rgb($col);
|
||||
$col_str = "{$rgb[0]}, {$rgb[1]}, $rgb[2]";
|
||||
$cmd = "\\renewcommand{\\theFancyVerbLine}{%
|
||||
\\textcolor[rgb]{{$col_str}}{\arabic{FancyVerbLine}}}";
|
||||
$cmds[] = $cmd;
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\n", $cmds);
|
||||
}
|
||||
|
||||
function get_background_colour() {
|
||||
if (($col = $this->css->value('code', 'bgcolor', null)) !== null) {
|
||||
if (preg_match('/^#[a-f0-9]{6}$/i', $col))
|
||||
$rgb = self::hex2rgb($col);
|
||||
$col_str = "{$rgb[0]}, {$rgb[1]}, $rgb[2]";
|
||||
return "\\pagecolor[rgb]{{$col_str}}";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function format($str) {
|
||||
$out = '';
|
||||
|
||||
$verbcmd = "\\begin{Verbatim}[commandchars=\\\\\\{\}";
|
||||
if ($this->line_numbers)
|
||||
$verbcmd .= ",numbers=left,firstnumber=1,stepnumber=1";
|
||||
$verbcmd .= ']';
|
||||
// define the preamble
|
||||
$out .= <<<EOF
|
||||
\documentclass{article}
|
||||
\usepackage{fullpage}
|
||||
\usepackage{color}
|
||||
\usepackage{fancyvrb}
|
||||
\begin{document}
|
||||
{$this->define_style_commands()}
|
||||
{$this->get_background_colour()}
|
||||
|
||||
$verbcmd
|
||||
|
||||
EOF;
|
||||
|
||||
$s = '';
|
||||
$str = preg_replace('%<([^/>]+)>\s*</\\1>%', '', $str);
|
||||
$str = str_replace("\t", ' ', $str);
|
||||
|
||||
$lines = explode("\n", $str);
|
||||
|
||||
if ($this->wrap_length > 0) {
|
||||
$str = '';
|
||||
foreach($lines as $i=>$l) {
|
||||
$this->wrap_line($l, $this->wrap_length);
|
||||
$str .= $l;
|
||||
}
|
||||
}
|
||||
|
||||
$str_ = preg_split('/(<[^>]+>)/', $str, -1,
|
||||
PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
$f1 = create_function('$matches', '
|
||||
return "\\\lms" . str_replace("_", "", $matches[1]) . "{"; ');
|
||||
$f2 = create_function('$matches', '
|
||||
if ($matches[0][0] == "\\\")
|
||||
return "{\\\textbackslash}";
|
||||
return "\\\" . $matches[0];');
|
||||
|
||||
foreach($str_ as $s_) {
|
||||
if ($s_[0] === '<') {
|
||||
$s_ = preg_replace('%</[^>]+>%', '}', $s_);
|
||||
$s_ = preg_replace_callback('%<([^>]+)>%', $f1
|
||||
,$s_);
|
||||
} else {
|
||||
$s_ = str_replace('>', '>', $s_);
|
||||
$s_ = str_replace('<', '<', $s_);
|
||||
$s_ = str_replace('&', '&', $s_);
|
||||
$s_ = preg_replace_callback('/[#{}_$\\\&]|&(?=amp;)/', $f2, $s_);
|
||||
}
|
||||
|
||||
$s .= $s_;
|
||||
}
|
||||
|
||||
unset($str_);
|
||||
|
||||
$s = "\\lmsCODE{" . $s . '}';
|
||||
|
||||
|
||||
/* XXX:
|
||||
* hack alert: leaving newline literals (\n) inside arguments seems to
|
||||
* leave them being totally ignored. This is a problem for wrapping.
|
||||
*
|
||||
* the current solution is to close all open lms commands before the
|
||||
* newline then reopen them afterwards.
|
||||
*/
|
||||
|
||||
$stack = array();
|
||||
$pieces = preg_split('/(\\\lms[^\{]+\{|(?<!\\\)(\\\\\\\\)*[\{\}])/', $s,
|
||||
-1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
// NOTE: p being a reference is probably going to necessitate a lot of
|
||||
// copying to pass through all these preg_* and str* calls.
|
||||
// consider rewriting.
|
||||
foreach($pieces as $k=>&$p) {
|
||||
if (preg_match('/^\\\lms/', $p))
|
||||
$stack[] = "" . $p;
|
||||
elseif(preg_match('/^(\\\\\\\\)*\}/', $p)) {
|
||||
array_pop($stack);
|
||||
}
|
||||
elseif(preg_match('/^(\\\\\\\\)*{/', $p))
|
||||
$stack [] = $p;
|
||||
elseif(strpos($p, "\n") !== false) {
|
||||
$before = "";
|
||||
$after = "";
|
||||
foreach($stack as $st_) {
|
||||
$before .= $st_;
|
||||
$after .= '}';
|
||||
}
|
||||
$p = str_replace("\n", "$after\n$before" , $p);
|
||||
}
|
||||
}
|
||||
|
||||
$s = implode('', $pieces);
|
||||
|
||||
$out .= $s;
|
||||
$out .= <<<EOF
|
||||
\end{Verbatim}
|
||||
\end{document}
|
||||
EOF;
|
||||
return $out;
|
||||
}
|
||||
|
||||
}
|
||||
/// @endcond
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This is a horrible routine to register all the default
|
||||
* scanners. The code is distracting at best so it's been factored into this one
|
||||
* file.
|
||||
*
|
||||
* We include it into the main program with a require statement, which
|
||||
* due to the literal way PHP includes work, when done within a function gives
|
||||
* us access to that function's scope.
|
||||
* We are in the scope of a method inside the Luminous_ object, so we refer to
|
||||
* $this as being the $luminous_ singleton object.
|
||||
*/
|
||||
|
||||
|
||||
$language_dir = luminous::root() . '/languages/';
|
||||
|
||||
|
||||
// this is a dummy file which includes ECMAScript dependencies in a
|
||||
// non-circular way.
|
||||
$this->scanners->AddScanner('ecma-includes', null, null,
|
||||
"$language_dir/include/ecma.php");
|
||||
|
||||
$this->scanners->AddScanner(array('ada', 'adb', 'ads'),
|
||||
'LuminousAdaScanner', 'Ada', "$language_dir/ada.php");
|
||||
|
||||
$this->scanners->AddScanner(array('as', 'actionscript'),
|
||||
'LuminousActionScriptScanner', 'ActionScript', "$language_dir/as.php",
|
||||
'ecma');
|
||||
|
||||
$this->scanners->AddScanner(array('bnf'),
|
||||
'LuminousBNFScanner', 'Backus Naur Form', "$language_dir/bnf.php");
|
||||
|
||||
$this->scanners->AddScanner(array('bash', 'sh'),
|
||||
'LuminousBashScanner', 'Bash', "$language_dir/bash.php");
|
||||
|
||||
$this->scanners->AddScanner(array('c', 'cpp', 'h', 'hpp', 'cxx', 'hxx'),
|
||||
'LuminousCppScanner', 'C/C++', "$language_dir/cpp.php");
|
||||
|
||||
$this->scanners->AddScanner(array('cs', 'csharp', 'c#'),
|
||||
'LuminousCSharpScanner', 'C#', "$language_dir/csharp.php");
|
||||
|
||||
$this->scanners->AddScanner('css',
|
||||
'LuminousCSSScanner', 'CSS', "$language_dir/css.php");
|
||||
|
||||
$this->scanners->AddScanner(array('diff', 'patch'),
|
||||
'LuminousDiffScanner', 'Diff', "$language_dir/diff.php");
|
||||
|
||||
$this->scanners->AddScanner(array('prettydiff', 'prettypatch',
|
||||
'diffpretty', 'patchpretty'),
|
||||
'LuminousPrettyDiffScanner', 'Diff-Pretty', "$language_dir/diff.php");
|
||||
|
||||
$this->scanners->AddScanner(array('html', 'htm'),
|
||||
'LuminousHTMLScanner', 'HTML', "$language_dir/html.php",
|
||||
array('js', 'css'));
|
||||
|
||||
$this->scanners->AddScanner(array('ecma', 'ecmascript'),
|
||||
'LuminousECMAScriptScanner', 'ECMAScript',
|
||||
"$language_dir/ecmascript.php", 'ecma-includes');
|
||||
|
||||
$this->scanners->AddScanner(array('erlang', 'erl', 'hrl'),
|
||||
'LuminousErlangScanner', 'Erlang', "$language_dir/erlang.php");
|
||||
|
||||
$this->scanners->AddScanner('go', 'LuminousGoScanner', 'Go',
|
||||
"$language_dir/go.php");
|
||||
|
||||
|
||||
$this->scanners->AddScanner(array('groovy'),
|
||||
'LuminousGroovyScanner', 'Groovy',
|
||||
"$language_dir/groovy.php");
|
||||
|
||||
$this->scanners->AddScanner(array('haskell', 'hs'),
|
||||
'LuminousHaskellScanner', 'Haskell', "$language_dir/haskell.php");
|
||||
|
||||
$this->scanners->AddScanner('java',
|
||||
'LuminousJavaScanner', 'Java', "$language_dir/java.php");
|
||||
|
||||
$this->scanners->AddScanner(array('js', 'javascript'),
|
||||
'LuminousJavaScriptScanner', 'JavaScript', "$language_dir/javascript.php",
|
||||
array('ecma'));
|
||||
|
||||
$this->scanners->AddScanner('json',
|
||||
'LuminousJSONScanner', 'JSON', "$language_dir/json.php");
|
||||
|
||||
$this->scanners->AddScanner(array('latex', 'tex'),
|
||||
'LuminousLatexScanner', 'LaTeX', "$language_dir/latex.php");
|
||||
|
||||
$this->scanners->AddScanner(array('lolcode', 'lolc', 'lol'),
|
||||
'LuminousLOLCODEScanner', 'LOLCODE', "$language_dir/lolcode.php");
|
||||
|
||||
$this->scanners->AddScanner(array('m', 'matlab'),
|
||||
'LuminousMATLABScanner', 'MATLAB', "$language_dir/matlab.php");
|
||||
|
||||
$this->scanners->AddScanner(array('perl', 'pl', 'pm'),
|
||||
'LuminousPerlScanner', 'Perl', "$language_dir/perl.php");
|
||||
|
||||
$this->scanners->AddScanner(array('rails','rhtml', 'ror'),
|
||||
'LuminousRailsScanner', 'Ruby on Rails',
|
||||
"$language_dir/rails.php", array('ruby', 'html'));
|
||||
|
||||
$this->scanners->AddScanner(array('ruby','rb'),
|
||||
'LuminousRubyScanner', 'Ruby', "$language_dir/ruby.php");
|
||||
|
||||
$this->scanners->AddScanner(array('plain', 'text', 'txt'),
|
||||
'LuminousIdentityScanner', 'Plain', "$language_dir/identity.php");
|
||||
|
||||
// PHP Snippet does not require an initial <?php tag to begin highlighting
|
||||
$this->scanners->AddScanner('php_snippet', 'LuminousPHPSnippetScanner',
|
||||
'PHP Snippet', "$language_dir/php.php", array('html'));
|
||||
|
||||
$this->scanners->AddScanner('php',
|
||||
'LuminousPHPScanner', 'PHP', "$language_dir/php.php",
|
||||
array('html'));
|
||||
|
||||
$this->scanners->AddScanner(array('python', 'py'),
|
||||
'LuminousPythonScanner', 'Python', "$language_dir/python.php");
|
||||
$this->scanners->AddScanner(array('django', 'djt'),
|
||||
'LuminousDjangoScanner', 'Django', "$language_dir/python.php",
|
||||
array('html')
|
||||
);
|
||||
$this->scanners->AddScanner(array('scala', 'scl'),
|
||||
'LuminousScalaScanner', 'Scala', "$language_dir/scala.php", 'xml');
|
||||
|
||||
$this->scanners->AddScanner('scss',
|
||||
'LuminousSCSSScanner', 'SCSS', "$language_dir/scss.php");
|
||||
|
||||
$this->scanners->AddScanner(array('sql', 'mysql'),
|
||||
'LuminousSQLScanner', 'SQL', "$language_dir/sql.php");
|
||||
|
||||
$this->scanners->AddScanner(array('vim', 'vimscript'),
|
||||
'LuminousVimScriptScanner', 'Vim Script', "$language_dir/vim.php");
|
||||
|
||||
$this->scanners->AddScanner(array('vb', 'bas'),
|
||||
'LuminousVBScanner', 'Visual Basic', "$language_dir/vb.php",
|
||||
'xml');
|
||||
|
||||
$this->scanners->AddScanner('xml', 'LuminousXMLScanner',
|
||||
'XML', "$language_dir/xml.php", 'html');
|
||||
|
||||
$this->scanners->SetDefaultScanner('plain');
|
||||
|
|
@ -1,626 +0,0 @@
|
|||
<?php
|
||||
|
||||
|
||||
require_once(dirname(__FILE__) . '/debug.php');
|
||||
|
||||
require_once(dirname(__FILE__) . '/options.class.php');
|
||||
|
||||
require_once(dirname(__FILE__) . '/cache/cache.class.php');
|
||||
require_once(dirname(__FILE__) . '/cache/fscache.class.php');
|
||||
require_once(dirname(__FILE__) . '/cache/sqlcache.class.php');
|
||||
require_once(dirname(__FILE__) . '/scanners.class.php');
|
||||
require_once(dirname(__FILE__) . '/formatters/formatter.class.php');
|
||||
require_once(dirname(__FILE__) . '/core/scanner.class.php');
|
||||
|
||||
// updated automatically, use single quotes, keep single line
|
||||
define('LUMINOUS_VERSION', 'v0.7.0');
|
||||
|
||||
|
||||
/*
|
||||
* This file contains the public calling interface for Luminous. It's split
|
||||
* into two classes: one is basically the user-interface, the other is a
|
||||
* wrapper around it. The wrapper allows a single-line function call, and is
|
||||
* procedural. It's wrapped in an abstract class for a namespace.
|
||||
* The real class is instantiated into a singleton which is manipulated by
|
||||
* the abstract class methods.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @cond ALL
|
||||
* This is kind of a pseudo-UI class. It's a singleton which will be
|
||||
* manipulated by a few procedural functions, for ease of use.
|
||||
* It's technically supposed to be private to this class, but this is a sort
|
||||
* of 'agreed' privateness, and we expose an instance of it globally.
|
||||
*
|
||||
* In fact, it is used by (at least) the diff scanner, which uses its
|
||||
* scanner table.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
*/
|
||||
class _Luminous {
|
||||
|
||||
/// Settings array
|
||||
/// @see LuminousOptions
|
||||
public $settings;
|
||||
|
||||
public $scanners; ///< the scanner table
|
||||
|
||||
public $cache = null;
|
||||
|
||||
/**
|
||||
* The language is passed to the formatter which may choose to do something
|
||||
* interesting with it. If you use the scanners table this can be figured out
|
||||
* automatically, but if you pass in your own scanner, you will need to
|
||||
* give a language name if you want the formatter to consider it.
|
||||
*/
|
||||
public $language = null;
|
||||
|
||||
public function __construct() {
|
||||
$this->scanners = new LuminousScanners();
|
||||
$this->register_default_scanners();
|
||||
}
|
||||
|
||||
/// registers builtin scanners
|
||||
private function register_default_scanners() {
|
||||
$this->settings = new LuminousOptions();
|
||||
require dirname(__FILE__) . '/load_scanners.php';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an instance of the current formatter
|
||||
*/
|
||||
function get_formatter() {
|
||||
$fmt_path = dirname(__FILE__) . '/formatters/';
|
||||
|
||||
$fmt = $this->settings->format;
|
||||
$formatter = null;
|
||||
if (!is_string($fmt) && is_subclass_of($fmt, 'LuminousFormatter')) {
|
||||
$formatter = clone $fmt;
|
||||
} elseif ($fmt === 'html') {
|
||||
require_once($fmt_path . 'htmlformatter.class.php');
|
||||
$formatter = new LuminousFormatterHTML();
|
||||
} elseif ($fmt === 'html-inline') {
|
||||
require_once($fmt_path . 'htmlformatter.class.php');
|
||||
$formatter = new LuminousFormatterHTMLInline();
|
||||
} elseif ($fmt === 'html-full') {
|
||||
require_once($fmt_path . 'htmlformatter.class.php');
|
||||
$formatter = new LuminousFormatterHTMLFullPage();
|
||||
} elseif($fmt === 'latex') {
|
||||
require_once($fmt_path . 'latexformatter.class.php');
|
||||
$formatter = new LuminousFormatterLatex();
|
||||
} elseif($fmt === null || $fmt === 'none') {
|
||||
require_once($fmt_path . 'identityformatter.class.php');
|
||||
$formatter = new LuminousIdentityFormatter();
|
||||
}
|
||||
|
||||
if ($formatter === null) {
|
||||
throw new Exception('Unknown formatter: ' . $this->settings->format);
|
||||
return null;
|
||||
}
|
||||
$this->set_formatter_options($formatter);
|
||||
return $formatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a formatter instance according to our current options/settings
|
||||
*/
|
||||
private function set_formatter_options(&$formatter) {
|
||||
$formatter->wrap_length = $this->settings->wrap_width;
|
||||
$formatter->line_numbers = $this->settings->line_numbers;
|
||||
$formatter->start_line = $this->settings->start_line;
|
||||
$formatter->link = $this->settings->auto_link;
|
||||
$formatter->height = $this->settings->max_height;
|
||||
$formatter->strict_standards = $this->settings->html_strict;
|
||||
$formatter->set_theme(luminous::theme($this->settings->theme));
|
||||
$formatter->highlight_lines = $this->settings->highlight_lines;
|
||||
$formatter->language = $this->language;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculates a 'cache_id' for the input. This is dependent upon the
|
||||
* source code and the settings. This should be (near-as-feasible) unique
|
||||
* for any cobmination of source, language and settings
|
||||
*/
|
||||
private function cache_id($scanner, $source) {
|
||||
// to figure out the cache id, we mash a load of stuff together and
|
||||
// md5 it. This gives us a unique (assuming no collisions) handle to
|
||||
// a cache file, which depends on the input source, the relevant formatter
|
||||
// settings, the version, and scanner.
|
||||
$settings = array($this->settings->wrap_width,
|
||||
$this->settings->line_numbers,
|
||||
$this->settings->start_line,
|
||||
$this->settings->auto_link,
|
||||
$this->settings->max_height,
|
||||
$this->settings->format,
|
||||
$this->settings->theme,
|
||||
$this->settings->html_strict,
|
||||
LUMINOUS_VERSION,
|
||||
);
|
||||
|
||||
$id = md5($source);
|
||||
$id = md5($id . serialize($scanner));
|
||||
$id = md5($id . serialize($settings));
|
||||
return $id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The real highlighting function
|
||||
* @throw InvalidArgumentException if $scanner is not either a string or a
|
||||
* LuminousScanner instance, or if $source is not a string.
|
||||
*/
|
||||
function highlight($scanner, $source, $settings = null) {
|
||||
$old_settings = null;
|
||||
if ($settings !== null) {
|
||||
if (!is_array($settings)) {
|
||||
throw new Exception('Luminous internal error: Settings is not an array');
|
||||
}
|
||||
$old_settings = clone $this->settings;
|
||||
foreach($settings as $k=>$v) {
|
||||
$this->settings->set($k, $v);
|
||||
}
|
||||
}
|
||||
$should_reset_language = false;
|
||||
$this->cache = null;
|
||||
if (!is_string($source)) throw new InvalidArgumentException('Non-string '
|
||||
. 'supplied for $source');
|
||||
|
||||
if (!($scanner instanceof LuminousScanner)) {
|
||||
if (!is_string($scanner)) throw new InvalidArgumentException('Non-string
|
||||
or LuminousScanner instance supplied for $scanner');
|
||||
$code = $scanner;
|
||||
$scanner = $this->scanners->GetScanner($code);
|
||||
if ($scanner === null) throw new Exception("No known scanner for '$code' and no default set");
|
||||
$should_reset_language = true;
|
||||
$this->language = $this->scanners->GetDescription($code);
|
||||
}
|
||||
$cache_hit = true;
|
||||
$out = null;
|
||||
if ($this->settings->cache) {
|
||||
$cache_id = $this->cache_id($scanner, $source);
|
||||
if ($this->settings->sql_function !== null) {
|
||||
$this->cache = new LuminousSQLCache($cache_id);
|
||||
$this->cache->set_sql_function($this->settings->sql_function);
|
||||
} else {
|
||||
$this->cache = new LuminousFileSystemCache($cache_id);
|
||||
}
|
||||
$this->cache->set_purge_time($this->settings->cache_age);
|
||||
$out = $this->cache->read();
|
||||
}
|
||||
if ($out === null) {
|
||||
$cache_hit = false;
|
||||
$out_raw = $scanner->highlight($source);
|
||||
$formatter = $this->get_formatter();
|
||||
$out = $formatter->format($out_raw);
|
||||
}
|
||||
|
||||
if ($this->settings->cache && !$cache_hit) {
|
||||
$this->cache->write($out);
|
||||
}
|
||||
if ($should_reset_language) $this->language = null;
|
||||
if ($old_settings !== null) {
|
||||
$this->settings = $old_settings;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
// ends ALL
|
||||
|
||||
|
||||
// Here's our singleton.
|
||||
global $luminous_; // sometimes need this or the object seems to disappear
|
||||
$luminous_ = new _Luminous();
|
||||
|
||||
/// @cond USER
|
||||
|
||||
// here's our 'real' UI class, which uses the above singleton. This is all
|
||||
// static because these are actually procudural functions, we're using the
|
||||
// class as a namespace.
|
||||
/**
|
||||
* @brief Users' API
|
||||
*/
|
||||
abstract class luminous {
|
||||
|
||||
/**
|
||||
* @brief Highlights a string according to the current settings
|
||||
*
|
||||
* @param $scanner The scanner to use, this can either be a langauge code,
|
||||
* or it can be an instance of LuminousScanner.
|
||||
* @param $source The source string
|
||||
* @param $cache Whether or not to use the cache
|
||||
* @return the highlighted source code.
|
||||
*
|
||||
* To specify different output formats or other options, see set().
|
||||
*/
|
||||
static function highlight($scanner, $source, $cache_or_settings=null) {
|
||||
global $luminous_;
|
||||
try {
|
||||
$settings = null;
|
||||
if (is_bool($cache_or_settings)) {
|
||||
$settings = array('cache' => $cache_or_settings);
|
||||
} else if (is_array($cache_or_settings)) {
|
||||
$settings = $cache_or_settings;
|
||||
}
|
||||
$h = $luminous_->highlight($scanner, $source, $settings);
|
||||
if ($luminous_->settings->verbose) {
|
||||
$errs = self::cache_errors();
|
||||
if (!empty($errs)) {
|
||||
trigger_error("Luminous cache errors were encountered. \n" .
|
||||
'See luminous::cache_errors() for details.');
|
||||
}
|
||||
}
|
||||
return $h;
|
||||
} catch (InvalidArgumentException $e) {
|
||||
// this is a user error, let it bubble
|
||||
//FIXME how do we let it bubble without throwing? the stack trace will
|
||||
// be wrong.
|
||||
throw $e;
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// this is an internal error or a scanner error, or something
|
||||
// it might not technically be Luminous that caused it, but let's not
|
||||
// make it kill the whole page in production code
|
||||
if (LUMINOUS_DEBUG) throw $e;
|
||||
else {
|
||||
$return = $source;
|
||||
if (($t = self::setting('failure-tag')))
|
||||
$return = "<$t>$return</$t>";
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Highlights a file according to the current setings.
|
||||
*
|
||||
* @param $scanner The scanner to use, this can either be a langauge code,
|
||||
* or it can be an instance of LuminousScanner.
|
||||
* @param $file the source string
|
||||
* @param $cache Whether or not to use the cache
|
||||
* @return the highlighted source code.
|
||||
*
|
||||
* To specify different output formats or other options, see set().
|
||||
*/
|
||||
static function highlight_file($scanner, $file, $cache_or_settings=null) {
|
||||
return self::highlight($scanner, file_get_contents($file), $cache_or_settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a list of cache errors encountered during the most recent highlight
|
||||
*
|
||||
* @return An array of errors the cache encountered (which may be empty),
|
||||
* or @c FALSE if the cache is not enabled
|
||||
*/
|
||||
static function cache_errors() {
|
||||
global $luminous_;
|
||||
$c = $luminous_->cache;
|
||||
if ($c === null) return FALSE;
|
||||
return $c->errors();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Registers a scanner
|
||||
*
|
||||
* Registers a scanner with Luminous's scanner table. Utilising this
|
||||
* function means that Luminous will handle instantiation and inclusion of
|
||||
* the scanner's source file in a lazy-manner.
|
||||
*
|
||||
* @param $language_code A string or array of strings designating the
|
||||
* aliases by which this scanner may be accessed
|
||||
* @param $classname The class name of the scanner, as string. If you
|
||||
* leave this as 'null', it will be treated as a dummy file (you can use
|
||||
* this to handle a set of non-circular include rules, if you run into
|
||||
* problems).
|
||||
* @param $readable_language A human readable language name
|
||||
* @param $path The path to the source file containing your scanner
|
||||
* @param dependencies An array of other scanners which this scanner
|
||||
* depends on (as sub-scanners, or superclasses). Each item in the
|
||||
* array should be a $language_code for another scanner.
|
||||
*/
|
||||
static function register_scanner($language_code, $classname,
|
||||
$readable_language, $path, $dependencies=null) {
|
||||
global $luminous_;
|
||||
$luminous_->scanners->AddScanner($language_code, $classname,
|
||||
$readable_language, $path, $dependencies);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the full filesystem path to Luminous
|
||||
* @return what Luminous thinks its location is on the filesystem
|
||||
* @internal
|
||||
*/
|
||||
static function root() {
|
||||
return realpath(dirname(__FILE__) . '/../');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a list of installed themes
|
||||
*
|
||||
* @return the list of theme files present in style/.
|
||||
* Each theme will simply be a filename, and will end in .css, and will not
|
||||
* have any directory prefix.
|
||||
*/
|
||||
static function themes() {
|
||||
$themes_uri = self::root() . '/style/';
|
||||
$themes = array();
|
||||
foreach(glob($themes_uri . '/*.css') as $css) {
|
||||
$fn = trim(preg_replace("%.*/%", '', $css));
|
||||
switch($fn) {
|
||||
// these are special, exclude these
|
||||
case 'luminous.css':
|
||||
case 'luminous_print.css':
|
||||
case 'luminous.min.css':
|
||||
continue;
|
||||
default:
|
||||
$themes[] = $fn;
|
||||
}
|
||||
}
|
||||
return $themes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks whether a theme exists
|
||||
* @param $theme the name of a theme, which should be suffixed with .css
|
||||
* @return @c TRUE if a theme exists in style/, else @c FALSE
|
||||
*/
|
||||
static function theme_exists($theme) {
|
||||
return in_array($theme, self::themes());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a CSS theme file
|
||||
* Gets the CSS-string content of a theme file.
|
||||
* Use this function for reading themes as it involves security
|
||||
* checks against reading arbitrary files
|
||||
*
|
||||
* @param $theme The name of the theme to retrieve, which may or may not
|
||||
* include the .css suffix.
|
||||
* @return the content of a theme; this is the actual CSS text.
|
||||
* @internal
|
||||
*/
|
||||
static function theme($theme) {
|
||||
if (!preg_match('/\.css$/i', $theme)) $theme .= '.css';
|
||||
if (self::theme_exists($theme))
|
||||
return file_get_contents(self::root() . "/style/" . $theme);
|
||||
else
|
||||
throw new Exception('No such theme file: ' . $theme);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets a setting's value
|
||||
* @param $option The name of the setting (corresponds to an attribute name
|
||||
* in LuminousOptions)
|
||||
* @return The value of the given setting
|
||||
* @throws Exception if the option is unrecognised
|
||||
*
|
||||
* Options are stored in LuminousOptions, which provides documentation of
|
||||
* each option.
|
||||
* @see LuminousOptions
|
||||
*/
|
||||
static function setting($option) {
|
||||
global $luminous_;
|
||||
$option = str_replace('-', '_', $option);
|
||||
return $luminous_->settings->$option;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the given option to the given value
|
||||
* @param $option The name of the setting (corresponds to an attribute name
|
||||
* in LuminousOptions)
|
||||
* @param $value The new value of the setting
|
||||
* @throws Exception if the option is unrecognised (and in various other
|
||||
* validation failures),
|
||||
* @throws InvalidArgumentException if the argument fails the type-validation
|
||||
* check
|
||||
*
|
||||
* @note This function can also accept multiple settings if $option is a
|
||||
* map of option_name=>value
|
||||
*
|
||||
* Options are stored in LuminousOptions, which provides documentation of
|
||||
* each option.
|
||||
*
|
||||
* @note as of 0.7 this is a thin wrapper around LuminousOptions::set()
|
||||
*
|
||||
* @see LuminousOptions::set
|
||||
*/
|
||||
static function set($option, $value=null) {
|
||||
global $luminous_;
|
||||
$luminous_->settings->set($option, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a list of registered scanners
|
||||
*
|
||||
* @return a list of scanners currently registered. The list is in the
|
||||
* format:
|
||||
*
|
||||
* language_name => codes,
|
||||
*
|
||||
* where language_name is a string, and codes is an array of strings.
|
||||
*
|
||||
* The array is sorted alphabetically by key.
|
||||
*/
|
||||
static function scanners() {
|
||||
global $luminous_;
|
||||
$scanners = $luminous_->scanners->ListScanners();
|
||||
ksort($scanners);
|
||||
return $scanners;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a formatter instance
|
||||
*
|
||||
* @return an instance of a LuminousFormatter according to the current
|
||||
* format setting
|
||||
*
|
||||
* This shouldn't be necessary for general usage, it is only implemented
|
||||
* for testing.
|
||||
* @internal
|
||||
*/
|
||||
static function formatter() {
|
||||
global $luminous_;
|
||||
return $luminous_->get_formatter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Comparison function for guess_language()'s sorting
|
||||
*/
|
||||
static function __guess_language_cmp($a, $b) {
|
||||
$c = $a['p'] - $b['p'];
|
||||
if ($c === 0) return 0;
|
||||
elseif ($c < 0) return -1;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Attempts to guess the language of a piece of source code
|
||||
* @param $src The source code whose language is to be guessed
|
||||
* @param $confidence The desired confidence level: if this is 0.05 but the
|
||||
* best guess has a confidence of 0.04, then $default is returned. Note
|
||||
* that the confidence level returned by scanners is quite arbitrary, so
|
||||
* don't set this to '1' thinking that'll give you better results.
|
||||
* A realistic confidence is likely to be quite low, because a scanner will
|
||||
* only return 1 if it's able to pick out a shebang (#!) line or something
|
||||
* else definitive. If there exists no such identifier, a 'strong'
|
||||
* confidence which is right most of the time might be as low as 0.1.
|
||||
* Therefore it is recommended to keep this between 0.01 and 0.10.
|
||||
* @param $default The default name to return in the event that no scanner
|
||||
* thinks this source belongs to them (at the desired confidence).
|
||||
*
|
||||
* @return A valid code for the best scanner, or $default.
|
||||
*
|
||||
* This is a wrapper around luminous::guess_language_full
|
||||
*/
|
||||
static function guess_language($src, $confidence=0.05, $default = 'plain') {
|
||||
$guess = self::guess_language_full($src);
|
||||
if ($guess[0]['p'] >= $confidence)
|
||||
return $guess[0]['codes'][0];
|
||||
else
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attempts to guess the language of a piece of source code
|
||||
* @param $src The source code whose language is to be guessed
|
||||
* @return An array - the array is ordered by probability, with the most
|
||||
* probable language coming first in the array.
|
||||
* Each array element is an array which represents a language (scanner),
|
||||
* and has the keys:
|
||||
* \li \c 'language' => Human-readable language description,
|
||||
* \li \c 'codes' => valid codes for the language (array),
|
||||
* \li \c 'p' => the probability (between 0.0 and 1.0 inclusive),
|
||||
*
|
||||
* note that \c 'language' and \c 'codes' are the key => value pair from
|
||||
* luminous::scanners()
|
||||
*
|
||||
* @warning Language guessing is inherently unreliable but should be right
|
||||
* about 80% of the time on common languages. Bear in mind that guessing is
|
||||
* going to be severely hampered in the case that one language is used to
|
||||
* generate code in another language.
|
||||
*
|
||||
* Usage for this function will be something like this:
|
||||
* @code
|
||||
* $guesses = luminous::guess_language($src);
|
||||
* $output = luminous::highlight($guesses[0]['codes'][0], $src);
|
||||
* @endcode
|
||||
*
|
||||
* @see luminous::guess_language
|
||||
*/
|
||||
static function guess_language_full($src) {
|
||||
global $luminous_;
|
||||
// first we're going to make an 'info' array for the source, which
|
||||
// precomputes some frequently useful things, like how many lines it
|
||||
// has, etc. It prevents scanners from redundantly figuring these things
|
||||
// out themselves
|
||||
$lines = preg_split("/\r\n|[\r\n]/", $src);
|
||||
$shebang = '';
|
||||
if (preg_match('/^#!.*/', $src, $m)) $shebang = $m[0];
|
||||
|
||||
$info = array(
|
||||
'lines' => $lines,
|
||||
'num_lines' => count($lines),
|
||||
'trimmed' => trim($src),
|
||||
'shebang' => $shebang
|
||||
);
|
||||
|
||||
$return = array();
|
||||
foreach(self::scanners() as $lang=>$codes) {
|
||||
$scanner_name = $luminous_->scanners->GetScanner($codes[0], false,
|
||||
false);
|
||||
assert($scanner_name !== null);
|
||||
$return[] = array(
|
||||
'language' => $lang,
|
||||
'codes' => $codes,
|
||||
'p' => call_user_func(array($scanner_name, 'guess_language'), $src,
|
||||
$info)
|
||||
);
|
||||
}
|
||||
uasort($return, array('luminous', '__guess_language_cmp'));
|
||||
$return = array_reverse($return);
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the markup you need to include in your web page
|
||||
* @return a string representing everything that needs to be printed in
|
||||
* the \<head\> section of a website.
|
||||
*
|
||||
* This is influenced by the following settings:
|
||||
* relative-root,
|
||||
* include-javascript,
|
||||
* include-jquery
|
||||
* theme
|
||||
*/
|
||||
static function head_html() {
|
||||
global $luminous_;
|
||||
$theme = self::setting('theme');
|
||||
$relative_root = self::setting('relative-root');
|
||||
$js = self::setting('include-javascript');
|
||||
$jquery = self::setting('include-jquery');
|
||||
|
||||
if (!preg_match('/\.css$/i', $theme)) $theme .= '.css';
|
||||
if (!self::theme_exists($theme)) $theme = 'luminous_light.css';
|
||||
|
||||
if ($relative_root === null) {
|
||||
$relative_root = str_replace($_SERVER['DOCUMENT_ROOT'], '/',
|
||||
dirname(__FILE__));
|
||||
$relative_root = str_replace('\\', '/', $relative_root); // bah windows
|
||||
$relative_root = rtrim($relative_root, '/');
|
||||
// go up one level.
|
||||
$relative_root = preg_replace('%/[^/]*$%', '', $relative_root);
|
||||
}
|
||||
// if we ended up with any double slashes, let's zap them, and also
|
||||
// trim any trailing ones
|
||||
$relative_root = preg_replace('%(?<!:)//+%', '/', $relative_root);
|
||||
$relative_root = rtrim($relative_root, '/');
|
||||
$out = '';
|
||||
$link_template = "<link rel='stylesheet' type='text/css' href='$relative_root/style/%s' id='%s'>\n";
|
||||
$script_template = "<script type='text/javascript' src='$relative_root/client/%s'></script>\n";
|
||||
$out .= sprintf($link_template, 'luminous.css', 'luminous-style');
|
||||
$out .= sprintf($link_template, $theme, 'luminous-theme');
|
||||
if ($js) {
|
||||
if ($jquery)
|
||||
$out .= sprintf($script_template, 'jquery-1.6.4.min.js');
|
||||
$out .= sprintf($script_template, 'luminous.js');
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
// ends user
|
||||
|
|
@ -1,342 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @cond USER
|
||||
*
|
||||
* @brief Options class.
|
||||
*
|
||||
* @warning This object's structure isn't guaranteed to be stable so don't read
|
||||
* or write these directly. As a user, you should be using luminous::set()
|
||||
* and luminous::setting()
|
||||
*
|
||||
* We use a fair bit of PHP trickery in the implementation here. The keener
|
||||
* among you will notice that the options are all private: don't worry about
|
||||
* that. We override the __set() method to apply option specific validation.
|
||||
* Options can be written to as normal.
|
||||
*
|
||||
* The option variable names correspond with option strings that can be passed
|
||||
* through luminous::set(), however, for historical reasons, underscores can be
|
||||
* replaced with dashed in the call.
|
||||
*/
|
||||
class LuminousOptions {
|
||||
|
||||
/**
|
||||
* @brief Whether to use the built-in cache
|
||||
*/
|
||||
private $cache = true;
|
||||
|
||||
/**
|
||||
* @brief Maximum age of cache files in seconds
|
||||
*
|
||||
* Cache files which have not been read for this length of time will be
|
||||
* removed from the file system. The file's 'mtime' is used to calculate
|
||||
* when it was last used, and a cache hit triggers a 'touch'
|
||||
*
|
||||
* Set to -1 or 0 to disable cache purges
|
||||
*/
|
||||
private $cache_age = 7776000; // 90 days
|
||||
|
||||
/**
|
||||
* @brief Word wrapping
|
||||
*
|
||||
* If the formatter supports line wrapping, lines will be wrapped at
|
||||
* this number of characters (0 or -1 to disable)
|
||||
*/
|
||||
private $wrap_width = -1;
|
||||
|
||||
/**
|
||||
* @brief Line numbering
|
||||
*
|
||||
* If the formatter supports line numbering, this setting controls whether
|
||||
* or not lines should be numbered
|
||||
*/
|
||||
private $line_numbers = true;
|
||||
|
||||
/**
|
||||
* @brief Line number of first line
|
||||
*
|
||||
* If the formatter supports line numbering, this setting controls number
|
||||
* of the first line
|
||||
*/
|
||||
private $start_line = 1;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Highlighting of lines
|
||||
*
|
||||
* If the formatter supports highlighting lines, this setting allows
|
||||
* the caller to specify the set of line numbers to highlight
|
||||
*/
|
||||
private $highlight_lines = array();
|
||||
|
||||
/**
|
||||
* @brief Hyperlinking
|
||||
*
|
||||
* If the formatter supports hyper-linking, this setting controls whether
|
||||
* or not URLs will be automatically linked
|
||||
*/
|
||||
private $auto_link = true;
|
||||
|
||||
/**
|
||||
* @brief Widget height constraint
|
||||
*
|
||||
* If the formatter supports heigh constraint, this setting controls whether
|
||||
* or not to constrain the widget's height, and to what.
|
||||
*/
|
||||
private $max_height = -1;
|
||||
|
||||
/**
|
||||
* @brief Output format
|
||||
*
|
||||
* Chooses which output format to use. Current valid settings are:
|
||||
* \li 'html' - standard HTML element, contained in a \<div\> with class 'luminous',
|
||||
* CSS is not included and must be included on the page separately
|
||||
* (probably with luminous::head_html())
|
||||
* \li 'html-full' - A complete HTML document. CSS is included.
|
||||
* \li 'html-inline' - Very similar to 'html' but geared towards inline display.
|
||||
* Probably not very useful.
|
||||
* \li 'latex' - A full LaTeX document
|
||||
* \li 'none' or \c NULL - No formatter. Internal XML format is returned.
|
||||
* You probably don't want this.
|
||||
*/
|
||||
private $format = 'html';
|
||||
|
||||
/**
|
||||
* @brief Theme
|
||||
*
|
||||
* The default theme to use. This is observed by the HTML-full and LaTeX
|
||||
* formatters, it is also read by luminous::head_html().
|
||||
*
|
||||
* This should be a valid theme which exists in style/
|
||||
*/
|
||||
private $theme = 'luminous_light.css';
|
||||
|
||||
/**
|
||||
* @brief HTML strict standards mode
|
||||
*
|
||||
* The HTML4-strict doctype disallows a few things which are technically
|
||||
* useful. Set this to true if you don't want Luminous to break validation
|
||||
* on your HTML4-strict document. Luminous should be valid
|
||||
* HTML4 loose/transitional and HTML5 without needing to enable this.
|
||||
*/
|
||||
private $html_strict = false;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Location of Luminous relative to your document root
|
||||
*
|
||||
* If you use luminous::head_html(), it has to try to figure out the
|
||||
* path to the style/ directory so that it can return a correct URL to the
|
||||
* necessary stylesheets. Luminous may get this wrong in some situations,
|
||||
* specifically it is currently impossible to get this right if Luminous
|
||||
* exists on the filesystem outside of the document root, and you have used
|
||||
* a symbolic link to put it inside. For this reason, this setting allows you
|
||||
* to override the path.
|
||||
*
|
||||
* e.g. If you set this to '/extern/highlighter', the stylesheets will be
|
||||
* linked with
|
||||
* \<link rel='stylesheet' href='/extern/highlighter/style/luminous.css'\>
|
||||
*
|
||||
*/
|
||||
private $relative_root = null;
|
||||
|
||||
/**
|
||||
* @brief JavaScript extras
|
||||
*
|
||||
* controls whether luminous::head_html() outputs the javascript 'extras'.
|
||||
*/
|
||||
private $include_javascript = false;
|
||||
|
||||
/**
|
||||
* @brief jQuery
|
||||
*
|
||||
* Controls whether luminous::head_html() outputs jQuery, which is required
|
||||
* for the JavaScript extras. This has no effect if $include_javascript is
|
||||
* false.
|
||||
*/
|
||||
private $include_jquery = false;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Failure recovery
|
||||
*
|
||||
* If Luminous hits some kind of unrecoverable internal error, it should
|
||||
* return the input source code back to you. If you want, it can be
|
||||
* wrapped in an HTML tag. Hopefully you will never see this.
|
||||
*/
|
||||
private $failure_tag = 'pre';
|
||||
|
||||
/**
|
||||
* @brief Defines an SQL function which can execute queries on a database
|
||||
*
|
||||
* An SQL database can be used as a replacement for the file-system cache
|
||||
* database.
|
||||
* This function should act similarly to the mysql_query function:
|
||||
* it should take a single argument (the query string) and return:
|
||||
* @li boolean @c false if the query fails
|
||||
* @li boolean @c true if the query succeeds but has no return value
|
||||
* @li An array of associative arrays if the query returns rows (each
|
||||
* element is a row, and each row is an map keyed by field name)
|
||||
*/
|
||||
private $sql_function = null;
|
||||
|
||||
private $verbose = true;
|
||||
|
||||
|
||||
public function LuminousOptions($opts=null) {
|
||||
if (is_array($opts)) {
|
||||
$this->set($opts);
|
||||
}
|
||||
}
|
||||
|
||||
public function set($nameOrArray, $value=null) {
|
||||
$array = $nameOrArray;
|
||||
if (!is_array($array)) {
|
||||
$array = array($nameOrArray => $value);
|
||||
}
|
||||
foreach($array as $option => $value) {
|
||||
// for backwards compatibility we need to do this here
|
||||
$option = str_replace('-', '_', $option);
|
||||
$this->__set($option, $value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static function check_type($value, $type, $nullable=false) {
|
||||
if ($nullable && $value === null) return true;
|
||||
$func = null;
|
||||
if ($type === 'string') $func = 'is_string';
|
||||
elseif($type === 'int') $func = 'is_int';
|
||||
elseif($type === 'numeric') $func = 'is_numeric';
|
||||
elseif($type === 'bool') $func = 'is_bool';
|
||||
elseif($type === 'func') $func = 'is_callable';
|
||||
elseif($type === 'array') $func = 'is_array';
|
||||
else {
|
||||
assert(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
$test = call_user_func($func, $value);
|
||||
if (!$test) {
|
||||
throw new InvalidArgumentException('Argument should be type ' . $type .
|
||||
($nullable? ' or null' : ''));
|
||||
}
|
||||
return $test;
|
||||
}
|
||||
|
||||
public function __get($name) {
|
||||
if (property_exists($this, $name))
|
||||
return $this->$name;
|
||||
else {
|
||||
throw new Exception('Unknown property: ' . $name);
|
||||
}
|
||||
}
|
||||
|
||||
public function __set($name, $value) {
|
||||
if ($name === 'auto_link')
|
||||
$this->set_bool($name, $value);
|
||||
else if ($name === 'cache') {
|
||||
$this->set_bool($name, $value);
|
||||
}
|
||||
elseif($name === 'cache_age') {
|
||||
if (self::check_type($value, 'int')) $this->$name = $value;
|
||||
}
|
||||
elseif($name === 'failure_tag') {
|
||||
if (self::check_type($value, 'string', true)) $this->$name = $value;
|
||||
}
|
||||
elseif($name === 'format')
|
||||
$this->set_format($value);
|
||||
elseif($name === 'html_strict') {
|
||||
if (self::check_type($value, 'bool')) $this->$name = $value;
|
||||
}
|
||||
elseif($name === 'include_javascript' || $name === 'include_jquery')
|
||||
$this->set_bool($name, $value);
|
||||
elseif($name === 'line_numbers')
|
||||
$this->set_bool($name, $value);
|
||||
elseif($name === 'start_line')
|
||||
$this->set_start_line($value);
|
||||
elseif($name === 'highlight_lines') {
|
||||
if (self::check_type($value, 'array'))
|
||||
$this->highlight_lines = $value;
|
||||
}
|
||||
elseif($name === 'max_height')
|
||||
$this->set_height($value);
|
||||
elseif($name === 'relative_root') {
|
||||
if (self::check_type($value, 'string', true)) $this->$name = $value;
|
||||
}
|
||||
elseif($name === 'theme')
|
||||
$this->set_theme($value);
|
||||
elseif($name === 'wrap_width') {
|
||||
if (self::check_type($value, 'int')) $this->$name = $value;
|
||||
}
|
||||
elseif($name === 'sql_function') {
|
||||
if (self::check_type($value, 'func', true)) $this->$name = $value;
|
||||
}
|
||||
elseif ($name === 'verbose') {
|
||||
$this->set_bool($name, $value);
|
||||
}
|
||||
else {
|
||||
throw new Exception('Unknown option: ' . $name);
|
||||
}
|
||||
}
|
||||
|
||||
private function set_bool($key, $value) {
|
||||
if (self::check_type($value, 'bool')) {
|
||||
$this->$key = $value;
|
||||
}
|
||||
}
|
||||
private function set_string($key, $value, $nullable=false) {
|
||||
if (self::check_type($value, 'string', $nullable)) {
|
||||
$this->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
private function set_start_line($value) {
|
||||
if (is_numeric($value) && $value > 0) {
|
||||
$this->start_line = $value;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Start line must be a positive number');
|
||||
}
|
||||
}
|
||||
|
||||
private function set_format($value) {
|
||||
// formatter can either be an instance or an identifier (string)
|
||||
$is_obj = $value instanceof LuminousFormatter;
|
||||
if($is_obj || self::check_type($value, 'string', true)) {
|
||||
// validate the string is a known type
|
||||
if (!$is_obj && !in_array($value, array('html', 'html-full',
|
||||
'html-inline', 'latex', 'none', null), true)) {
|
||||
throw new Exception('Invalid formatter: ' . $value);
|
||||
}
|
||||
else {
|
||||
$this->format = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function set_theme($value) {
|
||||
if (self::check_type($value, 'string')) {
|
||||
if (!preg_match('/\.css$/', $value)) $value .= '.css';
|
||||
if (!luminous::theme_exists($value)) {
|
||||
throw new Exception('No such theme: '
|
||||
. luminous::root() . '/style/' . $value);
|
||||
}
|
||||
else $this->theme = $value;
|
||||
}
|
||||
}
|
||||
|
||||
private function set_height($value) {
|
||||
// height should be either a number or a numeric string with some units at
|
||||
// the end
|
||||
if (is_numeric($value)
|
||||
|| (is_string($value) && preg_match('/^\d+/', $value))
|
||||
) {
|
||||
$this->max_height = $value;
|
||||
}
|
||||
else {
|
||||
throw new InvalidArgumentException('Unrecognised format for height');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/// @endcond
|
||||
|
|
@ -1,221 +0,0 @@
|
|||
<?php
|
||||
|
||||
/// \cond ALL
|
||||
|
||||
/**
|
||||
* \file scanners.class.php
|
||||
* \brief Scanner lookup table definition.
|
||||
*/
|
||||
/**
|
||||
* \class LuminousScanners
|
||||
* \author Mark Watkinson
|
||||
* \brief A glorified lookup table for languages to scanners.
|
||||
* One of these is instantiated in the global scope at the bottom of this source.
|
||||
* The parser assumes it to exist and uses it to look up scanners.
|
||||
* Users seeking to override scanners or add new scanners should add their
|
||||
* scanner into '$luminous_scanners'.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
class LuminousScanners
|
||||
{
|
||||
|
||||
private $lookup_table = array(); /**<
|
||||
The language=>scanner lookup table. Scanner is an array with keys:
|
||||
scanner (the string of the scanner's class name),
|
||||
file (the path to the file in which its definition resides)
|
||||
dependencies (the language name for any scanners it this scanner
|
||||
either depends on or needs to instantiate itself)
|
||||
*/
|
||||
|
||||
private $default_scanner = null; /**<
|
||||
Language name of the default scanner to use if none is found
|
||||
for a particular language */
|
||||
|
||||
private $descriptions = array();
|
||||
|
||||
private $resolved_dependencies = array();
|
||||
|
||||
/**
|
||||
* Adds a scanner into the table, or overwrites an existing scanner.
|
||||
*
|
||||
* \param language_name may be either a string or an array of strings, if
|
||||
* multiple languages are to use the same scanner
|
||||
* \param $scanner the name of the LuminousScanner object as string, (not an
|
||||
* actual instance!). If the file is actually a dummy file (say for includes),
|
||||
* leave $scanner as \c null.
|
||||
* \param lang_description a human-readable description of the language.
|
||||
* \param file the path to the file in which the scanner is defined.
|
||||
* \param dependencies optional, a string or array of strings representing
|
||||
* the language names (given in another call to AddScanner, as
|
||||
* language_name), on which the instantiation of this scanner depends.
|
||||
* i.e. any super-classes, and any classes which this scanner instantiates
|
||||
* itself.
|
||||
*
|
||||
*/
|
||||
public function AddScanner($language_name, $scanner,
|
||||
$lang_description, $file=null, $dependencies=null)
|
||||
{
|
||||
|
||||
$dummy = $scanner === null;
|
||||
$d = array();
|
||||
if (is_array($dependencies))
|
||||
$d = $dependencies;
|
||||
elseif ($dependencies !== null)
|
||||
$d = array($dependencies);
|
||||
|
||||
$insert = array('scanner'=>$scanner,
|
||||
'file'=>$file,
|
||||
'dependencies'=>$d,
|
||||
'description'=>$lang_description
|
||||
);
|
||||
if (!is_array($language_name))
|
||||
$language_name = array($language_name);
|
||||
foreach($language_name as $l) {
|
||||
$this->lookup_table[$l] = $insert;
|
||||
if (!$dummy)
|
||||
$this->AddDescription($lang_description, $l);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function AddDescription($language_name, $language_code)
|
||||
{
|
||||
if (!isset($this->descriptions[$language_name]))
|
||||
$this->descriptions[$language_name] = array();
|
||||
$this->descriptions[$language_name][] = $language_code;
|
||||
}
|
||||
|
||||
|
||||
private function UnsetDescription($language_name)
|
||||
{
|
||||
foreach($this->descriptions as &$d)
|
||||
{
|
||||
foreach($d as $k=>$l)
|
||||
{
|
||||
if($l === $language_name)
|
||||
unset($d[$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a scanner from the table
|
||||
*
|
||||
* \param language_name may be either a string or an array of strings, each of
|
||||
* which will be removed from the lookup table.
|
||||
*/
|
||||
public function RemoveScanner($language_name)
|
||||
{
|
||||
if (is_array($language_name))
|
||||
{
|
||||
foreach($language_name as $l)
|
||||
{
|
||||
unset($this->lookup_table[$l]);
|
||||
$this->UnsetDescription($l);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->UnsetDescription($language_name);
|
||||
unset($this->lookup_table[$language_name]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default scanner. This is used when none matches a lookup
|
||||
* \param scanner the LuminousScanner object
|
||||
*/
|
||||
public function SetDefaultScanner($scanner)
|
||||
{
|
||||
$this->default_scanner = $scanner;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method which retrives the desired scanner array, and
|
||||
* recursively settles the include dependencies while doing so.
|
||||
* \param language_name the name under which the gramar was originally indexed
|
||||
* \param default if true: if the scanner doesn't exist, return the default
|
||||
* scanner. If false, return false
|
||||
* \return the scanner-array stored for the given language name
|
||||
* \internal
|
||||
* \see LuminousScanners::GetScanner
|
||||
*/
|
||||
private function GetScannerArray($language_name, $default=true)
|
||||
{
|
||||
$g = null;
|
||||
if (array_key_exists($language_name, $this->lookup_table))
|
||||
$g = $this->lookup_table[$language_name];
|
||||
elseif($this->default_scanner !== null && $default === true)
|
||||
$g = $this->lookup_table[$this->default_scanner];
|
||||
|
||||
if ($g === null)
|
||||
return false;
|
||||
|
||||
// Break on circular dependencies.
|
||||
if (!isset($this->resolved_dependencies[$language_name]))
|
||||
{
|
||||
$this->resolved_dependencies[$language_name] = true;
|
||||
foreach($g['dependencies'] as $d)
|
||||
{
|
||||
$this->GetScannerArray($d, $default);
|
||||
}
|
||||
if ($g['file'] !== null)
|
||||
require_once($g['file']);
|
||||
}
|
||||
return $g;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a scanner for a language
|
||||
* \param language_name the name under which the gramar was originally indexed
|
||||
* \param default if true: if the scanner doesn't exist, return the default
|
||||
* scanner. If false, return false
|
||||
* \return The scanner, the default scanner, or null.
|
||||
*/
|
||||
function GetScanner($language_name, $default=true, $instance=true)
|
||||
{
|
||||
$resolved_dependencies = array();
|
||||
$g = $this->GetScannerArray($language_name, $default);
|
||||
$resolved_dependencies = array();
|
||||
|
||||
if ($g !== false) {
|
||||
return $instance? new $g['scanner'] : $g['scanner'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function GetDescription($language_name) {
|
||||
$resolved_dependencies = array();
|
||||
$g = $this->GetScannerArray($language_name, true);
|
||||
$resolved_dependencies = array();
|
||||
if ($g !== false) {
|
||||
return $g['description'];
|
||||
} else return null;
|
||||
}
|
||||
/**
|
||||
* Returns a list of known aliases for scanners.
|
||||
* \return a list, the list is such that each item is itself a list whose
|
||||
* elements are aliases of the same scanner. eg:
|
||||
* [
|
||||
* ['c', 'cpp'],
|
||||
* ['java'],
|
||||
* ['py', 'python']
|
||||
* ]
|
||||
* etc.
|
||||
*
|
||||
*/
|
||||
function ListScanners()
|
||||
{
|
||||
$l = $this->descriptions;
|
||||
return $l;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// \endcond
|
||||
|
|
@ -1,386 +0,0 @@
|
|||
<?php
|
||||
|
||||
/// \cond ALL
|
||||
/*
|
||||
* This is a simple CSS parser, which we use to make CSS themes portable.
|
||||
* The basic idea is we're going to use the CSS scanner to tokenize the
|
||||
* input, then we're going to parse the tokens.
|
||||
* There is some amount of redundancy here with the scanner, but this way
|
||||
* means that we are 1) not dependent too much on the implementation of
|
||||
* the scanner, and 2) not having to write our own with full pattern matching.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once dirname(__FILE__) . '/../luminous.php';
|
||||
|
||||
// source: http://www.w3schools.com/css/css_colornames.asp
|
||||
global $luminous_col2hex;
|
||||
$luminous_col2hex = array(
|
||||
'aliceblue' => '#f0f8ff',
|
||||
'antiquewhite' => '#faebd7',
|
||||
'aqua' => '#00ffff',
|
||||
'aquamarine' => '#7fffd4',
|
||||
'azure' => '#f0ffff',
|
||||
'beige' => '#f5f5dc',
|
||||
'bisque' => '#ffe4c4',
|
||||
'black' => '#000000',
|
||||
'blanchedalmond' => '#ffebcd',
|
||||
'blue' => '#0000ff',
|
||||
'blueviolet' => '#8a2be2',
|
||||
'brown' => '#a52a2a',
|
||||
'burlywood' => '#deb887',
|
||||
'cadetblue' => '#5f9ea0',
|
||||
'chartreuse' => '#7fff00',
|
||||
'chocolate' => '#d2691e',
|
||||
'coral' => '#ff7f50',
|
||||
'cornflowerblue' => '#6495ed',
|
||||
'cornsilk' => '#fff8dc',
|
||||
'crimson' => '#dc143c',
|
||||
'cyan' => '#00ffff',
|
||||
'darkblue' => '#00008b',
|
||||
'darkcyan' => '#008b8b',
|
||||
'darkgoldenrod' => '#b8860b',
|
||||
'darkgray' => '#a9a9a9',
|
||||
'darkgrey' => '#a9a9a9',
|
||||
'darkgreen' => '#006400',
|
||||
'darkkhaki' => '#bdb76b',
|
||||
'darkmagenta' => '#8b008b',
|
||||
'darkolivegreen' => '#556b2f',
|
||||
'darkorange' => '#ff8c00',
|
||||
'darkorchid' => '#9932cc',
|
||||
'darkred' => '#8b0000',
|
||||
'darksalmon' => '#e9967a',
|
||||
'darkseagreen' => '#8fbc8f',
|
||||
'darkslateblue' => '#483d8b',
|
||||
'darkslategray' => '#2f4f4f',
|
||||
'darkslategrey' => '#2f4f4f',
|
||||
'darkturquoise' => '#00ced1',
|
||||
'darkviolet' => '#9400d3',
|
||||
'deeppink' => '#ff1493',
|
||||
'deepskyblue' => '#00bfff',
|
||||
'dimgray' => '#696969',
|
||||
'dimgrey' => '#696969',
|
||||
'dodgerblue' => '#1e90ff',
|
||||
'firebrick' => '#b22222',
|
||||
'floralwhite' => '#fffaf0',
|
||||
'forestgreen' => '#228b22',
|
||||
'fuchsia' => '#ff00ff',
|
||||
'gainsboro' => '#dcdcdc',
|
||||
'ghostwhite' => '#f8f8ff',
|
||||
'gold' => '#ffd700',
|
||||
'goldenrod' => '#daa520',
|
||||
'gray' => '#808080',
|
||||
'grey' => '#808080',
|
||||
'green' => '#008000',
|
||||
'greenyellow' => '#adff2f',
|
||||
'honeydew' => '#f0fff0',
|
||||
'hotpink' => '#ff69b4',
|
||||
'indianred' => '#cd5c5c',
|
||||
'indigo' => '#4b0082',
|
||||
'ivory' => '#fffff0',
|
||||
'khaki' => '#f0e68c',
|
||||
'lavender' => '#e6e6fa',
|
||||
'lavenderblush' => '#fff0f5',
|
||||
'lawngreen' => '#7cfc00',
|
||||
'lemonchiffon' => '#fffacd',
|
||||
'lightblue' => '#add8e6',
|
||||
'lightcoral' => '#f08080',
|
||||
'lightcyan' => '#e0ffff',
|
||||
'lightgoldenrodyellow' => '#fafad2',
|
||||
'lightgray' => '#d3d3d3',
|
||||
'lightgrey' => '#d3d3d3',
|
||||
'lightgreen' => '#90ee90',
|
||||
'lightpink' => '#ffb6c1',
|
||||
'lightsalmon' => '#ffa07a',
|
||||
'lightseagreen' => '#20b2aa',
|
||||
'lightskyblue' => '#87cefa',
|
||||
'lightslategray' => '#778899',
|
||||
'lightslategrey' => '#778899',
|
||||
'lightsteelblue' => '#b0c4de',
|
||||
'lightyellow' => '#ffffe0',
|
||||
'lime' => '#00ff00',
|
||||
'limegreen' => '#32cd32',
|
||||
'linen' => '#faf0e6',
|
||||
'magenta' => '#ff00ff',
|
||||
'maroon' => '#800000',
|
||||
'mediumaquamarine' => '#66cdaa',
|
||||
'mediumblue' => '#0000cd',
|
||||
'mediumorchid' => '#ba55d3',
|
||||
'mediumpurple' => '#9370d8',
|
||||
'mediumseagreen' => '#3cb371',
|
||||
'mediumslateblue' => '#7b68ee',
|
||||
'mediumspringgreen' => '#00fa9a',
|
||||
'mediumturquoise' => '#48d1cc',
|
||||
'mediumvioletred' => '#c71585',
|
||||
'midnightblue' => '#191970',
|
||||
'mintcream' => '#f5fffa',
|
||||
'mistyrose' => '#ffe4e1',
|
||||
'moccasin' => '#ffe4b5',
|
||||
'navajowhite' => '#ffdead',
|
||||
'navy' => '#000080',
|
||||
'oldlace' => '#fdf5e6',
|
||||
'olive' => '#808000',
|
||||
'olivedrab' => '#6b8e23',
|
||||
'orange' => '#ffa500',
|
||||
'orangered' => '#ff4500',
|
||||
'orchid' => '#da70d6',
|
||||
'palegoldenrod' => '#eee8aa',
|
||||
'palegreen' => '#98fb98',
|
||||
'paleturquoise' => '#afeeee',
|
||||
'palevioletred' => '#d87093',
|
||||
'papayawhip' => '#ffefd5',
|
||||
'peachpuff' => '#ffdab9',
|
||||
'peru' => '#cd853f',
|
||||
'pink' => '#ffc0cb',
|
||||
'plum' => '#dda0dd',
|
||||
'powderblue' => '#b0e0e6',
|
||||
'purple' => '#800080',
|
||||
'red' => '#ff0000',
|
||||
'rosybrown' => '#bc8f8f',
|
||||
'royalblue' => '#4169e1',
|
||||
'saddlebrown' => '#8b4513',
|
||||
'salmon' => '#fa8072',
|
||||
'sandybrown' => '#f4a460',
|
||||
'seagreen' => '#2e8b57',
|
||||
'seashell' => '#fff5ee',
|
||||
'sienna' => '#a0522d',
|
||||
'silver' => '#c0c0c0',
|
||||
'skyblue' => '#87ceeb',
|
||||
'slateblue' => '#6a5acd',
|
||||
'slategray' => '#708090',
|
||||
'slategrey' => '#708090',
|
||||
'snow' => '#fffafa',
|
||||
'springgreen' => '#00ff7f',
|
||||
'steelblue' => '#4682b4',
|
||||
'tan' => '#d2b48c',
|
||||
'teal' => '#008080',
|
||||
'thistle' => '#d8bfd8',
|
||||
'tomato' => '#ff6347',
|
||||
'turquoise' => '#40e0d0',
|
||||
'violet' => '#ee82ee',
|
||||
'wheat' => '#f5deb3',
|
||||
'white' => '#ffffff',
|
||||
'whitesmoke' => '#f5f5f5',
|
||||
'yellow' => '#ffff00',
|
||||
'yellowgreen' => '#9acd32'
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Simple CSS parser to make theme files portable across output formats.
|
||||
*
|
||||
* This is CSS parser for making Luminous themes portable. This is not
|
||||
* a general CSS parser, but could be with a bit of work!
|
||||
*
|
||||
* Parses CSS strings into a map of rules and values. The resulting map is
|
||||
* a somewhat simplified version of CSS.
|
||||
* For simplificity we re-map the following properties:
|
||||
*
|
||||
* background-color => bgcolor
|
||||
* font-weight => bold? (bool)
|
||||
* font-style => italic? (bool)
|
||||
* text-decoration => underline? OR strikethrough? (bool)
|
||||
*
|
||||
* We also drop things like '!important'.
|
||||
*
|
||||
* Colours are stored as 6-digit hexadecimal strings with leading #. 3-digit
|
||||
* hex strings are expanded to their 6-digit equivalents. Named colour aliases
|
||||
* are replaced with their hex equivalents.
|
||||
*/
|
||||
class LuminousCSSParser {
|
||||
|
||||
private $data = array();
|
||||
|
||||
private static function format_property_value($prop, $value) {
|
||||
global $luminous_col2hex;
|
||||
// drop !important
|
||||
$value = preg_replace('/\s*!important$/', '', $value);
|
||||
// expand 3-digit hex
|
||||
if (preg_match('/^#([a-fA-F0-9]{3})$/', $value, $m))
|
||||
$value .= $m[1];
|
||||
// remove quotes
|
||||
$value = trim($value);
|
||||
if (preg_match('/^(["\'])(.*)\\1$/', $value, $m)) $value = $m[2];
|
||||
|
||||
// now get it into a simpler form:
|
||||
switch($prop) {
|
||||
case 'color':
|
||||
if (isset($luminous_col2hex[$value]))
|
||||
$value = $luminous_col2hex[$value];
|
||||
break;
|
||||
case 'background-color':
|
||||
$prop = 'bgcolor';
|
||||
if (isset($luminous_col2hex[$value]))
|
||||
$value = $luminous_col2hex[$value];
|
||||
break;
|
||||
case 'font-weight':
|
||||
$prop = 'bold';
|
||||
$value = in_array($value, array('bold', 'bolder', '700', '800', '900'));
|
||||
break;
|
||||
case 'font-style':
|
||||
$prop = 'italic';
|
||||
$value = in_array($value, array('italic', 'oblique'));
|
||||
case 'text-decoration':
|
||||
if ($value === 'line-through') {
|
||||
$prop = 'strikethrough';
|
||||
$value = true;
|
||||
}
|
||||
elseif($value === 'underline') {
|
||||
$prop = 'underline';
|
||||
$value = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return array($prop, $value);
|
||||
}
|
||||
|
||||
|
||||
private static function format_css_array($css) {
|
||||
$css_ = array();
|
||||
|
||||
// now cleanup the array, drop !important
|
||||
foreach($css as $selector=>$rules) {
|
||||
$rules_ = array();
|
||||
foreach($rules as $prop=>$value) {
|
||||
list($prop, $value) = self::format_property_value($prop, $value);
|
||||
$rules_[$prop] = $value;
|
||||
}
|
||||
// now split selector by comma
|
||||
$selectors = preg_split('/\s*,\s*/', $selector);
|
||||
|
||||
foreach($selectors as $s) {
|
||||
// drop .luminous from the selector
|
||||
$s = preg_replace('/^\.luminous\s*/', '', $s);
|
||||
// now we assume that if something is in the form .classname then
|
||||
// it's probably of interest, ie directly specifying a rule for a
|
||||
// highlighting calss.
|
||||
// and if it's not in that form them
|
||||
// it's probably something else (like a rule for hyperlinks or something)
|
||||
if (preg_match('/\.([\-\w]+)/', $s, $m)) $s = $m[1];
|
||||
else continue;
|
||||
if (!isset($css_[$s])) $css_[$s] = array();
|
||||
$css_[$s] = array_merge($css_[$s], $rules_);
|
||||
}
|
||||
}
|
||||
return $css_;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parsed rules. The rules are an array in the format:
|
||||
*
|
||||
* array(
|
||||
* $rule_name => array($property => $value)
|
||||
* )
|
||||
*
|
||||
* So, $rules['.comment']['color'] would return the color property of comment
|
||||
* classes.
|
||||
*/
|
||||
function rules() {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value for the given property of the given rule name, or
|
||||
* returns $default.
|
||||
* @param $rule_name the CSS rule name, e.g. 'a', '.luminous', etc
|
||||
* @param $property the property to access, e.g. 'color'
|
||||
* @param $default the value to return in the case that the rule/proeprty
|
||||
* was not set. Default: null
|
||||
*/
|
||||
function value($rule_name, $property, $default=null) {
|
||||
if (isset($this->data[$rule_name][$property]))
|
||||
return $this->data[$rule_name][$property];
|
||||
else return $default;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a CSS string into a nested map of values.
|
||||
* See LuminousCSSParser::rules() for the structure.
|
||||
* @param $string the CSS string
|
||||
* @returns the rule map
|
||||
*/
|
||||
function convert($string) {
|
||||
$css = self::parse($string);
|
||||
$data = self::format_css_array($css);
|
||||
$this->data = $data;
|
||||
return $data;
|
||||
}
|
||||
|
||||
private static function parse($string) {
|
||||
global $luminous_col2hex;
|
||||
// singleton from usage API
|
||||
global $luminous_;
|
||||
$scanner = $luminous_->scanners->GetScanner('css');
|
||||
$scanner->string($string);
|
||||
$scanner->init();
|
||||
$scanner->main();
|
||||
$tokens = $scanner->token_array();
|
||||
|
||||
$block = false;
|
||||
$expect;
|
||||
$key;
|
||||
$value;
|
||||
$selector = '';
|
||||
|
||||
$css = array();
|
||||
// array of selectors => rules, where rules is an array itself of (property, value)
|
||||
// note this is going to get @font-face wrong, but we don't care about that.
|
||||
for($i=0; $i<count($tokens); $i++) {
|
||||
list($tok, $content, ) = $tokens[$i];
|
||||
if ($tok === 'COMMENT') continue;
|
||||
if (!$block) {
|
||||
$expect = 'key';
|
||||
// not in block, look for selectors.
|
||||
if ($content === '{') {
|
||||
$block = true;
|
||||
$key = '';
|
||||
$selector = trim($selector);
|
||||
|
||||
if (!isset($css[$selector]))
|
||||
$css[$selector] = array();
|
||||
}
|
||||
else {
|
||||
$selector .= $content;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ($content === '}') {
|
||||
$block = false;
|
||||
$value = null;
|
||||
$key = null;
|
||||
$selector = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
// expecting key, append to the key or finalise it
|
||||
if ($expect === 'key') {
|
||||
if ($content === ':') {
|
||||
$expect = 'value';
|
||||
$value = '';
|
||||
}
|
||||
else $key .= $content;
|
||||
} elseif($expect === 'value') {
|
||||
// expecting value, append to it or finalise and insert it (with the key)
|
||||
if ($content === ';') {
|
||||
// don't overwrite things - use the first definition
|
||||
// this is for stuff like rgba which might re-define something
|
||||
$key = trim($key);
|
||||
$value = trim($value);
|
||||
if (!isset($css[$selector][$key])) {
|
||||
$css[$selector][$key] = $value;
|
||||
}
|
||||
$expect = 'key';
|
||||
$key = '';
|
||||
$value = '';
|
||||
}
|
||||
else $value .= $content;
|
||||
}
|
||||
}
|
||||
return $css;
|
||||
}
|
||||
}
|
||||
/// \endcond
|
||||
|
|
@ -1 +0,0 @@
|
|||
allow from all
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
|
||||
.luminous {
|
||||
background-color: #EEEEED;
|
||||
}
|
||||
|
||||
/* line numbers */
|
||||
.luminous .line-numbers {
|
||||
background-color: #F0F0F0 !important;
|
||||
border-right: 1px dashed #BBBBBB !important;
|
||||
color: #555555;
|
||||
}
|
||||
|
||||
.luminous .code .highlight {
|
||||
background-color: #A4C0E4;
|
||||
background-color: rgba(164, 192, 228, 0.5);
|
||||
}
|
||||
|
||||
|
||||
.luminous .character { color: #9C0F0F !important; }
|
||||
.luminous .comment { color: #57401E !important; font-style: italic !important;}
|
||||
.luminous .comment_note { font-weight: bold !important; font-style:normal !important;}
|
||||
.luminous .constant { color : #462886 !important; }
|
||||
.luminous .delimiter {color: #CF4913 !important; font-weight:bold !important; }
|
||||
.luminous .diff_header_new{color: #008C00 !important;}
|
||||
.luminous .diff_header_old{color: #BF0303 !important;}
|
||||
.luminous .diff_range{color:#0000FF !important;}
|
||||
.luminous .doccomment{color: #00734D !important;}
|
||||
.luminous .doctag {color: #00BF00 !important; font-weight: bold !important;}
|
||||
.luminous .docproperty{font-weight: bold !important;}
|
||||
.luminous .esc{color: #8F6B32 !important;}
|
||||
.luminous .function{ color: #E20800 !important;}
|
||||
.luminous .heredoc, .luminous .string {
|
||||
color: #00892C !important;
|
||||
background-color: rgba(119, 183, 83, 0.15) !important;
|
||||
}
|
||||
.luminous .htmltag {
|
||||
font-weight: bold !important;
|
||||
color: #644A9B !important;
|
||||
}
|
||||
.luminous .interpolation {background-color: rgba(164, 192, 228, 0.15) !important;}
|
||||
.luminous .keyword { font-weight:bold !important; color: #2C72C7 !important; }
|
||||
.luminous .numeric {color: #00BF00 !important; }
|
||||
.luminous .operator {color: #E20071 !important; }
|
||||
.luminous .obj {}
|
||||
.luminous .oo { color: #00A7B3 !important; }
|
||||
.luminous .preprocessor { color: #004D00 !important; }
|
||||
.luminous .regex {color: #644A9B !important; }
|
||||
.luminous .type { color: #730055 !important; }
|
||||
.luminous .user_function {font-weight: bold !important;}
|
||||
.luminous .value{ color: #555753 !important; }
|
||||
.luminous .variable { color: #00438A !important; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* this stuff has to come after the other rules because it will probably
|
||||
* override some of them
|
||||
*/
|
||||
.luminous .diff_old{
|
||||
background-color:#FFBFBF !important;
|
||||
background-color: rgba(232, 87, 82, 0.15) !important;
|
||||
}
|
||||
.luminous .diff_new{
|
||||
background-color:#BFFFBF !important;
|
||||
background-color: rgba(0, 191, 0, 0.15) !important;
|
||||
}
|
||||
.luminous .diff_unchanged, .luminous .diff_unchanged * {
|
||||
color: #888A85 !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
.luminous {
|
||||
color:black !important;
|
||||
border-color: #ddd;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.luminous .highlight {
|
||||
background-color:#FFFFCC;
|
||||
}
|
||||
|
||||
/* line numbers */
|
||||
.luminous .line-numbers {
|
||||
background-color:#ECECEC !important;
|
||||
color: #aaa !important;
|
||||
border-right:1px solid #ddd !important;
|
||||
}
|
||||
.luminous .code {
|
||||
}
|
||||
|
||||
.luminous a.link, .luminous a.link:visited {
|
||||
color:blue !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.luminous .character{color:#DD1144 !important;}
|
||||
|
||||
.luminous .comment{color:#999988 !important; font-style:italic !important;}
|
||||
|
||||
/* NOTE: TODO: etc. */
|
||||
.luminous .comment_note{
|
||||
background-color:#FFB2B0 !important;
|
||||
background-color:rgba(255, 178, 176, 0.70) !important;
|
||||
color:black !important;
|
||||
font-style:normal !important;}
|
||||
.luminous .constant{}
|
||||
.luminous .esc{color:#057CA3 !important;}
|
||||
.luminous .function{color:#0086B3 !important;}
|
||||
.luminous .heredoc{color:#DD1144 !important; }
|
||||
.luminous .htmltag{color:#000080 !important;}
|
||||
.luminous .keyword{font-weight:bold !important;}
|
||||
.luminous .numeric {color:#009999 !important;}
|
||||
.luminous .operator{font-weight: bold !important;}
|
||||
|
||||
.luminous .oo{/*color:#339900 !important;*/}
|
||||
.luminous .obj{color:#3366FF !important;}
|
||||
.luminous .preprocessor{color:#999999 !important; font-weight: bold !important;}
|
||||
.luminous .shebang{font-weight:bold !important; font-style:normal !important; color:purple !important;}
|
||||
.luminous .string{color:#DD1144 !important; }
|
||||
.luminous .type{color:#445588 !important; font-weight: bold;}
|
||||
/* not used*/
|
||||
.luminous .user_function{color: #990000 !important; font-weight:bold !important;}
|
||||
.luminous .value{color:#999999 !important;}
|
||||
.luminous .variable{color:#008080 !important;}
|
||||
|
||||
.luminous .doccomment{color:blue !important;}
|
||||
.luminous .doctag {color:#CA60CA !important;}
|
||||
.luminous .docstr {color:red !important;}
|
||||
.luminous .docproperty{color:#0095FF !important; font-weight:bold !important;}
|
||||
|
||||
|
||||
|
||||
.luminous .lang_latex{color:blue !important;}
|
||||
.luminous .latex_function{color:red !important; font-weight:normal !important;}
|
||||
.luminous .latex_operator{color:black !important;}
|
||||
|
||||
.luminous .make_target{color:magenta !important;}
|
||||
.luminous .make_dep{color: blue !important;}
|
||||
|
||||
.luminous .regex{color:#8000FF !important;
|
||||
background-color:#F9F3FF !important;
|
||||
background-color:rgba(231, 206, 255, 0.20) !important;
|
||||
}
|
||||
.luminous .regex_subpattern{font-weight:bold !important; color:black !important;}
|
||||
.luminous .regex_class_marker{color:#0083E1 !important; font-weight:bold !important;}
|
||||
.luminous .regex_subpattern_marker{color:green !important; font-weight:bold !important;}
|
||||
.luminous .regex_repeat_marker {color:blue !important;}
|
||||
.luminous .regex_operator{color:green !important;}
|
||||
|
||||
/* Specific to the whitespace language */
|
||||
.luminous .whitespace_space{background-color:#FF5151 !important;}
|
||||
.luminous .whitespace_tab{background-color:#A1B6FF !important;}
|
||||
|
||||
|
||||
|
||||
|
||||
.luminous .diff_header_new{color:green !important;}
|
||||
.luminous .diff_header_old{color:red !important;}
|
||||
.luminous .diff_range{color:blue !important;}
|
||||
.luminous .diff_old{background-color:#FFBFBF !important;
|
||||
background-color: rgba(255, 191, 191, 0.5) !important;
|
||||
}
|
||||
.luminous .diff_new{background-color:#BFFFBF !important;
|
||||
background-color: rgba(191, 255, 191, 0.5) !important;
|
||||
}
|
||||
.luminous .diff_unchanged{
|
||||
color: #888888 !important;
|
||||
|
||||
}
|
||||
|
||||
.luminous .diff_unchanged * {
|
||||
background-color: transparent !important;
|
||||
color: #888888 !important;
|
||||
}
|
||||
|
||||
|
||||
.luminous .xml {
|
||||
color: #666 !important;
|
||||
}
|
||||
.luminous .xml * {
|
||||
color: black !important;
|
||||
}
|
||||
.luminous .xml .type {
|
||||
color: #00892C !important;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
.luminous .xml .htmltag {
|
||||
color: #2C72C7 !important;
|
||||
}
|
||||
.luminous .xml .string {
|
||||
color: #DD1144 !important;
|
||||
}
|
||||
.luminous .xml .comment {
|
||||
color: gray !important;
|
||||
}
|
||||
|
||||
|
||||
.luminous .interpolation * {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
.luminous .interpolation {
|
||||
font-style: italic;
|
||||
/* background-color: rgba(30, 80, 200, 0.1); */
|
||||
}
|
||||
|
||||
.luminous .delimiter {
|
||||
font-weight:bold;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 823 B |
Binary file not shown.
|
Before Width: | Height: | Size: 833 B |
|
|
@ -1,117 +0,0 @@
|
|||
/**
|
||||
* Kimono - heavily based on the Monokai theme.
|
||||
*
|
||||
* Dark, simple and uncluttered.
|
||||
*
|
||||
* Some colours stolen from http://www.eclipsecolorthemes.org/?view=theme&id=52
|
||||
*/
|
||||
|
||||
.luminous {
|
||||
color : #F8F8F2;
|
||||
border-color: #555;
|
||||
background-color: #272822;
|
||||
}
|
||||
.luminous .code {
|
||||
}
|
||||
/* line numbers */
|
||||
.luminous .line-numbers {
|
||||
border-right: 1px solid #d0d0d0 !important;
|
||||
background-color: #272822 !important;
|
||||
color : #F8F8F2 !important;
|
||||
|
||||
|
||||
}
|
||||
.luminous .highlight {
|
||||
background-color: #3E3D32 !important;
|
||||
}
|
||||
|
||||
.luminous .comment {
|
||||
color: #75715E !important;
|
||||
}
|
||||
.luminous .preprocessor {
|
||||
color: #9C977D !important;
|
||||
}
|
||||
.luminous .comment_note {
|
||||
color: #CCDF32 !important;
|
||||
}
|
||||
.luminous .doccomment {
|
||||
color: #D9E577 !important;
|
||||
}
|
||||
.luminous .doctag {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
.luminous .operator {
|
||||
color: #F95994 !important;
|
||||
}
|
||||
.luminous .numeric {
|
||||
color: #7FB347 !important;
|
||||
}
|
||||
.luminous .string, .luminous .character, .luminous .heredoc, .luminous .regex {
|
||||
color: #E6DB74 !important;
|
||||
}
|
||||
.luminous .keyword {
|
||||
color: #66CCB3 !important;
|
||||
}
|
||||
.luminous .variable {
|
||||
color: #79ABFF !important;
|
||||
}
|
||||
.luminous .constant {
|
||||
color: #EFB571 !important;
|
||||
}
|
||||
.luminous .function {
|
||||
color: #79ABFF !important;
|
||||
}
|
||||
.luminous .user_function {
|
||||
color: #BED6FF !important;
|
||||
}
|
||||
|
||||
.luminous .htmltag {
|
||||
color: #BED6FF !important;
|
||||
}
|
||||
|
||||
.luminous .type {
|
||||
color: #BFA4A4 !important;
|
||||
}
|
||||
|
||||
.luminous .delimiter {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.luminous .esc {
|
||||
color: #AE81FF !important;
|
||||
}
|
||||
|
||||
.luminous .diff_header_old {
|
||||
color: #D25252 !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
.luminous .diff_header_new {
|
||||
color: #51D251 !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
.luminous .diff_old {
|
||||
color: #D25252 !important;
|
||||
background-color: #2A0000 !important;
|
||||
}
|
||||
.luminous .diff_new {
|
||||
color: #51D251 !important;
|
||||
background-color: #002A00 !important;
|
||||
}
|
||||
|
||||
.luminous .diff_unchanged{
|
||||
color: #888888 !important;
|
||||
|
||||
}
|
||||
|
||||
.luminous .diff_unchanged * {
|
||||
background-color: transparent !important;
|
||||
color: #888888 !important;
|
||||
}
|
||||
|
||||
.luminous .diff_range {
|
||||
color: #79ABFF !important;
|
||||
}
|
||||
|
||||
.luminous a {
|
||||
color: #F95994 !important;
|
||||
}
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
.luminous {
|
||||
font-size: inherit;
|
||||
text-align: left;
|
||||
font-family: "Consolas", "DejaVu Sans Mono", monospace;
|
||||
overflow: auto;
|
||||
border: 2px solid #dddddd;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
/* line numbers */ }
|
||||
.luminous.inline {
|
||||
min-width: 1px;
|
||||
max-width: none;
|
||||
line-height: normal; }
|
||||
.luminous.inline, .luminous.inline div, .luminous.inline pre {
|
||||
padding: 0;
|
||||
*display: inline;
|
||||
display: inline-block; }
|
||||
.luminous.inline pre {
|
||||
overflow: visible; }
|
||||
.luminous .link, .luminous .link:visited {
|
||||
text-decoration: underline; }
|
||||
.luminous .link:hover {
|
||||
text-decoration: none; }
|
||||
.luminous pre {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: transparent none;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
width: auto; }
|
||||
.luminous > pre {
|
||||
padding-left: 1em; }
|
||||
.luminous table {
|
||||
width: 100%;
|
||||
vertical-align: top;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0; }
|
||||
.luminous table td {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
vertical-align: top; }
|
||||
.luminous table td.code-container {
|
||||
width: 100%; }
|
||||
.luminous table .code {
|
||||
transition-property: padding-left;
|
||||
transition-duration: 0.2s;
|
||||
transition-timing-function: ease-in;
|
||||
-webkit-transition-property: padding-left;
|
||||
-webkit-transition-duration: 0.2s;
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
-moz-transition-property: padding-left;
|
||||
-moz-transition-duration: 0.2s;
|
||||
-moz-transition-timing-function: ease-in;
|
||||
-o-transition-property: padding-left;
|
||||
-o-transition-duration: 0.2s;
|
||||
-o-transition-timing-function: ease-in;
|
||||
-ms-transition-property: padding-left;
|
||||
-ms-transition-duration: 0.2s;
|
||||
-ms-transition-timing-function: ease-in; }
|
||||
.luminous table .code > span {
|
||||
padding: 0 0 0 1em;
|
||||
display: block;
|
||||
transition-property: background-color;
|
||||
transition-duration: 0.5s;
|
||||
transition-timing-function: ease-in;
|
||||
-webkit-transition-property: background-color;
|
||||
-webkit-transition-duration: 0.5s;
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
-moz-transition-property: background-color;
|
||||
-moz-transition-duration: 0.5s;
|
||||
-moz-transition-timing-function: ease-in;
|
||||
-o-transition-property: background-color;
|
||||
-o-transition-duration: 0.5s;
|
||||
-o-transition-timing-function: ease-in;
|
||||
-ms-transition-property: background-color;
|
||||
-ms-transition-duration: 0.5s;
|
||||
-ms-transition-timing-function: ease-in; }
|
||||
.luminous table .line-numbers {
|
||||
cursor: default;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
max-width: 60px;
|
||||
transition-property: max-width;
|
||||
transition-duration: 0.2s;
|
||||
transition-timing-function: ease-in;
|
||||
-webkit-transition-property: max-width;
|
||||
-webkit-transition-duration: 0.2s;
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
-moz-transition-property: max-width;
|
||||
-moz-transition-duration: 0.2s;
|
||||
-moz-transition-timing-function: ease-in;
|
||||
-o-transition-property: max-width;
|
||||
-o-transition-duration: 0.2s;
|
||||
-o-transition-timing-function: ease-in;
|
||||
-ms-transition-property: max-width;
|
||||
-ms-transition-duration: 0.2s;
|
||||
-ms-transition-timing-function: ease-in; }
|
||||
.luminous table .line-numbers span {
|
||||
padding: 0 0.5em;
|
||||
display: block; }
|
||||
.luminous table .line-numbers span:nth-child(5n) {
|
||||
font-weight: bold; }
|
||||
.luminous table .line-numbers.collapsed {
|
||||
border: none;
|
||||
max-width: 0; }
|
||||
.luminous div {
|
||||
border-radius: inherit; }
|
||||
.luminous .line-number-control {
|
||||
transition-property: left;
|
||||
transition-duration: 0.2s;
|
||||
transition-timing-function: ease-in;
|
||||
-webkit-transition-property: left;
|
||||
-webkit-transition-duration: 0.2s;
|
||||
-webkit-transition-timing-function: ease-in;
|
||||
-moz-transition-property: left;
|
||||
-moz-transition-duration: 0.2s;
|
||||
-moz-transition-timing-function: ease-in;
|
||||
-o-transition-property: left;
|
||||
-o-transition-duration: 0.2s;
|
||||
-o-transition-timing-function: ease-in;
|
||||
-ms-transition-property: left;
|
||||
-ms-transition-duration: 0.2s;
|
||||
-ms-transition-timing-function: ease-in;
|
||||
height: 26px;
|
||||
width: 18px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
cursor: pointer;
|
||||
background: transparent url(icons/chevron-left.png); }
|
||||
.luminous .line-number-control.show-line-numbers {
|
||||
background: transparent url(icons/chevron-right.png); }
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
// This is the source file for luminous.css
|
||||
// If you want to edit it, you'll need SASS.
|
||||
// http://sass-lang.com/
|
||||
|
||||
@mixin vendor-prefix($property, $value) {
|
||||
@each $prefix in '', -webkit-, -moz-, -o-, -ms- {
|
||||
#{$prefix}#{$property} : $value;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin transition($properties, $duration: 0.5s, $easing: ease-in) {
|
||||
@each $prefix in '', -webkit-, -moz-, -o-, -ms- {
|
||||
#{$prefix}transition-property: $properties;
|
||||
#{$prefix}transition-duration : $duration;
|
||||
#{$prefix}transition-timing-function: $easing;
|
||||
}
|
||||
}
|
||||
|
||||
.luminous {
|
||||
|
||||
font-size:inherit;
|
||||
text-align:left;
|
||||
font-family: "Consolas", "DejaVu Sans Mono", monospace;
|
||||
overflow: auto;
|
||||
|
||||
border: 2px solid #ddd;
|
||||
border-radius: 5px;
|
||||
|
||||
position: relative;
|
||||
|
||||
&.inline {
|
||||
min-width: 1px;
|
||||
max-width: none;
|
||||
line-height: normal;
|
||||
&, div, pre {
|
||||
padding: 0;
|
||||
*display: inline;
|
||||
display: inline-block;
|
||||
}
|
||||
pre {
|
||||
// this would otherwise get 'overflow auto', but auto seems to
|
||||
// cause it to sit a bit out of line with the text. So does 'hidden'.
|
||||
// in any case, this shouldn't overflow.
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
.link {
|
||||
&, &:visited {
|
||||
text-decoration: underline;
|
||||
}
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: transparent none;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
// non-line numbered, directly inside the .luminous
|
||||
& > pre {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
|
||||
/* line numbers */
|
||||
table {
|
||||
width: 100%;
|
||||
vertical-align: top;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
td {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
&.code-container { width: 100%; }
|
||||
}
|
||||
|
||||
.code {
|
||||
& > span {
|
||||
padding: 0 0 0 1em;
|
||||
display: block;
|
||||
@include transition(background-color);
|
||||
}
|
||||
@include transition(padding-left, 0.2s);
|
||||
}
|
||||
.line-numbers {
|
||||
cursor: default;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
span {
|
||||
padding: 0 0.5em;
|
||||
display: block;
|
||||
&:nth-child(5n) {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
max-width: 60px;
|
||||
@include transition(max-width, 0.2s);
|
||||
|
||||
&.collapsed {
|
||||
border: none;
|
||||
max-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
div {
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
||||
.line-number-control {
|
||||
@include transition(left, 0.2s);
|
||||
height: 26px;
|
||||
width: 18px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
cursor: pointer;
|
||||
// default: line numbers are shown
|
||||
background: transparent url(icons/chevron-left.png);
|
||||
&.show-line-numbers {
|
||||
// override: line numbers are hidden
|
||||
background: transparent url(icons/chevron-right.png);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
.luminous { border-color: #444; }
|
||||
|
||||
.luminous .character{color:#FF69B4 !important;}
|
||||
|
||||
.luminous .comment{color:gray !important; font-style:italic !important;}
|
||||
|
||||
/* NOTE: TODO: etc. */
|
||||
.luminous .comment_note{background-color:#E0FE37 !important;
|
||||
color:black !important;
|
||||
font-style:normal !important;}
|
||||
.luminous .constant{color:#0073AD !important; font-weight:bold !important;}
|
||||
.luminous .delimiter{ font-weight:bold !important;}
|
||||
.luminous .esc{color:#478CA3 !important;}
|
||||
.luminous .function{color:#99D1FF !important;}
|
||||
.luminous .heredoc{color:#FF6767 !important;}
|
||||
.luminous .htmltag{font-weight:bold !important; color:#66FFCC !important;}
|
||||
.luminous .keyword{font-weight:bold !important; color:#00FF00 !important;}
|
||||
.luminous .numeric {color:#B1B1FF !important;}
|
||||
.luminous .operator{color:#68FF68 !important;}
|
||||
.luminous .obj{color: #DCDCDC !important;}
|
||||
.luminous .oo{color:#C0FFFF !important;}
|
||||
.luminous .preprocessor{color:#DA1FDA !important;}
|
||||
.luminous .shebang{font-weight:bold !important; font-style:normal !important; color:#C0FFC0 !important;}
|
||||
.luminous .string{color:#FF6767 !important;}
|
||||
.luminous .type{color:#5CA0E4 !important;}
|
||||
/* not used*/
|
||||
.luminous .user_function{color: #0083E1 !important; font-weight:bold !important;}
|
||||
.luminous .value{color:green !important;}
|
||||
.luminous .variable{color:#8989A9 !important;}
|
||||
|
||||
.luminous .doccomment{color:#008100 !important;}
|
||||
.luminous .doctag {color:#CA60CA !important;}
|
||||
.luminous .docstr {color:#FF6767 !important;}
|
||||
.luminous .docproperty{color:#0095FF !important; font-weight:bold !important;}
|
||||
|
||||
.luminous .diff_header_new{color:green !important;}
|
||||
.luminous .diff_header_old{color:red !important;}
|
||||
.luminous .diff_range{color:#B1B1FF !important;}
|
||||
.luminous .diff_old{color:#AF0000 !important;}
|
||||
.luminous .diff_new{color:#00AF00 !important;}
|
||||
|
||||
.luminous .lang_latex{color:#B1B1FF !important;}
|
||||
.luminous .latex_function{color:#FF6767 !important; font-weight:normal !important;}
|
||||
.luminous .latex_operator{color:#676CFF !important;}
|
||||
|
||||
.luminous .make_target{color:magenta !important;}
|
||||
.luminous .make_dep{color: #B1B1FF !important;}
|
||||
|
||||
.luminous .regex{color:#BE7CFF !important;}
|
||||
.luminous .regex_subpattern{font-weight:bold !important; color:#FF6767 !important;}
|
||||
.luminous .regex_class_marker{color:#0083E1 !important; font-weight:bold !important;}
|
||||
.luminous .regex_subpattern_marker{color:green !important; font-weight:bold !important;}
|
||||
.luminous .regex_repeat_marker {color:#B1B1FF !important;}
|
||||
.luminous .regex_operator{color:green !important;}
|
||||
|
||||
/* Specific to the whitespace language */
|
||||
.luminous .whitespace_space{background-color:#FF5151 !important;}
|
||||
.luminous .whitespace_tab{background-color:#A1B6FF !important;}
|
||||
|
||||
.luminous .link, .luminous .link:visited
|
||||
{
|
||||
color:#00AAAA !important;
|
||||
}
|
||||
.luminous .link:hover
|
||||
{
|
||||
color:#00AA00 !important;
|
||||
}
|
||||
|
||||
/* line numbers */
|
||||
.luminous .line-numbers {
|
||||
background-color:#1E1E1E !important;
|
||||
border-right:1px solid #5F5F5F !important;
|
||||
color:#BCFFBC !important;
|
||||
}
|
||||
|
||||
|
||||
.luminous
|
||||
{
|
||||
background-color:#1E1E1E !important;
|
||||
color:#FFFDCC !important;
|
||||
}
|
||||
|
||||
.luminous .code.numbered > span:nth-child(2n)
|
||||
{
|
||||
background-color: #232323;
|
||||
}
|
||||
|
||||
.luminous .code .highlight
|
||||
{
|
||||
background-color:#404040;
|
||||
}
|
||||
|
||||
.luminous .code.numbered .highlight:nth-child(2n)
|
||||
{
|
||||
background-color:#454545;
|
||||
}
|
||||
|
||||
/* this stuff has to come after the other rules because it will probably
|
||||
* override some of them
|
||||
*/
|
||||
.luminous .diff_old{
|
||||
background-color:#7C4543 !important;
|
||||
background-color: rgba(232, 87, 82, 0.35) !important;
|
||||
color: white !important;
|
||||
}
|
||||
.luminous .diff_new{
|
||||
background-color:#3F612C !important;
|
||||
background-color: rgba(0, 191, 0, 0.35) !important;
|
||||
color: white !important;
|
||||
}
|
||||
.luminous .diff_unchanged, .luminous .diff_unchanged * {
|
||||
color: #888A85 !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
|
@ -1,163 +0,0 @@
|
|||
.luminous .character{color:#FF69B4 !important;}
|
||||
|
||||
.luminous .comment{color:gray !important; font-style:italic !important;}
|
||||
|
||||
/* NOTE: TODO: etc. */
|
||||
.luminous .comment_note{
|
||||
background-color:#FFB2B0 !important;
|
||||
background-color:rgba(255, 178, 176, 0.70) !important;
|
||||
color:black !important;
|
||||
font-style:normal !important;}
|
||||
.luminous .constant{color:#0073AD !important; font-weight:bold !important;}
|
||||
.luminous .esc{color:#057CA3 !important;}
|
||||
.luminous .function{color:purple !important;}
|
||||
.luminous .heredoc{color:red !important;
|
||||
background-color:#FFF8F8 !important;
|
||||
background-color:rgba(255, 248, 248, 0.20) !important;
|
||||
|
||||
|
||||
}
|
||||
.luminous .htmltag{font-weight:bold !important; color:purple !important;}
|
||||
.luminous .keyword{font-weight:bold !important; color:#0066FF !important;}
|
||||
.luminous .numeric {color:blue !important;}
|
||||
.luminous .operator{color:#0000BF !important;}
|
||||
|
||||
.luminous .oo{color:#339900 !important;}
|
||||
.luminous .obj{color:#3366FF !important;}
|
||||
.luminous .preprocessor{color:green !important;}
|
||||
.luminous .shebang{font-weight:bold !important; font-style:normal !important; color:purple !important;}
|
||||
.luminous .string{color:red !important;
|
||||
background-color:#FFF8F8 !important;
|
||||
background-color:rgba(255, 157, 157, 0.20) !important;
|
||||
|
||||
}
|
||||
.luminous .type{color:#0057AE !important;}
|
||||
/* not used*/
|
||||
.luminous .user_function{color: #000099 !important; font-weight:bold !important;}
|
||||
.luminous .value{color:green !important;}
|
||||
.luminous .variable{color:#4545A9 !important;}
|
||||
|
||||
.luminous .doccomment{color:blue !important;}
|
||||
.luminous .doctag {color:#CA60CA !important;}
|
||||
.luminous .docstr {color:red !important;}
|
||||
.luminous .docproperty{color:#0095FF !important; font-weight:bold !important;}
|
||||
|
||||
|
||||
|
||||
.luminous .lang_latex{color:blue !important;}
|
||||
.luminous .latex_function{color:red !important; font-weight:normal !important;}
|
||||
.luminous .latex_operator{color:black !important;}
|
||||
|
||||
.luminous .make_target{color:magenta !important;}
|
||||
.luminous .make_dep{color: blue !important;}
|
||||
|
||||
.luminous .regex{color:#8000FF !important;
|
||||
background-color:#F9F3FF !important;
|
||||
background-color:rgba(231, 206, 255, 0.20) !important;
|
||||
}
|
||||
.luminous .regex_subpattern{font-weight:bold !important; color:black !important;}
|
||||
.luminous .regex_class_marker{color:#0083E1 !important; font-weight:bold !important;}
|
||||
.luminous .regex_subpattern_marker{color:green !important; font-weight:bold !important;}
|
||||
.luminous .regex_repeat_marker {color:blue !important;}
|
||||
.luminous .regex_operator{color:green !important;}
|
||||
|
||||
/* Specific to the whitespace language */
|
||||
.luminous .whitespace_space{background-color:#FF5151 !important;}
|
||||
.luminous .whitespace_tab{background-color:#A1B6FF !important;}
|
||||
|
||||
|
||||
|
||||
|
||||
.luminous .diff_header_new{color:green !important;}
|
||||
.luminous .diff_header_old{color:red !important;}
|
||||
.luminous .diff_range{color:blue !important;}
|
||||
.luminous .diff_old{background-color:#FFBFBF !important;
|
||||
background-color: rgba(255, 191, 191, 0.5) !important;
|
||||
}
|
||||
.luminous .diff_new{background-color:#BFFFBF !important;
|
||||
background-color: rgba(191, 255, 191, 0.5) !important;
|
||||
}
|
||||
.luminous .diff_unchanged{
|
||||
color: #888888 !important;
|
||||
|
||||
}
|
||||
|
||||
.luminous .diff_unchanged * {
|
||||
background-color: transparent !important;
|
||||
color: #888888 !important;
|
||||
}
|
||||
|
||||
|
||||
.luminous .xml {
|
||||
color: #666 !important;
|
||||
}
|
||||
.luminous .xml * {
|
||||
color: black !important;
|
||||
}
|
||||
.luminous .xml .type {
|
||||
color: #2C72C7 !important;
|
||||
}
|
||||
.luminous .xml .htmltag {
|
||||
color: #00892C !important;
|
||||
/* font-weight: normal !important; */
|
||||
}
|
||||
.luminous .xml .string {
|
||||
color: #0057AE !important;
|
||||
}
|
||||
.luminous .xml .comment {
|
||||
color: gray !important;
|
||||
}
|
||||
|
||||
|
||||
.luminous .interpolation * {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
.luminous .interpolation {
|
||||
font-style: italic;
|
||||
background-color: rgba(30, 80, 200, 0.1);
|
||||
}
|
||||
|
||||
.luminous .delimiter {
|
||||
font-weight:bold;
|
||||
color: #644A9B;
|
||||
}
|
||||
|
||||
|
||||
.luminous .code
|
||||
{
|
||||
background-color: #FCFCFC !important;
|
||||
}
|
||||
|
||||
.luminous a.link, .luminous a.link:visited
|
||||
{
|
||||
color:blue !important;
|
||||
}
|
||||
|
||||
/* line numbers */
|
||||
.luminous .line-numbers{
|
||||
color:black !important;
|
||||
background-color:#e0e0e0 !important;
|
||||
border-right:1px solid black !important;
|
||||
}
|
||||
.luminous
|
||||
{
|
||||
color:black !important;
|
||||
border-color: #999;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.luminous .code.numbered > span:nth-child(2n)
|
||||
{
|
||||
background-color:#F3F3F3;
|
||||
}
|
||||
|
||||
.luminous .code .highlight
|
||||
{
|
||||
background-color:#DFDEF6;
|
||||
}
|
||||
.luminous .code.numbered .highlight:nth-child(2n)
|
||||
{
|
||||
background-color:#DFDEF6;
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Here we override some CSS to make a Luminous object more print-friendly.
|
||||
* as well as some layout, we override a few colours of the light theme.
|
||||
* This is because some colours do not print well (grey comments => green)
|
||||
* and boldness appears to be dropped from keywords, thereby removing all their
|
||||
* highlighting (these are changed to a purple colour)
|
||||
*/
|
||||
|
||||
/* body {padding:0px !important; margin:0px !important;} */
|
||||
div.luminous .metabar_buttons, div.luminous .metabar_fixed
|
||||
{
|
||||
display:none !important;
|
||||
visibility:hidden !important;
|
||||
}
|
||||
|
||||
div.luminous, .luminous .code, .luminous .line_numbers
|
||||
{
|
||||
height:auto !important;
|
||||
}
|
||||
.luminous pre.code, .luminous pre.line_numbers {
|
||||
overflow:visible !important;
|
||||
max-height:none !important;
|
||||
}
|
||||
|
||||
div.luminous .comment{color:green !important;}
|
||||
div.luminous .keyword {}
|
||||
div.luminous table.code_container{height:auto !important;}
|
||||
div.luminous div.code_container{max-height:none !important;
|
||||
overflow:visible !important;
|
||||
height:auto !important;
|
||||
}
|
||||
table.code_container {padding:0px !important;
|
||||
border-collapse:collapse;
|
||||
}
|
||||
td {padding: 0px !important;}
|
||||
td.lineno {border-right:1px solid black; }
|
||||
td.code { padding-left: 1em !important;}
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
/*
|
||||
* Based on the 'Birds of Paradise' theme
|
||||
* http://joebergantine.com/werkstatt/birds-of-paradise
|
||||
*/
|
||||
|
||||
|
||||
.luminous { border-color: #666; }
|
||||
|
||||
.luminous .character{color:#DCA3A3;}
|
||||
.luminous .comment{color:#8F6843; font-style:italic;}
|
||||
.luminous .comment_note{color:#D24421;
|
||||
font-style:normal; font-weight:bold;}
|
||||
.luminous .constant{color:#EFAC32; font-weight:bold;}
|
||||
.luminous .delimiter{ font-weight:bold;}
|
||||
.luminous .esc{color:#FFFF00 ;}
|
||||
.luminous .function{color:#EFAC32;}
|
||||
.luminous .heredoc{color:#D9D762;}
|
||||
.luminous .htmltag{font-weight:bold; color:#EFCB43;}
|
||||
.luminous .keyword{font-weight:bold; color:#EF5D32; }
|
||||
.luminous .numeric {color:#6C99BB;}
|
||||
.luminous .operator{color:#F68895;}
|
||||
.luminous .obj{color:#8E83BD;}
|
||||
.luminous .oo{}
|
||||
.luminous .preprocessor{color:#FF9D5B;}
|
||||
.luminous .shebang{font-weight:bold; font-style:normal;
|
||||
color:#FFFFFF;}
|
||||
.luminous .string{color:#D9D762;}
|
||||
.luminous .type{color:#EFAC32; }
|
||||
.luminous .user_function{color: #FFE432; font-weight:bold;}
|
||||
.luminous .value{color:#FF9074;}
|
||||
.luminous .variable{color:#7DAF9C;}
|
||||
|
||||
/* italicised because otherwise it seems to blend into the rest of the
|
||||
* source too much */
|
||||
.luminous .doccomment{color:#D2D2D2; font-style:italic;}
|
||||
.luminous .doctag {color:#C6D25A;}
|
||||
.luminous .docstr {color:#FF9B9B;}
|
||||
.luminous .docproperty{color:#D2B777; font-weight:bold;}
|
||||
|
||||
.luminous .diff_header_new{background-color:#2F33AB;}
|
||||
.luminous .diff_header_old{background-color:#2F33AB;}
|
||||
.luminous .diff_range{background-color:#2F33AB;}
|
||||
|
||||
|
||||
|
||||
/* .luminous .lang_latex{color:#b1b1ff;} */
|
||||
.luminous .latex_function{color:#FFDCA8;}
|
||||
.luminous .latex_operator{color:#888888;}
|
||||
|
||||
.luminous .code {}
|
||||
|
||||
.luminous .long_delim{font-weight:bold;}
|
||||
|
||||
|
||||
.luminous .generics{color:#adff5a;}
|
||||
|
||||
|
||||
|
||||
.luminous .regex{color:#A19BE9;}
|
||||
.luminous .regex_subpattern{font-weight:bold;
|
||||
color:#B383ED;}
|
||||
.luminous .regex_class_marker{color:#7CB7E1; font-weight:bold;}
|
||||
.luminous .regex_subpattern_marker{color:#D684EE;
|
||||
font-weight:bold;}
|
||||
.luminous .regex_repeat_marker{color:#b1b1ff;}
|
||||
.luminous .regex_operator{color:#8FC08F;}
|
||||
|
||||
.luminous .make_target{color:#FFD5FF;}
|
||||
.luminous .make_dep{color: #b1b1ff;}
|
||||
|
||||
.luminous .whitespace_space{background-color:#C877A5;}
|
||||
.luminous .whitespace_tab{background-color:#7D85D1;}
|
||||
|
||||
.luminous .link, .luminous .link:visited
|
||||
{
|
||||
color:#FFC0FF;
|
||||
}
|
||||
.luminous .link:hover
|
||||
{
|
||||
color:#FFC0FF;
|
||||
}
|
||||
|
||||
/* line numbers */
|
||||
.luminous .line-numbers {
|
||||
background-color:#3E2C29;
|
||||
border-right:1px solid #F5AEA3;
|
||||
color: #CA7A2A;
|
||||
}
|
||||
|
||||
|
||||
.luminous
|
||||
{
|
||||
background-color:#322323;
|
||||
color:#E6E1C4;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.luminous .code.numbered > span:nth-child(2n)
|
||||
{
|
||||
background-color: #3E2C29;
|
||||
}
|
||||
|
||||
.luminous .code .highlight
|
||||
{
|
||||
background-color:#1F1611;
|
||||
}
|
||||
|
||||
.luminous .code.numbered .highlight:nth-child(2n)
|
||||
{
|
||||
background-color: #1F1611;
|
||||
}
|
||||
|
||||
/* this stuff has to come after the other rules because it will probably
|
||||
* override some of them
|
||||
*/
|
||||
.luminous .diff_old{
|
||||
background-color:#660000;
|
||||
background-color: rgba(232, 87, 82, 0.35);
|
||||
color: #E6E1DC;
|
||||
}
|
||||
.luminous .diff_new{
|
||||
background-color:#144212;
|
||||
background-color: rgba(0, 191, 0, 0.35);
|
||||
color: #E6E1DC;
|
||||
}
|
||||
.luminous .diff_unchanged, .luminous .diff_unchanged * {
|
||||
color: #888A85;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
|
||||
.luminous .character{color:#FF69B4 !important;}
|
||||
|
||||
.luminous .comment{color:#CC9999 !important; font-style:italic !important;}
|
||||
|
||||
/* NOTE: TODO: etc. */
|
||||
.luminous .comment_note{
|
||||
background-color:#FFB2B0 !important;
|
||||
background-color:rgba(255, 178, 176, 0.70) !important;
|
||||
color:black !important;
|
||||
font-style:normal !important;}
|
||||
.luminous .constant{color:#0073AD !important; font-weight:bold !important;}
|
||||
.luminous .delimiter{ font-weight:bold !important;}
|
||||
.luminous .esc{color:#057CA3 !important;}
|
||||
.luminous .function{color:#CC3399 !important;}
|
||||
|
||||
.luminous .htmltag{font-weight:bold !important; color:#006633 !important;}
|
||||
.luminous .keyword{font-weight:bold !important; color:#6666CC !important;}
|
||||
.luminous .numeric {color:#0099FF !important;}
|
||||
.luminous .operator{color:green !important;}
|
||||
|
||||
.luminous .oo{color:#339900 !important;}
|
||||
.luminous .obj{color:#3366FF !important;}
|
||||
.luminous .preprocessor{color:#9999CC !important;}
|
||||
.luminous .shebang{font-weight:bold !important; font-style:normal !important; color:purple !important;}
|
||||
.luminous .string, .luminous .heredoc{color:#339966 !important;
|
||||
/* background-color:#FFF8F8 !important;
|
||||
background-color:rgba(255, 157, 157, 0.20) !important;*/
|
||||
|
||||
}
|
||||
.luminous .type{color:#0057AE !important;}
|
||||
/* not used*/
|
||||
.luminous .user_function{color: #0083E1 !important; font-weight:bold !important;}
|
||||
.luminous .value{color:green !important;}
|
||||
.luminous .variable{color:#4545A9 !important;}
|
||||
|
||||
.luminous .doccomment{color:#9999CC !important;}
|
||||
.luminous .doctag {color:#CA60CA !important;}
|
||||
.luminous .docstr {color:#339966 !important;}
|
||||
.luminous .docproperty{color:#0095FF !important; font-weight:bold !important;}
|
||||
|
||||
.luminous .diff_header_new{color:green !important;}
|
||||
.luminous .diff_header_old{color:red !important;}
|
||||
.luminous .diff_range{color:blue !important;}
|
||||
|
||||
|
||||
.luminous .lang_latex{color:blue !important;}
|
||||
.luminous .latex_function{color:red !important; font-weight:normal !important;}
|
||||
.luminous .latex_operator{color:black !important;}
|
||||
|
||||
.luminous .make_target{color:#CC00FF !important;}
|
||||
.luminous .make_dep{color: blue !important;}
|
||||
|
||||
.luminous .regex{color:#8000FF !important;
|
||||
background-color:#F9F3FF !important;
|
||||
background-color:rgba(231, 206, 255, 0.20) !important;
|
||||
}
|
||||
.luminous .regex_subpattern{font-weight:bold !important; color:black !important;}
|
||||
.luminous .regex_class_marker{color:#0083E1 !important; font-weight:bold !important;}
|
||||
.luminous .regex_subpattern_marker{color:green !important; font-weight:bold !important;}
|
||||
.luminous .regex_repeat_marker {color:blue !important;}
|
||||
.luminous .regex_operator{color:green !important;}
|
||||
|
||||
/* Specific to the whitespace language */
|
||||
.luminous .whitespace_space{background-color:#FF5151 !important;}
|
||||
.luminous .whitespace_tab{background-color:#A1B6FF !important;}
|
||||
|
||||
|
||||
/* line numbers */
|
||||
.luminous .line-numbers{
|
||||
background-color:#F3EEFF !important;
|
||||
border-right:1px solid #BED6E1 !important;
|
||||
color: #000066 !important;
|
||||
}
|
||||
.luminous .code
|
||||
{
|
||||
background-color: #F3EEFF !important;
|
||||
color: #000066 !important;
|
||||
}
|
||||
|
||||
.luminous a.link, .luminous a.link:visited
|
||||
{
|
||||
color:blue !important;
|
||||
}
|
||||
|
||||
|
||||
.luminous
|
||||
{
|
||||
background-color: #fff;
|
||||
color:black !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.luminous .code.numbered > span:nth-child(2n)
|
||||
{
|
||||
background-color:#FAF8FF;
|
||||
}
|
||||
|
||||
.luminous .code .highlight
|
||||
{
|
||||
background-color:#BED6E1;
|
||||
}
|
||||
.luminous .code.numbered .highlight:nth-child(2n)
|
||||
{
|
||||
background-color:#BED6E1;
|
||||
}
|
||||
|
||||
/* this stuff has to come after the other rules because it will probably
|
||||
* override some of them
|
||||
*/
|
||||
.luminous .diff_old{
|
||||
background-color:#E2AEC1 !important;
|
||||
background-color: rgba(226, 174, 193, 0.65) !important;
|
||||
color: #666 !important;
|
||||
}
|
||||
.luminous .diff_new{
|
||||
background-color:#B7E2C6 !important;
|
||||
background-color: rgba(156, 226, 181, 0.65) !important;
|
||||
color: #666 !important;
|
||||
}
|
||||
.luminous .diff_unchanged, .luminous .diff_unchanged * {
|
||||
color: #888A85 !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
/*
|
||||
* Copyright 2010 Mark Watkinson
|
||||
*
|
||||
* This file is part of Luminous.
|
||||
*
|
||||
* Luminous 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Luminous 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 Luminous. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Based on the Zenburn theme.
|
||||
* Colours largely taken from:
|
||||
https://spreadsheets.google.com/ccc?key=pKLGtBDTfcpZoRtJFr_eeAg&hl=en#gid=0
|
||||
*/
|
||||
.luminous { border-color: #555; }
|
||||
.luminous .character{color:#DCA3A3 !important;}
|
||||
.luminous .comment{color:#7F9F7F !important;}
|
||||
.luminous .comment_note{color:#DFDFDF !important;
|
||||
font-style:normal !important; font-weight:bold !important;}
|
||||
.luminous .constant{color:#DCA3A3; font-weight:bold !important;}
|
||||
.luminous .delimiter{ font-weight:bold !important;}
|
||||
.luminous .esc{color:#478ca3 !important;}
|
||||
.luminous .function{color:#efef8f !important;}
|
||||
.luminous .heredoc{color:#cc9393 !important;}
|
||||
.luminous .htmltag{font-weight:bold !important; color:#e89393 !important;}
|
||||
.luminous .keyword{font-weight:bold !important; color:#f0dfaf !important; }
|
||||
.luminous .numeric {color:#8cd0d3 !important;}
|
||||
.luminous .operator{color:#888888 !important;}
|
||||
.luminous .obj{color:#dfdfbf !important;}
|
||||
.luminous .oo{}
|
||||
.luminous .preprocessor{color:#ffcfaf !important;}
|
||||
.luminous .shebang{font-weight:bold !important; font-style:normal !important;
|
||||
color:#c0ffc0 !important;}
|
||||
.luminous .string{color:#cc9393;}
|
||||
.luminous .type{color:#dfdfbf !important; }
|
||||
.luminous .user_function{color: #BAAD88 !important; font-weight:bold !important;}
|
||||
.luminous .value{color:#C0FFFF !important;}
|
||||
.luminous .variable{color:#f0dfaf !important;}
|
||||
|
||||
.luminous .doccomment{color:#82a282 !important;}
|
||||
.luminous .doctag {color:#d7afaf !important;}
|
||||
.luminous .docstr {color:#FF9B9B !important;}
|
||||
.luminous .docproperty{color:#FFFF87 !important; font-weight:bold !important;}
|
||||
|
||||
.luminous .diff_header_new{color:#D7D7AF !important;}
|
||||
.luminous .diff_header_old{color:#D7D7AF !important;}
|
||||
.luminous .diff_range{color:#D7D7AF !important; }
|
||||
.luminous .diff_old{color:#D7AFAF !important;}
|
||||
.luminous .diff_new{color:#FFD7AF !important;}
|
||||
|
||||
|
||||
/* .luminous .lang_latex{color:#b1b1ff;} */
|
||||
.luminous .latex_function{color:#FFDCA8 !important;}
|
||||
.luminous .latex_operator{color:#888888 !important;}
|
||||
|
||||
.luminous .code {}
|
||||
|
||||
.luminous .long_delim{font-weight:bold !important;}
|
||||
|
||||
|
||||
.luminous .generics{color:#adff5a !important;}
|
||||
|
||||
|
||||
|
||||
.luminous .regex{color:#E6CDFF !important;}
|
||||
.luminous .regex_subpattern{font-weight:bold !important;
|
||||
color:#FF8D8D !important;}
|
||||
.luminous .regex_class_marker{color:#7CB7E1; font-weight:bold;}
|
||||
.luminous .regex_subpattern_marker{color:#8FC08F !important;
|
||||
font-weight:bold !important;}
|
||||
.luminous .regex_repeat_marker{color:#b1b1ff !important;}
|
||||
.luminous .regex_operator{color:#8FC08F !important;}
|
||||
|
||||
.luminous .make_target{color:#FFD5FF !important;}
|
||||
.luminous .make_dep{color: #b1b1ff !important;}
|
||||
|
||||
.luminous .whitespace_space{background-color:#ff5151 !important;}
|
||||
.luminous .whitespace_tab{background-color:#a1b6ff !important;}
|
||||
|
||||
.luminous .link, .luminous .link:visited
|
||||
{
|
||||
color:#C0FFC0 !important;
|
||||
}
|
||||
.luminous .link:hover
|
||||
{
|
||||
color:#FFC0FF !important;
|
||||
}
|
||||
|
||||
/* line numbers */
|
||||
.luminous .line-numbers {
|
||||
background-color:#444444 !important;
|
||||
border-right:1px solid #5F5F5F !important;
|
||||
color: #A8A8A8 !important;
|
||||
}
|
||||
|
||||
|
||||
.luminous {
|
||||
background-color:#3a3a3a !important;
|
||||
color:#DCDCCC !important;
|
||||
}
|
||||
|
||||
.luminous .code.numbered > span:nth-child(2n) {
|
||||
background-color: #404040;
|
||||
}
|
||||
|
||||
.luminous .code .highlight
|
||||
{
|
||||
background-color:#6D6D6D;
|
||||
}
|
||||
.luminous .code.numbered .highlight:nth-child(2n) {
|
||||
background-color: #6D6D6D ;
|
||||
}
|
||||
|
||||
/* this stuff has to come after the other rules because it will probably
|
||||
* override some of them
|
||||
*/
|
||||
.luminous .diff_old{
|
||||
background-color:#7C4543 !important;
|
||||
background-color: rgba(232, 87, 82, 0.15) !important;
|
||||
}
|
||||
.luminous .diff_new{
|
||||
background-color:#3F612C !important;
|
||||
background-color: rgba(128, 251, 120, 0.15) !important;
|
||||
}
|
||||
.luminous .diff_unchanged, .luminous .diff_unchanged * {
|
||||
color: #888A85 !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
<?php
|
||||
require_once('luminous.php');
|
||||
?><!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
td {
|
||||
border: 1px solid gray;
|
||||
padding: 0 1em;
|
||||
}
|
||||
th {
|
||||
border-bottom: 1px solid black;
|
||||
text-align:center;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table style='margin-left:auto; margin-right: auto;'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style='border: 0px'></th>
|
||||
<th>Language</th>
|
||||
<th>Valid Codes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$i = 0;
|
||||
foreach(luminous::scanners() as $l=>$codes) { ?>
|
||||
<tr>
|
||||
<td><?php echo ++$i; ?></td>
|
||||
<td><?php echo $l; ?></td>
|
||||
<td><?php echo join(', ', $codes); ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* quick script checks whether or not we're running the current release by
|
||||
* fetching the most recent release data from the site API and comparing it
|
||||
* to the version we're running here
|
||||
*/
|
||||
include (dirname(__FILE__) . '/luminous.php');
|
||||
|
||||
$URL = 'http://luminous.asgaard.co.uk/index.php/ajax/luminous/version';
|
||||
$DOWNLOAD_URL = 'http://luminous.asgaard.co.uk/index.php/download';
|
||||
$cmd_line = PHP_SAPI === 'cli';
|
||||
$version = LUMINOUS_VERSION;
|
||||
|
||||
function urlify($url) {
|
||||
global $cmd_line;
|
||||
return $cmd_line? $url : "<a href='$url'>$url</a>";
|
||||
}
|
||||
|
||||
function _echo($string) {
|
||||
echo wordwrap($string, 79) . "\n";
|
||||
}
|
||||
|
||||
if (!$cmd_line) _echo('<pre>');
|
||||
|
||||
if ($version === 'master') {
|
||||
_echo('You are using a development version, I cannot check how up to date it is.');
|
||||
_echo('You can download the latest stable release from '
|
||||
. urlify($DOWNLOAD_URL));
|
||||
}
|
||||
else {
|
||||
_echo('Checking version...');
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $URL);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Luminous ' . LUMINOUS_VERSION
|
||||
. ' version check');
|
||||
$json = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if (!$json) {
|
||||
_echo('Remote request failed. Try again later or visit '
|
||||
. urlify($DOWNLOAD_URL) . ' to see what the latest version is');
|
||||
} else {
|
||||
$data = json_decode($json, true);
|
||||
if ($data['release_number'] === $version || 'v' . $data['release_number'] === $version) {
|
||||
_echo('You are up to date!');
|
||||
} else {
|
||||
$output = "You are not up to date: your version is " . $version
|
||||
. " and the most recent release is " . $data['release_number']
|
||||
. ", released " . $data['release_date'] . '. '
|
||||
. ' Visit ' . urlify($DOWNLOAD_URL) . ' to upgrade';
|
||||
_echo($output);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$cmd_line) _echo('</pre>');
|
||||
Loading…
Add table
Add a link
Reference in a new issue