Compare commits

..

95 Commits

Author SHA1 Message Date
Matt Pass
f0d4ef75d3 Design improvements for readability of shortcuts 2012-05-10 20:43:52 +01:00
Matt Pass
ec27eb53bc Close button now has 30% white BG, transparent on file deselect 2012-05-10 20:42:49 +01:00
Matt Pass
6512d4895b Nav design improvements & fix to .file types
Nav highlighting & changed status indication now improved
Fixed problem when adding .files it sees it as a folder
2012-05-10 18:43:11 +01:00
Matt Pass
de81341452 Version number update only 2012-05-10 18:41:40 +01:00
Matt Pass
97e6906f17 2 x new filetypes added, some hidden code renamed ready for next lot 2012-05-10 18:41:03 +01:00
Matt Pass
feeb3907bf Nav tab close button now round 2012-05-10 18:40:26 +01:00
Matt Pass
955d7714a2 Design improvements to the nav tabs 2012-05-10 18:40:04 +01:00
Matt Pass
e506d5a535 Couple of new filetype icons 2012-05-10 18:39:40 +01:00
Matt Pass
09ff2f279d Plenty of adjustments to give a new darker styling
Felt the file manager on the left being white was a bit jarring on the eyes
A darker background would be more suitable for long periods
Also decided to overhaul icons and give everything a modern feel
Previously it looked a bit dated, now looks much fresher
2012-05-09 17:22:18 +01:00
Matt Pass
e17a240661 Links in FM now white to suit dark BG removed CSS for unused filetypes
Plus added a couple of more specific filetypes
Commented out a few as I'll add them v/soon (before next point release)
2012-05-09 17:18:28 +01:00
Matt Pass
a6e244a82f No longer considers .asp/.aspx in restrictedFiles, considers .rb instead 2012-05-09 17:16:35 +01:00
Matt Pass
491fb4c243 Adjustments to colours/styling of tabs, items in FM & new Help popup
Minor alts to suit different states of tabs
Also minor alts to select/deselect of files/folders in file manager to suit darker style
New function to show/hide help popup on demand
2012-05-09 17:15:06 +01:00
Matt Pass
ca46e36e5a Minor alts to graphics to fit new styling
Slight adjustments to contrast of graphics
2012-05-09 17:10:28 +01:00
Matt Pass
09e3ece5a7 Help popup by clicking logo
You can now access help popup by clicking ICEcoder logo
2012-05-09 17:09:20 +01:00
Matt Pass
57e820501a Help popup added
New help popup screen, accessed by clicking ICEcoder logo
Shows shortcut keys for now
2012-05-09 17:08:14 +01:00
Matt Pass
1577118643 New & updated file manager icons
Added a few more specific icons such as html, js, ruby etc
Now starting to look more modern
Udpdated some general icons such as directory & refresh too
2012-05-09 17:06:17 +01:00
Matt Pass
856a0c9f31 Removing old icons
Removed many icons from the file manager
This is because I won't be supporting these file types, they're general purpose, or look dated
Will look to add css, sql, doc, pdf, swf, xls and more in the future
2012-05-09 17:04:17 +01:00
Matt Pass
c621479709 Dealing with new files & lastOpenedFiles array
[NEW] or 'blank' files not allowed into lastOpenedFiles array
Only update settings file if we have something to save
Otherwise, clear server message and remove from server queue
2012-05-08 18:31:35 +01:00
Matt Pass
b7769e6203 Dealing with fileMDT for new files
Don't tack fileMDT onto query string if it's undefined (ie, new files)
New file saves then possible if we don't have a fileMDT on query string
2012-05-08 18:29:03 +01:00
Matt Pass
b1e27282a9 Clear server message as well as remove from server queue 2012-05-08 18:26:21 +01:00
Matt Pass
c19df45ec1 New openFilesMDT array, stop erroneously showing changed tab & minor fixes
openFilesMDTs array now stores modified datetimes for collab edits
Stop clearing value of editor instance to avoid change tab error
New code to work with openFilesMDTs array
Stop switching to another tab unless we're closing current
2012-05-08 07:56:13 +01:00
Matt Pass
0ca29f9201 Additional if check on file datetime for collab edits
Wrapped an additional if around the save operations
This is to check if we have latest file, allowing collab edits
(if we attempt save and don't have latest modified date time, alert user
Other minor updates to work with new MDT vars, params, arrays
clearstatcache necessary to get latest modified datetime
2012-05-08 07:51:31 +01:00
Matt Pass
e208b45a88 v0.6.61 dev, .sql now restricted filetype and settings BG colour change 2012-05-08 07:47:31 +01:00
Matt Pass
b8f7be6376 Default BG now dark grey 2012-05-08 07:42:44 +01:00
mattpass
5ae958e349 Merge pull request #50 from WimTibackx/master
Fixes error #49 by isset catching missing GET & POST key errors in a stricter environment. Merged.
2012-05-07 13:09:54 -07:00
Wim Tibackx
7237ef8c69 One more... 2012-05-07 21:56:00 +02:00
Wim Tibackx
215a4ab362 Fix my earlier settings screw-up... Sorry! 2012-05-07 21:52:54 +02:00
Wim Tibackx
8c83378b8b Fixing issue #49: Notices in settings.php (unknown POST/GET-keys). About fix for issue #49 (example: lib/settings.php line 46): If isset(post theme) gives false, post theme would've given that too. If it gives true, validation is still the same as before. 2012-05-07 21:20:58 +02:00
mattpass
9d14ca1eb2 Update README.md 2012-05-07 13:01:33 +02:00
mattpass
78067a8dec Update README.md 2012-05-07 12:51:49 +02:00
mattpass
d12ea02c42 Update README.md 2012-05-07 12:40:31 +02:00
mattpass
3ceb519b8a Update README.md 2012-05-07 12:23:47 +02:00
mattpass
5508cd1074 Update README.md 2012-05-07 12:19:34 +02:00
Matt Pass
d2bf52e5a3 CSS for new multiple results screen 2012-05-05 17:48:34 +01:00
Matt Pass
f39b8e2a35 New multiple results screen
Shows multiple find results & allows user to replace singally, or all
Also shows count of found results, updates text & button vis on interaction
2012-05-05 17:48:13 +01:00
Matt Pass
8c97be00dc Nest display & find/replace improvements
Loaded code no longer has & converted to & so code is not messed with
Nesting only displays if you don't have include, include_once (PHP), plus must have html or body tag (HTML)
Found count display now updates on switching tabs
findReplace updated to take 3rd param, detecting how it was triggered
Find is now case-sensitive by default
Code realigned in findReplace to work more specifically with 'this document'
Extra code also added to replace all
Display count now fixed to be accurate
Multiple results screen show shows when not finding within current document
Function to deal with updating and showing/hiding of results count display
2012-05-05 17:36:13 +01:00
Matt Pass
83085c4c1f Update to always return and provide error message
Alert message now displays if a zip could not be created
Will now always return, success or fail to stop server queue jams
2012-05-05 15:44:01 +01:00
Matt Pass
8adec9a48b 'replace'/'replace all' select menu & show/hide results display switching
New select menu in find & replace, allowing you to replace or replace all
Results count displays only if you select 'this document'
New param on findReplace function to indicate clicking button or not
2012-05-05 15:42:27 +01:00
Matt Pass
c177374d23 Extra param to signify we're not triggering from button click 2012-05-05 15:19:12 +01:00
Matt Pass
334ced8627 Version number update only 2012-05-05 15:17:07 +01:00
Matt Pass
d8229d79a5 New class for replace select menu 2012-05-05 15:16:12 +01:00
Matt Pass
c8665584e9 Minor fix to stop matching on whitespace chars only
Whitespace only chars are now trimmed and so not matched
This is a future update (in next version of CodeMirror) that I'm adding now
2012-05-05 15:14:57 +01:00
Matt Pass
c56af14f52 stickyTab, login, plugin & settings improvements/features
New vars for stickyTab and plugin interval refs
New login container, adjusts to width of file manager
Upon login, slide login box up to reveal icons
New vars to allow stickyTab on CTRL+S+Enter
Improvement so you don't end up with a locked nav thats collapsed
Fix so we only switchtab if we have associated CM instance
Also updates found results display on switching tab
SwitchMode only does this if there is a filename (tab name) available
Plugin timers now created under vars so they can be cleared
If there is a login attempt, slide login box up to reveal icons
New function to show settings screen on demand
New function to update theme, tabsIndent, lockedNav, visibleTabs & file manager
(This is so changed settings can be applied straight away)
File manager refresh only happens if it needs to, for efficiency
2012-05-01 08:18:46 +01:00
Matt Pass
ed8fb0dd67 Settings can now be updated and changes applied on the fly
Moved various items around in code
Identified settings area with start & end comment blocks
.sql files are now a banned file type
new vars for tabsIndent, codeAssist & lockedNav
When settings are changed from settings screen, this file updates itself
Also then applies settings and refreshes/reloads intelligently
Work out if we have an approved IP or not, if not boot to root
Apply plugins (display & setIntervals) on load or on change of this file
Also apply autoOpenFiles onload from index.php
Refresh file manager and show icons if we have a correct login
2012-05-01 08:07:21 +01:00
Matt Pass
f906b41cd2 CSS classes for new settings popup screen 2012-05-01 07:56:37 +01:00
Matt Pass
1491e24039 Settings screen show in popup on right click of logo
Right clicking the ICEcoder logo now shows this settings screen in a popup
This allows you to control all main settings for ICEcoder
Saving settings applies changes to settings.php
Also intelligently reloads & refreshes relevant items for efficiency
Thanked a few people in this screen, hope they don't mind
2012-05-01 07:55:53 +01:00
Matt Pass
30dbad53a7 Session IP, plugin, autoOpenFiles, settingsScreen, & login improvements
Checking of IP now done via session var, so it's updatable via settings
Plugin intervals, display of icons & autoOpenFiles moved to settings.php
(This is so these things can be updated upon settings change)
init function now takes param to determin if you are logged in or not
Logo now right clickable to show settings screen
Account login box now in own container so it can slide out of view on login
Other minor changes to fit in with new features
2012-05-01 07:44:40 +01:00
Matt Pass
b129bc39cb Save now works with stickyTabs, plus minor improvements
When you save, if there is a stickyTab window, it reloads
Popups for images now have white glow around them, plus fix to text color
Moved clearing the server message to cover images too
2012-05-01 07:35:00 +01:00
Matt Pass
5ffba58802 Classes for h1, h2, whiteGlow, accountLogin & container, blue glow & more
Many new classes, including a few adjustments
whiteGlow class to surround popups and a similar blue one for input boxes
Minor adjustments to others to fit new features
2012-05-01 07:31:19 +01:00
Matt Pass
3cd5b99edd Tabbing can now dynamically switch between tab & indent
tab:after now always available, has dynamic content (blank or tab symbol)
Tabbing can now dynamically switch and is either default or indents
(default tabs, but if you've something selected will indent selected lines)
2012-05-01 07:26:01 +01:00
Matt Pass
89b1b51097 Upgrade to CodeMirror 2.24 2012-05-01 07:15:56 +01:00
Matt Pass
6b5c95fc3a Remove CodeMirror 2.23 (upgrading to 2.24) 2012-05-01 07:14:15 +01:00
Matt Pass
8019f66a78 Default = icecoder fix
If you choose the default theme, we need to identify that as 'iceocder'
2012-04-20 08:01:13 +01:00
Matt Pass
b5e8afb8d9 Fix to match new function variable name 2012-04-20 08:00:29 +01:00
Matt Pass
e2b585027b Various CSS styles back in theme
cursor, selected, gutter & matching bracket styles back in default theme
These styles pertain to this theme only and to avoid conflicts with another themne are back in
2012-04-20 07:47:04 +01:00
Matt Pass
56ade7fa75 Some CSS moved back into default theme & visibleTabs option back in
selected, gutter, cursor & matching bracket moved back into default theme
(As it pertains to that theme only)
$visibleTabs option back in
2012-04-20 07:45:58 +01:00
Matt Pass
efbef411f9 Theme setting, open last files if logged in plus fragmenting file menu
User selected 'Theme' variable set here and used later
Last opened files only loaded on start if you are logged in
Rename & View Webpage now within their own wrapper
(This allows us to only show if we have 1 file selected, done via JS)
2012-04-19 17:50:33 +01:00
Matt Pass
6ef524e4ce Themes applied to editor & styling made more general
Some of the general styling moved from default theme to here
(margin on HTML & body, plus selected, gutter, cursor & matching styles)
Removed setting of theme here, done dynamically with existing functions
2012-04-19 17:47:49 +01:00
Matt Pass
dff7573531 Theme can now be chosen, right click menu now dynamic & reload FM
Updates to allow usage of theme as chosen by user
Menu that displays when user click is now more dynamic
(Shows options based on number of files selected)
Function to reload File Manager on demand plus show loading screen
2012-04-19 17:43:41 +01:00
Matt Pass
881b8f014b Adjustment to onContextMenu & FM reloader
Removed selecting of files/folders func when right clicking
Added refresh icon to reload file manager on click
2012-04-19 17:40:19 +01:00
Matt Pass
d273c82b86 Removed clipboard plugin, theme setting & fix to stop UI jamming
Infinite Clipboard plugin removed as no longer developing this idea
Theme setting now available to choose the default or a CM based theme
UI now doesn't jam when opening/closing files if you're not logged in
2012-04-19 17:39:05 +01:00
Matt Pass
6e5ab719a4 Simplified default CSS file
HTML & body styling now spplied to tags
selected, gutter, cursor and matching elements now applied in editor.php
This all allows CodeMirror themes to be used if users want to switch from default
2012-04-19 17:34:28 +01:00
Matt Pass
b416dd79f5 CSS class for refresh icon 2012-04-19 17:29:46 +01:00
Matt Pass
1e4237a483 Refresh icon added to File Manager
Users can now reload file manager by clicking icon
2012-04-19 17:29:00 +01:00
Matt Pass
a90a53458d Clipboard plugin icon removed
Icon removed as no longer including an Infinite Clipboard plugin
2012-04-19 17:28:22 +01:00
Matt Pass
54fa471d26 CodeMirror themes dir added
CodeMirror themes can now be used by ICEcoder
All themes folder included so users can choose if they wish
2012-04-19 17:27:48 +01:00
Matt Pass
be20e8f302 Updates to the fold code function to standardise folding
Orig pull request approved by Marijn and merged into CodeMirror repo
(Not this one, but my previous fix)
2012-04-19 17:25:56 +01:00
Matt Pass
222f651d68 Minor fix to start session from beginnig of file
Was causing problems when opening a file, not able to set as session not started
2012-04-14 18:26:44 +01:00
Matt Pass
b70ee4553a Ruby language support & visible tabs
CodeMirror mode now loaded for Ruby code highlighting
CSS for visible tabs if setting turned on
2012-04-14 18:10:00 +01:00
Matt Pass
493037a01b Ruby language support & auto loading of last opened files
Ruby now supported as a language in .rb files or within % blocks
List of last opened files updates on opening, closing and renaming tabs
Comment toggle function now handles Ruby commenting via # hashes
(Decided not to go for =begin and =end as this requires extra lines)
New function to handle opening of previously opened files
A few global vars that have been added recently now closed
2012-04-14 18:08:03 +01:00
Matt Pass
8233763511 Extra code to allow for auto opening of files
On opening and files being auto loaded, we need to establish the shortURL
This is so tabs can have the correct name on auto loading files
2012-04-14 17:54:52 +01:00
Matt Pass
2c01eeba17 Visible tabs and auto opening last opened files
Option to show tabs as arrows or blanks
Option to open last opened files on next session or not
Accompanying coding to update list of last opened files on demand
Version no update to v0.6.3
2012-04-14 17:53:11 +01:00
Matt Pass
82fd2a5b5d Handling of unsaved changes & loading of previous files
Closing or reloading the window now checks for unsaved files and alerts user
Filenames opened in previous session loaded into array on start
If we have the setting on to open these files, they are opened sequentially on load
2012-04-14 17:44:02 +01:00
Matt Pass
e297fd049f Ruby code highlighting mode added
Mode added from CodeMirror modes lib to handle highlighting of Ruby coding
2012-04-14 17:36:44 +01:00
Matt Pass
ef9d8ed5de Nest hover/click function, better code folding plus error catching
You can now hover mouse over nest positions to have them selected
Can also click to set cursor position to within that nest
Removed old code folding function in favour of lib that comes with CodeMirror
Errors catched so clicking on a blank area of the file manager doesn't attempt anything
2012-04-07 21:17:33 +01:00
Matt Pass
07e44ecfb5 Overwrite permission prompt plus better display & error catching
Now asks for overwrite permission if saving new file or save as over another file
Server message now shows your new filename when saving
Error catching so if not saving it clears server message
2012-04-07 21:14:24 +01:00
Matt Pass
fee53144d9 Code folding upon gutter click
New fileName var
CodeMirror lib used to allow folding of code on clicking gutter
HTML folds on <tags> and JS & PHP fold on {braces}
+ in gutter indicates folded area
2012-04-07 21:11:45 +01:00
Matt Pass
e899c2f1bd Version no. update to v0.6.2 2012-04-07 20:27:40 +01:00
Matt Pass
579dc7d5d0 Version no update to v0.6.1 2012-04-05 07:58:09 +01:00
Matt Pass
bdb7433c4a Minor CSS adjustment to show pointer mouse cursor on file names 2012-04-05 07:54:28 +01:00
Matt Pass
2a2a631c99 Minor CSS adjustment to show default mouse cursor on gutter text 2012-04-05 07:53:56 +01:00
Matt Pass
a28213983b Hitting escape key outside of content area now cancels all actions
This stops parent from loading, hides the loading mask and clears server queue tasks other than one that is processing
Also displays message to inform you it's cancelled tasks
Function added to mediate file manager icon clicks to relevant functions
Icon visibility changes depending on actions you are taking and what is available to you right now
Simple function to handle icon visibility added
Code folding function added to allow collapsing and expanding of code blocks
(Its a bit slow & basic right now and only works for HTML, but improvements to come)
2012-04-05 07:52:57 +01:00
Matt Pass
0bcbc1a222 Account Options CSS added
New classes added to cover file manager icons
Also small adjustment to plugin icons position to line up with them
2012-04-05 07:46:48 +01:00
Matt Pass
978e2145e6 File Manager Icon Options Added
When you are logged in, in place of the login box there are now icons
These icons relate to tasks you can perform using key combos
Functions already established for these, though on click calls mediating function
Icons are mostly hidden by default, and light up/hide depending on functions available to you
2012-04-05 07:45:38 +01:00
Matt Pass
e4e75ccbef New file manager icons
Icons added to allow users option to click rather than press keys
Also means ICE coder now works with tablets as well as via mouse devices
These icons only show when you are logged in
2012-04-05 07:42:32 +01:00
Matt Pass
4a804e71df Interaction improvements via CSS and alternate functions
Pointing mouse over file manager icons now shows a CSS pointer cursor
On click of the HTML tag, selectFileFolder function is called, rather than just hide context menu
Calling this from HTML rather than body tag now
This in turn means the whole line for a file isn't clickable, just the name
2012-04-05 07:40:58 +01:00
Matt Pass
c758a2ff37 Gutter click now triggers code folding
Clicking gutter in CM editor triggers new code fold/expand function
2012-04-05 07:34:14 +01:00
Matt Pass
77aaa16be4 Extra nestTagException for ?php (not that it makes difference)
Removed ICEcoder.tD var as it was hardly used and theress no char saving really
Switched a few areas to ternary if statements
Code improvements, structure tidy up & improved commenting
Removed unnecessary code, stopped a few global vars
Also considering ?php as well as ?
Breaking tagEnd var on new lines to avoid nesting false errors
CTRL+I searches for highlighted word on Google in a context aware way
(ie, highlight 'echo' in a PHP block and it will search for 'PHP echo',
highlighting 'echo' in content area will search for just 'echo')
New function to select/deselect file/folder by changing CSS class
Only show New File and New Folder context menu options if we right clicked a folder
Simplified getcMInstance function
Improved commenting function to allow partial line commenting
Fixed issue with clicking plugin icons and server queue deletion on return
Fixed issue with CSS color blocks so they only show if they have a BG color
2012-04-01 12:43:18 +01:00
Matt Pass
215229d051 Fix & improvements to end tag postfixing, tab key & removing old code
Code assist now won't add an end tag if yours starts with a / (ie, it's already an end tag)
Also won't add an end tag if yours starts with ? (ie, it's ending a PHP block: ?>)
Switched from using the htmlTagArray to determin an end tag, to the tagString var
CodeMirror 2.23 handles tabs in a different way, so extraKeys has been set up to handle differently to new default
Old code removed related to showing results on clicking (now handled onChange as that's more efficient)
2012-04-01 12:18:04 +01:00
Matt Pass
dbf7e4e834 Span wrapper for dynamic context menu and fix to plugin icons clickability
New file and new folder options now inside span wrapper so it can be shown or not
(This is because these options are only suitable for folders and not files)
Fix to plugins that run through fileControl iFrame to make icon clickable again
2012-04-01 12:10:54 +01:00
Matt Pass
cafd79b03d Version & CodeMirror Update
Update ICEcoder to v0.6.0 and CodeMirror to v2.23
2012-04-01 12:07:17 +01:00
Matt Pass
0b1073fdbe Display server message
Now shows server message when loaded, to also cover clicking plugin icon
2012-04-01 12:05:21 +01:00
Matt Pass
d23171b8f1 Updated CodeMirror to v2.23 2012-04-01 12:04:00 +01:00
Matt Pass
64b026ca6e Removed CodeMirror v2.22
Update to v2.23
2012-04-01 12:01:03 +01:00
Matt Pass
422b013330 Minor bug fix to better detect file saving capabilities
Now tests if a file exists and is writable or is new before saving
Avoids false error problem
2012-03-26 07:54:11 +01:00
101 changed files with 3090 additions and 1392 deletions

View File

@@ -1,368 +0,0 @@
<!doctype html>
<html>
<head>
<title>CodeMirror</title>
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans:bold"/>
<link rel="stylesheet" type="text/css" href="doc/docs.css"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="alternate" href="http://twitter.com/statuses/user_timeline/242283288.rss" type="application/rss+xml"/>
</head>
<body>
<h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMirror</a></h1>
<pre class="grey">
<img src="doc/baboon.png" class="logo" alt="logo"/>/* In-browser code editing
made bearable */
</pre>
<div class="clear"><div class="left blk">
<p style="margin-top: 0">CodeMirror is a JavaScript library that can
be used to create a relatively pleasant editor interface for
code-like content &#x2015; computer programs, HTML markup, and
similar. If a mode has been written for the language you are
editing, the code will be coloured, and the editor will optionally
help you with indentation.</p>
<p>This is the project page for CodeMirror 2, the currently more
actively developed, and recommended
version. <a href="1/index.html">CodeMirror 1</a> is still available
from here.</p>
<div class="clear"><div class="left1 blk">
<h2 style="margin-top: 0">Supported modes:</h2>
<ul>
<li><a href="mode/clike/index.html">C, C++, Java, and similar</a></li>
<li><a href="mode/clojure/index.html">Clojure</a></li>
<li><a href="mode/coffeescript/index.html">CoffeeScript</a></li>
<li><a href="mode/css/index.html">CSS</a></li>
<li><a href="mode/diff/index.html">diff</a></li>
<li><a href="mode/ecl/index.html">ECL</a></li>
<li><a href="mode/go/index.html">Go</a></li>
<li><a href="mode/groovy/index.html">Groovy</a></li>
<li><a href="mode/haskell/index.html">Haskell</a></li>
<li><a href="mode/htmlembedded/index.html">HTML embedded scripts</a></li>
<li><a href="mode/htmlmixed/index.html">HTML mixed-mode</a></li>
<li><a href="mode/javascript/index.html">JavaScript</a></li>
<li><a href="mode/jinja2/index.html">Jinja2</a></li>
<li><a href="mode/less/index.html">LESS</a></li>
<li><a href="mode/lua/index.html">Lua</a></li>
<li><a href="mode/markdown/index.html">Markdown</a> (<a href="mode/gfm/index.html">Github-flavour</a>)</li>
<li><a href="mode/mysql/index.html">MySQL</a></li>
<li><a href="mode/ntriples/index.html">NTriples</a></li>
<li><a href="mode/pascal/index.html">Pascal</a></li>
<li><a href="mode/perl/index.html">Perl</a></li>
<li><a href="mode/php/index.html">PHP</a></li>
<li><a href="mode/plsql/index.html">PL/SQL</a></li>
<li><a href="mode/properties/index.html">Properties files</a></li>
<li><a href="mode/python/index.html">Python</a></li>
<li><a href="mode/r/index.html">R</a></li>
<li>RPM <a href="mode/rpm/spec/index.html">spec</a> and <a href="mode/rpm/changes/index.html">changelog</a></li>
<li><a href="mode/rst/index.html">reStructuredText</a></li>
<li><a href="mode/ruby/index.html">Ruby</a></li>
<li><a href="mode/rust/index.html">Rust</a></li>
<li><a href="mode/scheme/index.html">Scheme</a></li>
<li><a href="mode/smalltalk/index.html">Smalltalk</a></li>
<li><a href="mode/sparql/index.html">SPARQL</a></li>
<li><a href="mode/stex/index.html">sTeX, LaTeX</a></li>
<li><a href="mode/tiddlywiki/index.html">Tiddlywiki</a></li>
<li><a href="mode/velocity/index.html">Velocity</a></li>
<li><a href="mode/verilog/index.html">Verilog</a></li>
<li><a href="mode/xml/index.html">XML/HTML</a> (<a href="mode/xmlpure/index.html">alternative XML</a>)</li>
<li><a href="mode/yaml/index.html">YAML</a></li>
</ul>
</div><div class="left2 blk">
<h2 style="margin-top: 0">Usage demos:</h2>
<ul>
<li><a href="demo/complete.html">Autocompletion</a></li>
<li><a href="demo/mustache.html">Mode overlays</a></li>
<li><a href="demo/search.html">Search/replace</a></li>
<li><a href="demo/folding.html">Code folding</a></li>
<li><a href="demo/preview.html">HTML editor with preview</a></li>
<li><a href="demo/resize.html">Auto-resizing editor</a></li>
<li><a href="demo/marker.html">Setting breakpoints</a></li>
<li><a href="demo/activeline.html">Highlighting the current line</a></li>
<li><a href="demo/matchhighlighter.html">Highlighting selection matches</a></li>
<li><a href="demo/theme.html">Theming</a></li>
<li><a href="demo/runmode.html">Stand-alone highlighting</a></li>
<li><a href="demo/fullscreen.html">Full-screen editing</a></li>
<li><a href="demo/changemode.html">Mode auto-changing</a></li>
<li><a href="demo/visibletabs.html">Visible tabs</a></li>
<li><a href="demo/formatting.html">Autoformatting of code</a></li>
<li><a href="demo/emacs.html">Emacs keybindings</a></li>
<li><a href="demo/vim.html">Vim keybindings</a></li>
</ul>
<h2>Real-world uses:</h2>
<ul>
<li><a href="http://jsbin.com">jsbin.com</a> (JS playground)</li>
<li><a href="http://buzzard.ups.edu/">Sage demo</a> (math system)</li>
<li><a href="http://www.sourcelair.com/">sourceLair</a> (online IDE)</li>
<li><a href="http://eloquentjavascript.net/chapter1.html">Eloquent JavaScript</a> (book)</a></li>
<li><a href="http://www.mergely.com/">Mergely</a> (interactive diffing)</li>
<li><a href="http://paperjs.org/">Paper.js</a> (graphics scripting)</li>
<li><a href="http://www.wescheme.org/">WeScheme</a> (learning tool)</li>
<li><a href="http://webglplayground.net/">WebGL playground</a></li>
<li><a href="http://ql.io/">ql.io</a> (http API query helper)</li>
<li><a href="http://elm-lang.org/Examples.elm">Elm language examples</a></li>
<li><a href="http://bluegriffon.org/">BlueGriffon</a> (HTML editor)</li>
<li><a href="http://www.jshint.com/">JSHint</a> (JS linter)</li>
<li><a href="http://kl1p.com/cmtest/1">kl1p</a> (paste service)</li>
</ul>
</div></div>
<h2 id="code">Getting the code</h2>
<p>All of CodeMirror is released under a <a
href="LICENSE">MIT-style</a> license. To get it, you can download
the <a href="http://codemirror.net/codemirror.zip">latest
release</a> or the current <a
href="http://codemirror.net/codemirror2-latest.zip">development
snapshot</a> as zip files. To create a custom minified script file,
you can use the <a href="doc/compress.html">compression API</a>.</p>
<p>We use <a href="http://git-scm.com/">git</a> for version control.
The main repository can be fetched in this way:</p>
<pre class="code">git clone http://marijnhaverbeke.nl/git/codemirror2</pre>
<p>CodeMirror can also be found on GitHub at <a
href="http://github.com/marijnh/CodeMirror2">marijnh/CodeMirror2</a>.
If you plan to hack on the code and contribute patches, the best way
to do it is to create a GitHub fork, and send pull requests.</p>
<h2 id="documention">Documentation</h2>
<p>The <a href="doc/manual.html">manual</a> is your first stop for
learning how to use this library. It starts with a quick explanation
of how to use the editor, and then describes the API in detail.</p>
<p>For those who want to learn more about the code, there is
an <a href="doc/internals.html">overview of the internals</a> available.
The <a href="http://github.com/marijnh/CodeMirror2">source code</a>
itself is, for the most part, also well commented.</p>
<h2 id="support">Support and bug reports</h2>
<p>There is
a <a href="http://groups.google.com/group/codemirror">Google
group</a> (a sort of mailing list/newsgroup thing) for discussion
and news related to CodeMirror. When reporting a bug,
<a href="doc/reporting.html">read this first</a>. If you have
a <a href="http://github.com">github</a> account,
simply <a href="http://github.com/marijnh/CodeMirror2/issues">open
an issue there</a>. Otherwise, post something to
the <a href="http://groups.google.com/group/codemirror">group</a>,
or e-mail me directly: <a href="mailto:marijnh@gmail.com">Marijn
Haverbeke</a>.</p>
<h2 id="supported">Supported browsers</h2>
<p>The following browsers are able to run CodeMirror:</p>
<ul>
<li>Firefox 2 or higher</li>
<li>Chrome, any version</li>
<li>Safari 3 or higher</li>
<li>Internet Explorer 6 or higher in standards (<strong>non-quirks</strong>) mode</li>
<li>Opera 9 or higher (with some key-handling problems on OS X)</li>
</ul>
<p>I am not actively testing against every new browser release, and
vendors have a habit of introducing bugs all the time, so I am
relying on the community to tell me when something breaks.
See <a href="#support">here</a> for information on how to contact
me.</p>
<h2 id="commercial">Commercial support</h2>
<p>CodeMirror is developed and maintained by me, Marijn Haverbeke,
in my own time. If your company is getting value out of CodeMirror,
please consider purchasing a support contract.</p>
<ul>
<li>You'll be funding further work on CodeMirror.</li>
<li>You ensure that you get a quick response when you have a
problem, even when I am otherwise busy.</li>
</ul>
<p>CodeMirror support contracts exist in two
forms—<strong>basic</strong> at €100 per month,
and <strong>premium</strong> at €500 per
month. <a href="mailto:marijnh@gmail.com">Contact me</a> for further
information.</p>
</div>
<div class="right blk">
<a href="http://codemirror.net/codemirror.zip" class="download">Download the latest release</a>
<h2>Support CodeMirror</h2>
<ul>
<li>Donate
(<span onclick="document.getElementById('paypal').submit();"
class="quasilink">Paypal</span>
or <span onclick="document.getElementById('bankinfo').style.display = 'block';"
class="quasilink">bank</span>)</li>
<li>Purchase <a href="#commercial">commercial support</a></li>
</ul>
<p id="bankinfo" style="display: none;">
Bank: <i>Rabobank</i><br/>
Country: <i>Netherlands</i><br/>
SWIFT: <i>RABONL2U</i><br/>
Account: <i>147850770</i><br/>
Name: <i>Marijn Haverbeke</i><br/>
IBAN: <i>NL26 RABO 0147 8507 70</i>
</p>
<h2>Releases:</h2>
<p class="rel">27-02-2012: <a href="http://codemirror.net/codemirror-2.22.zip">Version 2.22</a>:</p>
<ul class="rel-note">
<li>Allow <a href="doc/manual.html#keymaps">key handlers</a> to pass up events, allow binding characters.</li>
<li>Add <a href="doc/manual.html#option_autoClearEmptyLines"><code>autoClearEmptyLines</code></a> option.</li>
<li>Properly use tab stops when rendering tabs.</li>
<li>Make PHP mode more robust.</li>
<li>Support indentation blocks in <a href="doc/manual.html#util_foldcode">code folder</a>.</li>
<li>Add a script for <a href="doc/manual.html#util_match-highlighter">highlighting instances of the selection</a>.</li>
<li>New <a href="mode/properties/index.html">.properties</a> mode.</li>
<li>Fix many bugs.</li>
</ul>
<p class="rel">27-01-2012: <a href="http://codemirror.net/codemirror-2.21.zip">Version 2.21</a>:</p>
<ul class="rel-note">
<li>Added <a href="mode/less/index.html">LESS</a>, <a href="mode/mysql/index.html">MySQL</a>,
<a href="mode/go/index.html">Go</a>, and <a href="mode/verilog/index.html">Verilog</a> modes.</li>
<li>Add <a href="doc/manual.html#option_smartIndent"><code>smartIndent</code></a>
option.</li>
<li>Support a cursor in <a href="doc/manual.html#option_readOnly"><code>readOnly</code></a>-mode.</li>
<li>Support assigning multiple styles to a token.</li>
<li>Use a new approach to drawing the selection.</li>
<li>Add <a href="doc/manual.html#scrollTo"><code>scrollTo</code></a> method.</li>
<li>Allow undo/redo events to span non-adjacent lines.</li>
<li>Lots and lots of bugfixes.</li>
</ul>
<p class="rel">20-12-2011: <a href="http://codemirror.net/codemirror-2.2.zip">Version 2.2</a>:</p>
<ul class="rel-note">
<li>Slightly incompatible API changes. Read <a href="doc/upgrade_v2.2.html">this</a>.</li>
<li>New approach
to <a href="doc/manual.html#option_extraKeys">binding</a> keys,
support for <a href="doc/manual.html#option_keyMap">custom
bindings</a>.</li>
<li>Support for overwrite (insert).</li>
<li><a href="doc/manual.html#option_tabSize">Custom-width</a>
and <a href="demo/visibletabs.html">stylable</a> tabs.</li>
<li>Moved more code into <a href="doc/manual.html#addons">add-on scripts</a>.</li>
<li>Support for sane vertical cursor movement in wrapped lines.</li>
<li>More reliable handling of
editing <a href="doc/manual.html#markText">marked text</a>.</li>
<li>Add minimal <a href="demo/emacs.html">emacs</a>
and <a href="demo/vim.html">vim</a> bindings.</li>
<li>Rename <code>coordsFromIndex</code>
to <a href="doc/manual.html#posFromIndex"><code>posFromIndex</code></a>,
add <a href="doc/manual.html#indexFromPos"><code>indexFromPos</code></a>
method.</li>
</ul>
<p class="rel">21-11-2011: <a href="http://codemirror.net/codemirror-2.18.zip">Version 2.18</a>:</p>
<p class="rel-note">Fixes <code>TextMarker.clear</code>, which is broken in 2.17.</p>
<p class="rel">21-11-2011: <a href="http://codemirror.net/codemirror-2.17.zip">Version 2.17</a>:</p>
<ul class="rel-note">
<li>Add support for <a href="doc/manual.html#option_lineWrapping">line
wrapping</a> and <a href="doc/manual.html#hideLine">code
folding</a>.</li>
<li>Add <a href="mode/gfm/index.html">Github-style Markdown</a> mode.</li>
<li>Add <a href="theme/monokai.css">Monokai</a>
and <a href="theme/rubyblue.css">Rubyblue</a> themes.</li>
<li>Add <a href="doc/manual.html#setBookmark"><code>setBookmark</code></a> method.</li>
<li>Move some of the demo code into reusable components
under <a href="lib/util/"><code>lib/util</code></a>.</li>
<li>Make screen-coord-finding code faster and more reliable.</li>
<li>Fix drag-and-drop in Firefox.</li>
<li>Improve support for IME.</li>
<li>Speed up content rendering.</li>
<li>Fix browser's built-in search in Webkit.</li>
<li>Make double- and triple-click work in IE.</li>
<li>Various fixes to modes.</li>
</ul>
<p class="rel">27-10-2011: <a href="http://codemirror.net/codemirror-2.16.zip">Version 2.16</a>:</p>
<ul class="rel-note">
<li>Add <a href="mode/perl/index.html">Perl</a>, <a href="mode/rust/index.html">Rust</a>, <a href="mode/tiddlywiki/index.html">TiddlyWiki</a>, and <a href="mode/groovy/index.html">Groovy</a> modes.</li>
<li>Dragging text inside the editor now moves, rather than copies.</li>
<li>Add a <a href="doc/manual.html#coordsFromIndex"><code>coordsFromIndex</code></a> method.</li>
<li><strong>API change</strong>: <code>setValue</code> now no longer clears history. Use <a href="doc/manual.html#clearHistory"><code>clearHistory</code></a> for that.</li>
<li><strong>API change</strong>: <a href="doc/manual.html#markText"><code>markText</code></a> now
returns an object with <code>clear</code> and <code>find</code>
methods. Marked text is now more robust when edited.</li>
<li>Fix editing code with tabs in Internet Explorer.</li>
</ul>
<p class="rel">26-09-2011: <a href="http://codemirror.net/codemirror-2.15.zip">Version 2.15</a>:</p>
<p class="rel-note">Fix bug that snuck into 2.14: Clicking the
character that currently has the cursor didn't re-focus the
editor.</p>
<p class="rel">26-09-2011: <a href="http://codemirror.net/codemirror-2.14.zip">Version 2.14</a>:</p>
<ul class="rel-note">
<li>Add <a href="mode/clojure/index.html">Clojure</a>, <a href="mode/pascal/index.html">Pascal</a>, <a href="mode/ntriples/index.html">NTriples</a>, <a href="mode/jinja2/index.html">Jinja2</a>, and <a href="mode/markdown/index.html">Markdown</a> modes.</li>
<li>Add <a href="theme/cobalt.css">Cobalt</a> and <a href="theme/eclipse.css">Eclipse</a> themes.</li>
<li>Add a <a href="doc/manual.html#option_fixedGutter"><code>fixedGutter</code></a> option.</li>
<li>Fix bug with <code>setValue</code> breaking cursor movement.</li>
<li>Make gutter updates much more efficient.</li>
<li>Allow dragging of text out of the editor (on modern browsers).</li>
</ul>
<p class="rel">23-08-2011: <a href="http://codemirror.net/codemirror-2.13.zip">Version 2.13</a>:</p>
<ul class="rel-note">
<li>Add <a href="mode/ruby/index.html">Ruby</a>, <a href="mode/r/index.html">R</a>, <a href="mode/coffeescript/index.html">CoffeeScript</a>, and <a href="mode/velocity/index.html">Velocity</a> modes.</li>
<li>Add <a href="doc/manual.html#getGutterElement"><code>getGutterElement</code></a> to API.</li>
<li>Several fixes to scrolling and positioning.</li>
<li>Add <a href="doc/manual.html#option_smartHome"><code>smartHome</code></a> option.</li>
<li>Add an experimental <a href="mode/xmlpure/index.html">pure XML</a> mode.</li>
</ul>
<p class="rel">25-07-2011: <a href="http://codemirror.net/codemirror-2.12.zip">Version 2.12</a>:</p>
<ul class="rel-note">
<li>Add a <a href="mode/sparql/index.html">SPARQL</a> mode.</li>
<li>Fix bug with cursor jumping around in an unfocused editor in IE.</li>
<li>Allow key and mouse events to bubble out of the editor. Ignore widget clicks.</li>
<li>Solve cursor flakiness after undo/redo.</li>
<li>Fix block-reindent ignoring the last few lines.</li>
<li>Fix parsing of multi-line attrs in XML mode.</li>
<li>Use <code>innerHTML</code> for HTML-escaping.</li>
<li>Some fixes to indentation in C-like mode.</li>
<li>Shrink horiz scrollbars when long lines removed.</li>
<li>Fix width feedback loop bug that caused the width of an inner DIV to shrink.</li>
</ul>
<p><a href="doc/oldrelease.html">Older releases...</a></p>
</div></div>
<div style="height: 2em">&nbsp;</div>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" id="paypal">
<input type="hidden" name="cmd" value="_s-xclick"/>
<input type="hidden" name="hosted_button_id" value="3FVHS5FGUY7CC"/>
</form>
</body>
</html>

View File

@@ -1,347 +0,0 @@
(function() {
var count = "";
var sdir = "f";
var buf = "";
var yank = 0;
var mark = [];
function emptyBuffer() { buf = ""; }
function pushInBuffer(str) { buf += str; };
function pushCountDigit(digit) { return function(cm) {count += digit;} }
function popCount() { var i = parseInt(count); count = ""; return i || 1; }
function countTimes(func) {
if (typeof func == "string") func = CodeMirror.commands[func];
return function(cm) { for (var i = 0, c = popCount(); i < c; ++i) func(cm); }
}
function iterObj(o, f) {
for (var prop in o) if (o.hasOwnProperty(prop)) f(prop, o[prop]);
}
var word = [/\w/, /[^\w\s]/], bigWord = [/\S/];
function findWord(line, pos, dir, regexps) {
var stop = 0, next = -1;
if (dir > 0) { stop = line.length; next = 0; }
var start = stop, end = stop;
// Find bounds of next one.
outer: for (; pos != stop; pos += dir) {
for (var i = 0; i < regexps.length; ++i) {
if (regexps[i].test(line.charAt(pos + next))) {
start = pos;
for (; pos != stop; pos += dir) {
if (!regexps[i].test(line.charAt(pos + next))) break;
}
end = pos;
break outer;
}
}
}
return {from: Math.min(start, end), to: Math.max(start, end)};
}
function moveToWord(cm, regexps, dir, where) {
var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line), word;
while (true) {
word = findWord(line, ch, dir, regexps);
ch = word[where == "end" ? "to" : "from"];
if (ch == cur.ch && word.from != word.to) ch = word[dir < 0 ? "from" : "to"];
else break;
}
cm.setCursor(cur.line, word[where == "end" ? "to" : "from"], true);
}
function joinLineNext(cm) {
var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line);
CodeMirror.commands.goLineEnd(cm);
if (cur.line != cm.lineCount()) {
CodeMirror.commands.goLineEnd(cm);
cm.replaceSelection(" ", "end");
CodeMirror.commands.delCharRight(cm);
}
}
function editCursor(mode) {
if (mode == "vim-insert") {
// put in your cursor css changing code
} else if (mode == "vim") {
// put in your cursor css changing code
}
}
function delTillMark(cm, cHar) {
var i = mark[cHar], l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
cm.setCursor(start);
for (var c = start; c <= end; c++) {
pushInBuffer("\n"+cm.getLine(start));
cm.removeLine(start);
}
}
function yankTillMark(cm, cHar) {
var i = mark[cHar], l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
for (var c = start; c <= end; c++) {
pushInBuffer("\n"+cm.getLine(c));
}
cm.setCursor(start);
}
var map = CodeMirror.keyMap.vim = {
"0": function(cm) {count.length > 0 ? pushCountDigit("0")(cm) : CodeMirror.commands.goLineStart(cm);},
"A": function(cm) {popCount(); cm.setCursor(cm.getCursor().line, cm.getCursor().ch+1, true); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"Shift-A": function(cm) {popCount(); CodeMirror.commands.goLineEnd(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"I": function(cm) {popCount(); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"Shift-I": function(cm) {popCount(); CodeMirror.commands.goLineStartSmart(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"O": function(cm) {popCount(); CodeMirror.commands.goLineEnd(cm); cm.replaceSelection("\n", "end"); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"Shift-O": function(cm) {popCount(); CodeMirror.commands.goLineStart(cm); cm.replaceSelection("\n", "start"); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"G": function(cm) {cm.setOption("keyMap", "vim-prefix-g");},
"D": function(cm) {cm.setOption("keyMap", "vim-prefix-d"); emptyBuffer();},
"M": function(cm) {cm.setOption("keyMap", "vim-prefix-m"); mark = [];},
"Y": function(cm) {cm.setOption("keyMap", "vim-prefix-y"); emptyBuffer(); yank = 0;},
"/": function(cm) {var f = CodeMirror.commands.find; f && f(cm); sdir = "f"},
"Shift-/": function(cm) {
var f = CodeMirror.commands.find;
if (f) { f(cm); CodeMirror.commands.findPrev(cm); sdir = "r"; }
},
"N": function(cm) {
var fn = CodeMirror.commands.findNext;
if (fn) sdir != "r" ? fn(cm) : CodeMirror.commands.findPrev(cm);
},
"Shift-N": function(cm) {
var fn = CodeMirror.commands.findNext;
if (fn) sdir != "r" ? CodeMirror.commands.findPrev(cm) : fn.findNext(cm);
},
"Shift-G": function(cm) {count == "" ? cm.setCursor(cm.lineCount()) : cm.setCursor(parseInt(count)-1); popCount(); CodeMirror.commands.goLineStart(cm);},
catchall: function(cm) {/*ignore*/}
};
// Add bindings for number keys
for (var i = 1; i < 10; ++i) map[i] = pushCountDigit(i);
// Add bindings that are influenced by number keys
iterObj({"H": "goColumnLeft", "L": "goColumnRight", "J": "goLineDown", "K": "goLineUp",
"Left": "goColumnLeft", "Right": "goColumnRight", "Down": "goLineDown", "Up": "goLineUp",
"Backspace": "goCharLeft", "Space": "goCharRight",
"B": function(cm) {moveToWord(cm, word, -1, "end");},
"E": function(cm) {moveToWord(cm, word, 1, "end");},
"W": function(cm) {moveToWord(cm, word, 1, "start");},
"Shift-B": function(cm) {moveToWord(cm, bigWord, -1, "end");},
"Shift-E": function(cm) {moveToWord(cm, bigWord, 1, "end");},
"Shift-W": function(cm) {moveToWord(cm, bigWord, 1, "start");},
"X": function(cm) {CodeMirror.commands.delCharRight(cm)},
"P": function(cm) {
var cur = cm.getCursor().line;
if (buf!= "") {
CodeMirror.commands.goLineEnd(cm);
cm.replaceSelection(buf, "end");
}
cm.setCursor(cur+1);
},
"Shift-X": function(cm) {CodeMirror.commands.delCharLeft(cm)},
"Shift-J": function(cm) {joinLineNext(cm)},
"Shift-`": function(cm) {
var cur = cm.getCursor(), cHar = cm.getRange({line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});
cHar = cHar != cHar.toLowerCase() ? cHar.toLowerCase() : cHar.toUpperCase();
cm.replaceRange(cHar, {line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});
cm.setCursor(cur.line, cur.ch+1);
},
"Ctrl-B": function(cm) {CodeMirror.commands.goPageUp(cm)},
"Ctrl-F": function(cm) {CodeMirror.commands.goPageDown(cm)},
"Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
"U": "undo", "Ctrl-R": "redo", "Shift-4": "goLineEnd"},
function(key, cmd) { map[key] = countTimes(cmd); });
CodeMirror.keyMap["vim-prefix-g"] = {
"E": countTimes(function(cm) { moveToWord(cm, word, -1, "start");}),
"Shift-E": countTimes(function(cm) { moveToWord(cm, bigWord, -1, "start");}),
auto: "vim",
catchall: function(cm) {/*ignore*/}
};
CodeMirror.keyMap["vim-prefix-m"] = {
"A": function(cm) {mark["A"] = cm.getCursor().line;},
"Shift-A": function(cm) {mark["Shift-A"] = cm.getCursor().line;},
"B": function(cm) {mark["B"] = cm.getCursor().line;},
"Shift-B": function(cm) {mark["Shift-B"] = cm.getCursor().line;},
"C": function(cm) {mark["C"] = cm.getCursor().line;},
"Shift-C": function(cm) {mark["Shift-C"] = cm.getCursor().line;},
"D": function(cm) {mark["D"] = cm.getCursor().line;},
"Shift-D": function(cm) {mark["Shift-D"] = cm.getCursor().line;},
"E": function(cm) {mark["E"] = cm.getCursor().line;},
"Shift-E": function(cm) {mark["Shift-E"] = cm.getCursor().line;},
"F": function(cm) {mark["F"] = cm.getCursor().line;},
"Shift-F": function(cm) {mark["Shift-F"] = cm.getCursor().line;},
"G": function(cm) {mark["G"] = cm.getCursor().line;},
"Shift-G": function(cm) {mark["Shift-G"] = cm.getCursor().line;},
"H": function(cm) {mark["H"] = cm.getCursor().line;},
"Shift-H": function(cm) {mark["Shift-H"] = cm.getCursor().line;},
"I": function(cm) {mark["I"] = cm.getCursor().line;},
"Shift-I": function(cm) {mark["Shift-I"] = cm.getCursor().line;},
"J": function(cm) {mark["J"] = cm.getCursor().line;},
"Shift-J": function(cm) {mark["Shift-J"] = cm.getCursor().line;},
"K": function(cm) {mark["K"] = cm.getCursor().line;},
"Shift-K": function(cm) {mark["Shift-K"] = cm.getCursor().line;},
"L": function(cm) {mark["L"] = cm.getCursor().line;},
"Shift-L": function(cm) {mark["Shift-L"] = cm.getCursor().line;},
"M": function(cm) {mark["M"] = cm.getCursor().line;},
"Shift-M": function(cm) {mark["Shift-M"] = cm.getCursor().line;},
"N": function(cm) {mark["N"] = cm.getCursor().line;},
"Shift-N": function(cm) {mark["Shift-N"] = cm.getCursor().line;},
"O": function(cm) {mark["O"] = cm.getCursor().line;},
"Shift-O": function(cm) {mark["Shift-O"] = cm.getCursor().line;},
"P": function(cm) {mark["P"] = cm.getCursor().line;},
"Shift-P": function(cm) {mark["Shift-P"] = cm.getCursor().line;},
"Q": function(cm) {mark["Q"] = cm.getCursor().line;},
"Shift-Q": function(cm) {mark["Shift-Q"] = cm.getCursor().line;},
"R": function(cm) {mark["R"] = cm.getCursor().line;},
"Shift-R": function(cm) {mark["Shift-R"] = cm.getCursor().line;},
"S": function(cm) {mark["S"] = cm.getCursor().line;},
"Shift-S": function(cm) {mark["Shift-S"] = cm.getCursor().line;},
"T": function(cm) {mark["T"] = cm.getCursor().line;},
"Shift-T": function(cm) {mark["Shift-T"] = cm.getCursor().line;},
"U": function(cm) {mark["U"] = cm.getCursor().line;},
"Shift-U": function(cm) {mark["Shift-U"] = cm.getCursor().line;},
"V": function(cm) {mark["V"] = cm.getCursor().line;},
"Shift-V": function(cm) {mark["Shift-V"] = cm.getCursor().line;},
"W": function(cm) {mark["W"] = cm.getCursor().line;},
"Shift-W": function(cm) {mark["Shift-W"] = cm.getCursor().line;},
"X": function(cm) {mark["X"] = cm.getCursor().line;},
"Shift-X": function(cm) {mark["Shift-X"] = cm.getCursor().line;},
"Y": function(cm) {mark["Y"] = cm.getCursor().line;},
"Shift-Y": function(cm) {mark["Shift-Y"] = cm.getCursor().line;},
"Z": function(cm) {mark["Z"] = cm.getCursor().line;},
"Shift-Z": function(cm) {mark["Shift-Z"] = cm.getCursor().line;},
auto: "vim",
catchall: function(cm) {/*ignore*/}
}
CodeMirror.keyMap["vim-prefix-d"] = {
"D": countTimes(function(cm) { pushInBuffer("\n"+cm.getLine(cm.getCursor().line)); cm.removeLine(cm.getCursor().line); }),
"'": function(cm) {cm.setOption("keyMap", "vim-prefix-d'"); emptyBuffer();},
auto: "vim",
catchall: function(cm) {/*ignore*/}
};
CodeMirror.keyMap["vim-prefix-d'"] = {
"A": function(cm) {delTillMark(cm,"A");},
"Shift-A": function(cm) {delTillMark(cm,"Shift-A");},
"B": function(cm) {delTillMark(cm,"B");},
"Shift-B": function(cm) {delTillMark(cm,"Shift-B");},
"C": function(cm) {delTillMark(cm,"C");},
"Shift-C": function(cm) {delTillMark(cm,"Shift-C");},
"D": function(cm) {delTillMark(cm,"D");},
"Shift-D": function(cm) {delTillMark(cm,"Shift-D");},
"E": function(cm) {delTillMark(cm,"E");},
"Shift-E": function(cm) {delTillMark(cm,"Shift-E");},
"F": function(cm) {delTillMark(cm,"F");},
"Shift-F": function(cm) {delTillMark(cm,"Shift-F");},
"G": function(cm) {delTillMark(cm,"G");},
"Shift-G": function(cm) {delTillMark(cm,"Shift-G");},
"H": function(cm) {delTillMark(cm,"H");},
"Shift-H": function(cm) {delTillMark(cm,"Shift-H");},
"I": function(cm) {delTillMark(cm,"I");},
"Shift-I": function(cm) {delTillMark(cm,"Shift-I");},
"J": function(cm) {delTillMark(cm,"J");},
"Shift-J": function(cm) {delTillMark(cm,"Shift-J");},
"K": function(cm) {delTillMark(cm,"K");},
"Shift-K": function(cm) {delTillMark(cm,"Shift-K");},
"L": function(cm) {delTillMark(cm,"L");},
"Shift-L": function(cm) {delTillMark(cm,"Shift-L");},
"M": function(cm) {delTillMark(cm,"M");},
"Shift-M": function(cm) {delTillMark(cm,"Shift-M");},
"N": function(cm) {delTillMark(cm,"N");},
"Shift-N": function(cm) {delTillMark(cm,"Shift-N");},
"O": function(cm) {delTillMark(cm,"O");},
"Shift-O": function(cm) {delTillMark(cm,"Shift-O");},
"P": function(cm) {delTillMark(cm,"P");},
"Shift-P": function(cm) {delTillMark(cm,"Shift-P");},
"Q": function(cm) {delTillMark(cm,"Q");},
"Shift-Q": function(cm) {delTillMark(cm,"Shift-Q");},
"R": function(cm) {delTillMark(cm,"R");},
"Shift-R": function(cm) {delTillMark(cm,"Shift-R");},
"S": function(cm) {delTillMark(cm,"S");},
"Shift-S": function(cm) {delTillMark(cm,"Shift-S");},
"T": function(cm) {delTillMark(cm,"T");},
"Shift-T": function(cm) {delTillMark(cm,"Shift-T");},
"U": function(cm) {delTillMark(cm,"U");},
"Shift-U": function(cm) {delTillMark(cm,"Shift-U");},
"V": function(cm) {delTillMark(cm,"V");},
"Shift-V": function(cm) {delTillMark(cm,"Shift-V");},
"W": function(cm) {delTillMark(cm,"W");},
"Shift-W": function(cm) {delTillMark(cm,"Shift-W");},
"X": function(cm) {delTillMark(cm,"X");},
"Shift-X": function(cm) {delTillMark(cm,"Shift-X");},
"Y": function(cm) {delTillMark(cm,"Y");},
"Shift-Y": function(cm) {delTillMark(cm,"Shift-Y");},
"Z": function(cm) {delTillMark(cm,"Z");},
"Shift-Z": function(cm) {delTillMark(cm,"Shift-Z");},
auto: "vim",
catchall: function(cm) {/*ignore*/}
};
CodeMirror.keyMap["vim-prefix-y'"] = {
"A": function(cm) {yankTillMark(cm,"A");},
"Shift-A": function(cm) {yankTillMark(cm,"Shift-A");},
"B": function(cm) {yankTillMark(cm,"B");},
"Shift-B": function(cm) {yankTillMark(cm,"Shift-B");},
"C": function(cm) {yankTillMark(cm,"C");},
"Shift-C": function(cm) {yankTillMark(cm,"Shift-C");},
"D": function(cm) {yankTillMark(cm,"D");},
"Shift-D": function(cm) {yankTillMark(cm,"Shift-D");},
"E": function(cm) {yankTillMark(cm,"E");},
"Shift-E": function(cm) {yankTillMark(cm,"Shift-E");},
"F": function(cm) {yankTillMark(cm,"F");},
"Shift-F": function(cm) {yankTillMark(cm,"Shift-F");},
"G": function(cm) {yankTillMark(cm,"G");},
"Shift-G": function(cm) {yankTillMark(cm,"Shift-G");},
"H": function(cm) {yankTillMark(cm,"H");},
"Shift-H": function(cm) {yankTillMark(cm,"Shift-H");},
"I": function(cm) {yankTillMark(cm,"I");},
"Shift-I": function(cm) {yankTillMark(cm,"Shift-I");},
"J": function(cm) {yankTillMark(cm,"J");},
"Shift-J": function(cm) {yankTillMark(cm,"Shift-J");},
"K": function(cm) {yankTillMark(cm,"K");},
"Shift-K": function(cm) {yankTillMark(cm,"Shift-K");},
"L": function(cm) {yankTillMark(cm,"L");},
"Shift-L": function(cm) {yankTillMark(cm,"Shift-L");},
"M": function(cm) {yankTillMark(cm,"M");},
"Shift-M": function(cm) {yankTillMark(cm,"Shift-M");},
"N": function(cm) {yankTillMark(cm,"N");},
"Shift-N": function(cm) {yankTillMark(cm,"Shift-N");},
"O": function(cm) {yankTillMark(cm,"O");},
"Shift-O": function(cm) {yankTillMark(cm,"Shift-O");},
"P": function(cm) {yankTillMark(cm,"P");},
"Shift-P": function(cm) {yankTillMark(cm,"Shift-P");},
"Q": function(cm) {yankTillMark(cm,"Q");},
"Shift-Q": function(cm) {yankTillMark(cm,"Shift-Q");},
"R": function(cm) {yankTillMark(cm,"R");},
"Shift-R": function(cm) {yankTillMark(cm,"Shift-R");},
"S": function(cm) {yankTillMark(cm,"S");},
"Shift-S": function(cm) {yankTillMark(cm,"Shift-S");},
"T": function(cm) {yankTillMark(cm,"T");},
"Shift-T": function(cm) {yankTillMark(cm,"Shift-T");},
"U": function(cm) {yankTillMark(cm,"U");},
"Shift-U": function(cm) {yankTillMark(cm,"Shift-U");},
"V": function(cm) {yankTillMark(cm,"V");},
"Shift-V": function(cm) {yankTillMark(cm,"Shift-V");},
"W": function(cm) {yankTillMark(cm,"W");},
"Shift-W": function(cm) {yankTillMark(cm,"Shift-W");},
"X": function(cm) {yankTillMark(cm,"X");},
"Shift-X": function(cm) {yankTillMark(cm,"Shift-X");},
"Y": function(cm) {yankTillMark(cm,"Y");},
"Shift-Y": function(cm) {yankTillMark(cm,"Shift-Y");},
"Z": function(cm) {yankTillMark(cm,"Z");},
"Shift-Z": function(cm) {yankTillMark(cm,"Shift-Z");},
auto: "vim",
catchall: function(cm) {/*ignore*/}
};
CodeMirror.keyMap["vim-prefix-y"] = {
"Y": countTimes(function(cm) { pushInBuffer("\n"+cm.getLine(cm.getCursor().line+yank)); yank++; }),
"'": function(cm) {cm.setOption("keyMap", "vim-prefix-y'"); emptyBuffer();},
auto: "vim",
catchall: function(cm) {/*ignore*/}
};
CodeMirror.keyMap["vim-insert"] = {
"Esc": function(cm) {
cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true);
cm.setOption("keyMap", "vim");
editCursor("vim");
},
"Ctrl-N": function(cm) {/* Code to bring up autocomplete hint */},
"Ctrl-P": function(cm) {/* Code to bring up autocomplete hint */},
fallthrough: ["default"]
};
})();

View File

@@ -1,4 +1,4 @@
Copyright (C) 2011 by Marijn Haverbeke <marijnh@gmail.com>
Copyright (C) 2012 by Marijn Haverbeke <marijnh@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -24,6 +24,6 @@
CodeMirror.keyMap["emacs-Ctrl-X"] = {
"Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": "undo", "K": "close",
auto: "emacs", catchall: function(cm) {/*ignore*/}
auto: "emacs", nofallthrough: true
};
})();

View File

@@ -0,0 +1,230 @@
(function() {
var count = "";
var sdir = "f";
var buf = "";
var yank = 0;
var mark = [];
function emptyBuffer() { buf = ""; }
function pushInBuffer(str) { buf += str; };
function pushCountDigit(digit) { return function(cm) {count += digit;} }
function popCount() { var i = parseInt(count); count = ""; return i || 1; }
function countTimes(func) {
if (typeof func == "string") func = CodeMirror.commands[func];
return function(cm) { for (var i = 0, c = popCount(); i < c; ++i) func(cm); }
}
function iterObj(o, f) {
for (var prop in o) if (o.hasOwnProperty(prop)) f(prop, o[prop]);
}
var word = [/\w/, /[^\w\s]/], bigWord = [/\S/];
function findWord(line, pos, dir, regexps) {
var stop = 0, next = -1;
if (dir > 0) { stop = line.length; next = 0; }
var start = stop, end = stop;
// Find bounds of next one.
outer: for (; pos != stop; pos += dir) {
for (var i = 0; i < regexps.length; ++i) {
if (regexps[i].test(line.charAt(pos + next))) {
start = pos;
for (; pos != stop; pos += dir) {
if (!regexps[i].test(line.charAt(pos + next))) break;
}
end = pos;
break outer;
}
}
}
return {from: Math.min(start, end), to: Math.max(start, end)};
}
function moveToWord(cm, regexps, dir, where) {
var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line), word;
while (true) {
word = findWord(line, ch, dir, regexps);
ch = word[where == "end" ? "to" : "from"];
if (ch == cur.ch && word.from != word.to) ch = word[dir < 0 ? "from" : "to"];
else break;
}
cm.setCursor(cur.line, word[where == "end" ? "to" : "from"], true);
}
function joinLineNext(cm) {
var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line);
CodeMirror.commands.goLineEnd(cm);
if (cur.line != cm.lineCount()) {
CodeMirror.commands.goLineEnd(cm);
cm.replaceSelection(" ", "end");
CodeMirror.commands.delCharRight(cm);
}
}
function editCursor(mode) {
if (mode == "vim-insert") {
// put in your cursor css changing code
} else if (mode == "vim") {
// put in your cursor css changing code
}
}
function delTillMark(cm, cHar) {
var i = mark[cHar], l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
cm.setCursor(start);
for (var c = start; c <= end; c++) {
pushInBuffer("\n"+cm.getLine(start));
cm.removeLine(start);
}
}
function yankTillMark(cm, cHar) {
var i = mark[cHar], l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
for (var c = start; c <= end; c++) {
pushInBuffer("\n"+cm.getLine(c));
}
cm.setCursor(start);
}
function goLineStartText(cm) {
// Go to the start of the line where the text begins, or the end for whitespace-only lines
var cur = cm.getCursor(), firstNonWS = cm.getLine(cur.line).search(/\S/);
cm.setCursor(cur.line, firstNonWS == -1 ? line.length : firstNonWS, true);
}
var map = CodeMirror.keyMap.vim = {
"0": function(cm) {count.length > 0 ? pushCountDigit("0")(cm) : CodeMirror.commands.goLineStart(cm);},
// Pipe (|); TODO: should be *screen* chars, so need a util function to turn tabs into spaces?
"'|'": function(cm) {cm.setCursor(cm.getCursor().line, popCount() - 1, true);},
"'^'": function(cm) {popCount(); goLineStartText(cm);},
"A": function(cm) {popCount(); cm.setCursor(cm.getCursor().line, cm.getCursor().ch+1, true); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"Shift-A": function(cm) {popCount(); CodeMirror.commands.goLineEnd(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"I": function(cm) {popCount(); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"Shift-I": function(cm) {popCount(); goLineStartText(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"O": function(cm) {popCount(); CodeMirror.commands.goLineEnd(cm); CodeMirror.commands.newlineAndIndent(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"Shift-O": function(cm) {popCount(); CodeMirror.commands.goLineStart(cm); cm.replaceSelection("\n", "start"); cm.indentLine(cm.getCursor().line); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"G": function(cm) {cm.setOption("keyMap", "vim-prefix-g");},
"D": function(cm) {cm.setOption("keyMap", "vim-prefix-d"); emptyBuffer();},
"Shift-D": function(cm) {
emptyBuffer();
mark["Shift-D"] = cm.getCursor(false).line;
cm.setCursor(cm.getCursor(true).line);
delTillMark(cm,"Shift-D"); mark = [];
},
"M": function(cm) {cm.setOption("keyMap", "vim-prefix-m"); mark = [];},
"Y": function(cm) {cm.setOption("keyMap", "vim-prefix-y"); emptyBuffer(); yank = 0;},
"Shift-Y": function(cm) {
emptyBuffer();
mark["Shift-D"] = cm.getCursor(false).line;
cm.setCursor(cm.getCursor(true).line);
yankTillMark(cm,"Shift-D"); mark = [];
},
"/": function(cm) {var f = CodeMirror.commands.find; f && f(cm); sdir = "f"},
"'?'": function(cm) {
var f = CodeMirror.commands.find;
if (f) { f(cm); CodeMirror.commands.findPrev(cm); sdir = "r"; }
},
"N": function(cm) {
var fn = CodeMirror.commands.findNext;
if (fn) sdir != "r" ? fn(cm) : CodeMirror.commands.findPrev(cm);
},
"Shift-N": function(cm) {
var fn = CodeMirror.commands.findNext;
if (fn) sdir != "r" ? CodeMirror.commands.findPrev(cm) : fn.findNext(cm);
},
"Shift-G": function(cm) {count == "" ? cm.setCursor(cm.lineCount()) : cm.setCursor(parseInt(count)-1); popCount(); CodeMirror.commands.goLineStart(cm);},
nofallthrough: true
};
// Add bindings for number keys
for (var i = 1; i < 10; ++i) map[i] = pushCountDigit(i);
// Add bindings that are influenced by number keys
iterObj({
"H": "goColumnLeft", "L": "goColumnRight", "J": "goLineDown",
"K": "goLineUp", "Left": "goColumnLeft", "Right": "goColumnRight",
"Down": "goLineDown", "Up": "goLineUp", "Backspace": "goCharLeft",
"Space": "goCharRight",
"B": function(cm) {moveToWord(cm, word, -1, "end");},
"E": function(cm) {moveToWord(cm, word, 1, "end");},
"W": function(cm) {moveToWord(cm, word, 1, "start");},
"Shift-B": function(cm) {moveToWord(cm, bigWord, -1, "end");},
"Shift-E": function(cm) {moveToWord(cm, bigWord, 1, "end");},
"Shift-W": function(cm) {moveToWord(cm, bigWord, 1, "start");},
"X": function(cm) {CodeMirror.commands.delCharRight(cm)},
"P": function(cm) {
var cur = cm.getCursor().line;
if (buf!= "") {
CodeMirror.commands.goLineEnd(cm);
cm.replaceSelection(buf, "end");
}
cm.setCursor(cur+1);
},
"Shift-X": function(cm) {CodeMirror.commands.delCharLeft(cm)},
"Shift-J": function(cm) {joinLineNext(cm)},
"'~'": function(cm) {
var cur = cm.getCursor(), cHar = cm.getRange({line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});
cHar = cHar != cHar.toLowerCase() ? cHar.toLowerCase() : cHar.toUpperCase();
cm.replaceRange(cHar, {line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});
cm.setCursor(cur.line, cur.ch+1);
},
"Ctrl-B": function(cm) {CodeMirror.commands.goPageUp(cm)},
"Ctrl-F": function(cm) {CodeMirror.commands.goPageDown(cm)},
"Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
"U": "undo", "Ctrl-R": "redo", "'$'": "goLineEnd"
}, function(key, cmd) { map[key] = countTimes(cmd); });
CodeMirror.keyMap["vim-prefix-g"] = {
"E": countTimes(function(cm) { moveToWord(cm, word, -1, "start");}),
"Shift-E": countTimes(function(cm) { moveToWord(cm, bigWord, -1, "start");}),
auto: "vim",
nofallthrough: true
};
CodeMirror.keyMap["vim-prefix-m"] = {
auto: "vim",
nofallthrough: true
};
CodeMirror.keyMap["vim-prefix-d"] = {
"D": countTimes(function(cm) { pushInBuffer("\n"+cm.getLine(cm.getCursor().line)); cm.removeLine(cm.getCursor().line); }),
"'": function(cm) {cm.setOption("keyMap", "vim-prefix-d'"); emptyBuffer();},
auto: "vim",
nofallthrough: true
};
CodeMirror.keyMap["vim-prefix-d'"] = {
auto: "vim",
nofallthrough: true
};
CodeMirror.keyMap["vim-prefix-y'"] = {
auto: "vim",
nofallthrough: true
};
// iterate through uppercase alphabet char codes
for (var i = 65; i < 65 + 26; i++) {
// apply for `letter` and 'Shift-' + `letter`
for (var m = String.fromCharCode(i); m.length < 8; m = "Shift-" + m) {
CodeMirror.keyMap["vim-prefix-m"][m] = function(cm) {
mark[m] = cm.getCursor().line;
};
CodeMirror.keyMap["vim-prefix-d'"][m] = function(cm) {
delTillMark(cm,m);
};
CodeMirror.keyMap["vim-prefix-y'"][m] = function(cm) {
yankTillMark(cm,m);
};
}
}
CodeMirror.keyMap["vim-prefix-y"] = {
"Y": countTimes(function(cm) { pushInBuffer("\n"+cm.getLine(cm.getCursor().line+yank)); yank++; }),
"'": function(cm) {cm.setOption("keyMap", "vim-prefix-y'"); emptyBuffer();},
auto: "vim",
nofallthrough: true
};
CodeMirror.keyMap["vim-insert"] = {
// TODO: override navigation keys so that Esc will cancel automatic indentation from o, O, i_<CR>
"Esc": function(cm) {
cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true);
cm.setOption("keyMap", "vim");
editCursor("vim");
},
"Ctrl-N": function(cm) {/* Code to bring up autocomplete hint */},
"Ctrl-P": function(cm) {/* Code to bring up autocomplete hint */},
fallthrough: ["default"]
};
})();

View File

@@ -9,6 +9,7 @@
/* This is needed to prevent an IE[67] bug where the scrolled content
is visible outside of the scrolling box. */
position: relative;
outline: none;
}
.CodeMirror-gutter {
@@ -27,6 +28,7 @@
}
.CodeMirror-lines {
padding: .4em;
white-space: pre;
}
.CodeMirror pre {
@@ -40,11 +42,13 @@
padding: 0; margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-wrap .CodeMirror-scroll {
overflow-x: hidden;

View File

@@ -0,0 +1,174 @@
/**
* Tag-closer extension for CodeMirror.
*
* This extension adds a "closeTag" utility function that can be used with key bindings to
* insert a matching end tag after the ">" character of a start tag has been typed. It can
* also complete "</" if a matching start tag is found. It will correctly ignore signal
* characters for empty tags, comments, CDATA, etc.
*
* The function depends on internal parser state to identify tags. It is compatible with the
* following CodeMirror modes and will ignore all others:
* - htmlmixed
* - xml
* - xmlpure
*
* See demos/closetag.html for a usage example.
*
* @author Nathan Williams <nathan@nlwillia.net>
* Contributed under the same license terms as CodeMirror.
*/
(function() {
/** Option that allows tag closing behavior to be toggled. Default is true. */
CodeMirror.defaults['closeTagEnabled'] = true;
/** Array of tag names to add indentation after the start tag for. Default is the list of block-level html tags. */
CodeMirror.defaults['closeTagIndent'] = ['applet', 'blockquote', 'body', 'button', 'div', 'dl', 'fieldset', 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'html', 'iframe', 'layer', 'legend', 'object', 'ol', 'p', 'select', 'table', 'ul'];
/**
* Call during key processing to close tags. Handles the key event if the tag is closed, otherwise throws CodeMirror.Pass.
* - cm: The editor instance.
* - ch: The character being processed.
* - indent: Optional. Omit or pass true to use the default indentation tag list defined in the 'closeTagIndent' option.
* Pass false to disable indentation. Pass an array to override the default list of tag names.
*/
CodeMirror.defineExtension("closeTag", function(cm, ch, indent) {
if (!cm.getOption('closeTagEnabled')) {
throw CodeMirror.Pass;
}
var mode = cm.getOption('mode');
if (mode == 'text/html') {
/*
* Relevant structure of token:
*
* htmlmixed
* className
* state
* htmlState
* type
* context
* tagName
* mode
*
* xml
* className
* state
* tagName
* type
*/
var pos = cm.getCursor();
var tok = cm.getTokenAt(pos);
var state = tok.state;
if (state.mode && state.mode != 'html') {
throw CodeMirror.Pass; // With htmlmixed, we only care about the html sub-mode.
}
if (ch == '>') {
var type = state.htmlState ? state.htmlState.type : state.type; // htmlmixed : xml
if (tok.className == 'tag' && type == 'closeTag') {
throw CodeMirror.Pass; // Don't process the '>' at the end of an end-tag.
}
cm.replaceSelection('>'); // Mode state won't update until we finish the tag.
pos = {line: pos.line, ch: pos.ch + 1};
cm.setCursor(pos);
tok = cm.getTokenAt(cm.getCursor());
state = tok.state;
type = state.htmlState ? state.htmlState.type : state.type; // htmlmixed : xml
if (tok.className == 'tag' && type != 'selfcloseTag') {
var tagName = state.htmlState ? state.htmlState.context.tagName : state.tagName; // htmlmixed : xml
if (tagName.length > 0) {
insertEndTag(cm, indent, pos, tagName);
}
return;
}
// Undo the '>' insert and allow cm to handle the key instead.
cm.setSelection({line: pos.line, ch: pos.ch - 1}, pos);
cm.replaceSelection("");
} else if (ch == '/') {
if (tok.className == 'tag' && tok.string == '<') {
var tagName = state.htmlState ? (state.htmlState.context ? state.htmlState.context.tagName : '') : state.context.tagName; // htmlmixed : xml # extra htmlmized check is for '</' edge case
if (tagName.length > 0) {
completeEndTag(cm, pos, tagName);
return;
}
}
}
} else if (mode == 'xmlpure') {
var pos = cm.getCursor();
var tok = cm.getTokenAt(pos);
var tagName = tok.state.context.tagName;
if (ch == '>') {
// <foo> tagName=foo, string=foo
// <foo /> tagName=foo, string=/ # ignore
// <foo></foo> tagName=foo, string=/foo # ignore
if (tok.string == tagName) {
cm.replaceSelection('>'); // parity w/html modes
pos = {line: pos.line, ch: pos.ch + 1};
cm.setCursor(pos);
insertEndTag(cm, indent, pos, tagName);
return;
}
} else if (ch == '/') {
// <foo / tagName=foo, string= # ignore
// <foo></ tagName=foo, string=<
if (tok.string == '<') {
completeEndTag(cm, pos, tagName);
return;
}
}
}
throw CodeMirror.Pass; // Bubble if not handled
});
function insertEndTag(cm, indent, pos, tagName) {
if (shouldIndent(cm, indent, tagName)) {
cm.replaceSelection('\n\n</' + tagName + '>', 'end');
cm.indentLine(pos.line + 1);
cm.indentLine(pos.line + 2);
cm.setCursor({line: pos.line + 1, ch: cm.getLine(pos.line + 1).length});
} else {
cm.replaceSelection('</' + tagName + '>');
cm.setCursor(pos);
}
}
function shouldIndent(cm, indent, tagName) {
if (typeof indent == 'undefined' || indent == null || indent == true) {
indent = cm.getOption('closeTagIndent');
}
if (!indent) {
indent = [];
}
return indexOf(indent, tagName.toLowerCase()) != -1;
}
// C&P from codemirror.js...would be nice if this were visible to utilities.
function indexOf(collection, elt) {
if (collection.indexOf) return collection.indexOf(elt);
for (var i = 0, e = collection.length; i < e; ++i)
if (collection[i] == elt) return i;
return -1;
}
function completeEndTag(cm, pos, tagName) {
cm.replaceSelection('/' + tagName + '>');
cm.setCursor({line: pos.line, ch: pos.ch + tagName.length + 2 });
}
})();

View File

@@ -1,7 +1,7 @@
// the tagRangeFinder function is
// Copyright (C) 2011 by Daniel Glazman <daniel@glazman.org>
// released under the MIT license (../../LICENSE) like the rest of CodeMirror
CodeMirror.tagRangeFinder = function(cm, line) {
CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
var nameChar = nameStartChar + "\-\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
var xmlNAMERegExp = new RegExp("^[" + nameStartChar + "][" + nameChar + "]*");
@@ -36,8 +36,10 @@ CodeMirror.tagRangeFinder = function(cm, line) {
var slash = lt.lastIndexOf("/", gt);
if (-1 != slash && slash < gt) {
var str = lineText.substr(slash, gt - slash + 1);
if (!str.match( /\/\s*\>/ )) // yep, that's the end of empty tag
return l+1;
if (!str.match( /\/\s*\>/ )) { // yep, that's the end of empty tag
if (hideEnd === true) l++;
return l;
}
}
}
l++;
@@ -80,7 +82,7 @@ CodeMirror.tagRangeFinder = function(cm, line) {
}
if (found) {
var startTag = "(\\<\\/" + tag + "\\>)|(\\<" + tag + "\\>)|(\\<" + tag + "\s)|(\\<" + tag + "$)";
var startTag = "(\\<\\/" + tag + "\\>)|(\\<" + tag + "\\>)|(\\<" + tag + "\\s)|(\\<" + tag + "$)";
var startTagRegExp = new RegExp(startTag, "g");
var endTag = "</" + tag + ">";
var depth = 1;
@@ -95,8 +97,10 @@ CodeMirror.tagRangeFinder = function(cm, line) {
depth--;
else
depth++;
if (!depth)
return l+1;
if (!depth) {
if (hideEnd === true) l++;
return l;
}
}
}
l++;
@@ -105,7 +109,7 @@ CodeMirror.tagRangeFinder = function(cm, line) {
}
};
CodeMirror.braceRangeFinder = function(cm, line) {
CodeMirror.braceRangeFinder = function(cm, line, hideEnd) {
var lineText = cm.getLine(line);
var startChar = lineText.lastIndexOf("{");
if (startChar < 0 || lineText.lastIndexOf("}") > startChar) return;
@@ -127,6 +131,7 @@ CodeMirror.braceRangeFinder = function(cm, line) {
}
}
if (end == null || end == line + 1) return;
if (hideEnd === true) end++;
return end;
};
@@ -144,7 +149,7 @@ CodeMirror.indentRangeFinder = function(cm, line) {
return last + 1;
};
CodeMirror.newFoldFunction = function(rangeFinder, markText) {
CodeMirror.newFoldFunction = function(rangeFinder, markText, hideEnd) {
var folded = [];
if (markText == null) markText = '<div style="position: absolute; left: 2px; color:#600">&#x25bc;</div>%N%';
@@ -169,7 +174,7 @@ CodeMirror.newFoldFunction = function(rangeFinder, markText) {
folded.splice(known.pos, 1);
expand(cm, known.region);
} else {
var end = rangeFinder(cm, line);
var end = rangeFinder(cm, line, hideEnd);
if (end == null) return;
var hidden = [];
for (var i = line + 1; i < end; ++i) {

View File

@@ -1,4 +1,4 @@
// ============== Formatting extensions ============================
// ============== Formatting extensions ============================
// A common storage for all mode-specific formatting features
if (!CodeMirror.modeExtensions) CodeMirror.modeExtensions = {};

View File

@@ -113,8 +113,10 @@
base = 1;
else if (obj.className == "function") {
if (window.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
(typeof jQuery == 'function')) base = jQuery();
else if (window._ != null && (obj.string == '_') && (typeof _ == 'function')) base = _();
(typeof window.jQuery == 'function'))
base = window.jQuery();
else if (window._ != null && (obj.string == '_') && (typeof window._ == 'function'))
base = window._();
}
while (base != null && context.length)
base = base[context.pop().string];

View File

@@ -0,0 +1,50 @@
(function() {
if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";
var loading = {};
function splitCallback(cont, n) {
var countDown = n;
return function() { if (--countDown == 0) cont(); }
}
function ensureDeps(mode, cont) {
var deps = CodeMirror.modes[mode].dependencies;
if (!deps) return cont();
var missing = [];
for (var i = 0; i < deps.length; ++i) {
if (!CodeMirror.modes.hasOwnProperty(deps[i]))
missing.push(deps[i]);
}
if (!missing.length) return cont();
var split = splitCallback(cont, missing.length);
for (var i = 0; i < missing.length; ++i)
CodeMirror.requireMode(missing[i], split);
}
CodeMirror.requireMode = function(mode, cont) {
if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont());
if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
var script = document.createElement("script");
script.src = CodeMirror.modeURL.replace(/%N/g, mode);
var others = document.getElementsByTagName("script")[0];
others.parentNode.insertBefore(script, others);
var list = loading[mode] = [cont];
var count = 0, poll = setInterval(function() {
if (++count > 100) return clearInterval(poll);
if (CodeMirror.modes.hasOwnProperty(mode)) {
clearInterval(poll);
loading[mode] = null;
ensureDeps(mode, function() {
for (var i = 0; i < list.length; ++i) list[i]();
});
}
}, 200);
};
CodeMirror.autoLoadMode = function(instance, mode) {
if (!CodeMirror.modes.hasOwnProperty(mode))
CodeMirror.requireMode(mode, function() {
instance.setOption("mode", instance.getOption("mode"));
});
};
}());

View File

@@ -23,7 +23,7 @@
function markDocument(cm, className, minChars) {
clearMarks(cm);
minChars = (typeof minChars !== 'undefined' ? minChars : DEFAULT_MIN_CHARS);
if (cm.somethingSelected() && cm.getSelection().length >= minChars) {
if (cm.somethingSelected() && cm.getSelection().replace(/^\s+|\s+$/g, "").length >= minChars) {
var state = getMatchHighlightState(cm);
var query = cm.getSelection();
cm.operation(function() {

View File

@@ -43,7 +43,7 @@ CodeMirror.overlayParser = function(base, overlay, combine) {
else return state.overlayCur;
},
indent: function(state, textAfter) {
indent: base.indent && function(state, textAfter) {
return base.indent(state.base, textAfter);
},
electricChars: base.electricChars

View File

@@ -72,14 +72,14 @@
query = parseQuery(query);
dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
if (all) {
cm.operation(function() {
cm.compoundChange(function() { cm.operation(function() {
for (var cursor = cm.getSearchCursor(query); cursor.findNext();) {
if (typeof query != "string") {
var match = cm.getRange(cursor.from(), cursor.to()).match(query);
cursor.replace(text.replace(/\$(\d)/, function(w, i) {return match[i];}));
} else cursor.replace(text);
}
});
})});
} else {
clearSearch(cm);
var cursor = cm.getSearchCursor(query, cm.getCursor());

View File

@@ -29,6 +29,10 @@
complete.style.left = pos.x + "px";
complete.style.top = pos.yBot + "px";
document.body.appendChild(complete);
// If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
if(winW - pos.x < sel.clientWidth)
complete.style.left = (pos.x - sel.clientWidth) + "px";
// Hack to hide the scrollbar.
if (completions.length <= 10)
complete.style.width = (sel.clientWidth - 1) + "px";
@@ -53,6 +57,8 @@
else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();}
else if (code != 38 && code != 40) {
close(); editor.focus();
// Pass the event to the CodeMirror instance so that it can handle things like backspace properly.
editor.triggerOnKeyDown(event);
setTimeout(function(){CodeMirror.simpleHint(editor, getHints);}, 50);
}
});

View File

@@ -21,7 +21,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
}
if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
curPunc = ch;
return null
return null;
}
if (/\d/.test(ch)) {
stream.eatWhile(/[\w\.]/);

View File

@@ -96,6 +96,6 @@ void* zmq_thread_init(void* zmq_context, int signal_fd) {
<p><strong>MIME types defined:</strong> <code>text/x-csrc</code>
(C code), <code>text/x-c++src</code> (C++
code), <code>text/x-java</code> (Java
code).</p>
code), <code>text/x-csharp</code> (C#).</p>
</body>
</html>

View File

@@ -92,7 +92,7 @@ CodeMirror.defineMode("css", function(config) {
var style = state.tokenize(stream, state);
var context = state.stack[state.stack.length-1];
if (type == "hash" && context == "rule") style = "atom";
if (type == "hash" && context != "rule") style = "string-2";
else if (style == "variable") {
if (context == "rule") style = "number";
else if (!context || context == "@media{") style = "tag";

View File

@@ -243,7 +243,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function maybeoperator(type, value) {
if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
if (type == "operator") return cont(expression);
if (type == "operator" || type == ":") return cont(expression);
if (type == ";") return;
if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
if (type == ".") return cont(property, maybeoperator);
@@ -319,8 +319,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
kwAllowed: true,
cc: [],
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
localVars: null,
context: null,
localVars: parserConfig.localVars,
context: parserConfig.localVars && {vars: parserConfig.localVars},
indented: 0
};
},
@@ -334,15 +334,16 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (stream.eatSpace()) return null;
var style = state.tokenize(stream, state);
if (type == "comment") return style;
state.reAllowed = type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/);
state.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/));
state.kwAllowed = type != '.';
return parseJS(state, style, type, content, stream);
},
indent: function(state, textAfter) {
if (state.tokenize != jsTokenBase) return 0;
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,
type = lexical.type, closing = firstChar == type;
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
var type = lexical.type, closing = firstChar == type;
if (type == "vardef") return lexical.indented + 4;
else if (type == "form" && firstChar == "{") return lexical.indented;
else if (type == "stat" || type == "form") return lexical.indented + indentUnit;

View File

@@ -143,7 +143,7 @@
electricChars: "/{}:"
}
});
}, "xml", "clike", "javascript", "css");
CodeMirror.defineMIME("application/x-httpd-php", "php");
CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true});
CodeMirror.defineMIME("text/x-php", phpConfig);

View File

@@ -0,0 +1,24 @@
Copyright (c) 2011, Ubalo, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Ubalo, Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL UBALO, INC BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,171 @@
<!doctype html>
<html>
<head>
<title>CodeMirror: Ruby mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="ruby.js"></script>
<style>
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
.cm-s-default span.cm-arrow { color: red; }
</style>
<link rel="stylesheet" href="../../doc/docs.css">
</head>
<body>
<h1>CodeMirror: Ruby mode</h1>
<form><textarea id="code" name="code">
# Code from http://sandbox.mc.edu/~bennet/ruby/code/poly_rb.html
#
# This program evaluates polynomials. It first asks for the coefficients
# of a polynomial, which must be entered on one line, highest-order first.
# It then requests values of x and will compute the value of the poly for
# each x. It will repeatly ask for x values, unless you the user enters
# a blank line. It that case, it will ask for another polynomial. If the
# user types quit for either input, the program immediately exits.
#
#
# Function to evaluate a polynomial at x. The polynomial is given
# as a list of coefficients, from the greatest to the least.
def polyval(x, coef)
sum = 0
coef = coef.clone # Don't want to destroy the original
while true
sum += coef.shift # Add and remove the next coef
break if coef.empty? # If no more, done entirely.
sum *= x # This happens the right number of times.
end
return sum
end
#
# Function to read a line containing a list of integers and return
# them as an array of integers. If the string conversion fails, it
# throws TypeError. If the input line is the word 'quit', then it
# converts it to an end-of-file exception
def readints(prompt)
# Read a line
print prompt
line = readline.chomp
raise EOFError.new if line == 'quit' # You can also use a real EOF.
# Go through each item on the line, converting each one and adding it
# to retval.
retval = [ ]
for str in line.split(/\s+/)
if str =~ /^\-?\d+$/
retval.push(str.to_i)
else
raise TypeError.new
end
end
return retval
end
#
# Take a coeff and an exponent and return the string representation, ignoring
# the sign of the coefficient.
def term_to_str(coef, exp)
ret = ""
# Show coeff, unless it's 1 or at the right
coef = coef.abs
ret = coef.to_s unless coef == 1 && exp > 0
ret += "x" if exp > 0 # x if exponent not 0
ret += "^" + exp.to_s if exp > 1 # ^exponent, if > 1.
return ret
end
#
# Create a string of the polynomial in sort-of-readable form.
def polystr(p)
# Get the exponent of first coefficient, plus 1.
exp = p.length
# Assign exponents to each term, making pairs of coeff and exponent,
# Then get rid of the zero terms.
p = (p.map { |c| exp -= 1; [ c, exp ] }).select { |p| p[0] != 0 }
# If there's nothing left, it's a zero
return "0" if p.empty?
# *** Now p is a non-empty list of [ coef, exponent ] pairs. ***
# Convert the first term, preceded by a "-" if it's negative.
result = (if p[0][0] < 0 then "-" else "" end) + term_to_str(*p[0])
# Convert the rest of the terms, in each case adding the appropriate
# + or - separating them.
for term in p[1...p.length]
# Add the separator then the rep. of the term.
result += (if term[0] < 0 then " - " else " + " end) +
term_to_str(*term)
end
return result
end
#
# Run until some kind of endfile.
begin
# Repeat until an exception or quit gets us out.
while true
# Read a poly until it works. An EOF will except out of the
# program.
print "\n"
begin
poly = readints("Enter a polynomial coefficients: ")
rescue TypeError
print "Try again.\n"
retry
end
break if poly.empty?
# Read and evaluate x values until the user types a blank line.
# Again, an EOF will except out of the pgm.
while true
# Request an integer.
print "Enter x value or blank line: "
x = readline.chomp
break if x == ''
raise EOFError.new if x == 'quit'
# If it looks bad, let's try again.
if x !~ /^\-?\d+$/
print "That doesn't look like an integer. Please try again.\n"
next
end
# Convert to an integer and print the result.
x = x.to_i
print "p(x) = ", polystr(poly), "\n"
print "p(", x, ") = ", polyval(x, poly), "\n"
end
end
rescue EOFError
print "\n=== EOF ===\n"
rescue Interrupt, SignalException
print "\n=== Interrupted ===\n"
else
print "--- Bye ---\n"
end
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: "text/x-ruby",
tabMode: "indent",
matchBrackets: true,
indentUnit: 4
});
</script>
<p><strong>MIME types defined:</strong> <code>text/x-ruby</code>.</p>
<p>Development of the CodeMirror Ruby mode was kindly sponsored
by <a href="http://ubalo.com/">Ubalo</a>, who hold
the <a href="LICENSE">license</a>.</p>
</body>
</html>

View File

@@ -0,0 +1,200 @@
CodeMirror.defineMode("ruby", function(config, parserConfig) {
function wordObj(words) {
var o = {};
for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;
return o;
}
var keywords = wordObj([
"alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined?", "do", "else",
"elsif", "END", "end", "ensure", "false", "for", "if", "in", "module", "next", "not", "or",
"redo", "rescue", "retry", "return", "self", "super", "then", "true", "undef", "unless",
"until", "when", "while", "yield", "nil", "raise", "throw", "catch", "fail", "loop", "callcc",
"caller", "lambda", "proc", "public", "protected", "private", "require", "load",
"require_relative", "extend", "autoload"
]);
var indentWords = wordObj(["def", "class", "case", "for", "while", "do", "module", "then",
"catch", "loop", "proc", "begin"]);
var dedentWords = wordObj(["end", "until"]);
var matching = {"[": "]", "{": "}", "(": ")"};
var curPunc;
function chain(newtok, stream, state) {
state.tokenize.push(newtok);
return newtok(stream, state);
}
function tokenBase(stream, state) {
curPunc = null;
if (stream.sol() && stream.match("=begin") && stream.eol()) {
state.tokenize.push(readBlockComment);
return "comment";
}
if (stream.eatSpace()) return null;
var ch = stream.next();
if (ch == "`" || ch == "'" || ch == '"' ||
(ch == "/" && !stream.eol() && stream.peek() != " ")) {
return chain(readQuoted(ch, "string", ch == '"' || ch == "`"), stream, state);
} else if (ch == "%") {
var style, embed = false;
if (stream.eat("s")) style = "atom";
else if (stream.eat(/[WQ]/)) { style = "string"; embed = true; }
else if (stream.eat(/[wxqr]/)) style = "string";
var delim = stream.eat(/[^\w\s]/);
if (!delim) return "operator";
if (matching.propertyIsEnumerable(delim)) delim = matching[delim];
return chain(readQuoted(delim, style, embed, true), stream, state);
} else if (ch == "#") {
stream.skipToEnd();
return "comment";
} else if (ch == "<" && stream.eat("<")) {
stream.eat("-");
stream.eat(/[\'\"\`]/);
var match = stream.match(/^\w+/);
stream.eat(/[\'\"\`]/);
if (match) return chain(readHereDoc(match[0]), stream, state);
return null;
} else if (ch == "0") {
if (stream.eat("x")) stream.eatWhile(/[\da-fA-F]/);
else if (stream.eat("b")) stream.eatWhile(/[01]/);
else stream.eatWhile(/[0-7]/);
return "number";
} else if (/\d/.test(ch)) {
stream.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+\-]?[\d_]+)?/);
return "number";
} else if (ch == "?") {
while (stream.match(/^\\[CM]-/)) {}
if (stream.eat("\\")) stream.eatWhile(/\w/);
else stream.next();
return "string";
} else if (ch == ":") {
if (stream.eat("'")) return chain(readQuoted("'", "atom", false), stream, state);
if (stream.eat('"')) return chain(readQuoted('"', "atom", true), stream, state);
stream.eatWhile(/[\w\?]/);
return "atom";
} else if (ch == "@") {
stream.eat("@");
stream.eatWhile(/[\w\?]/);
return "variable-2";
} else if (ch == "$") {
stream.next();
stream.eatWhile(/[\w\?]/);
return "variable-3";
} else if (/\w/.test(ch)) {
stream.eatWhile(/[\w\?]/);
if (stream.eat(":")) return "atom";
return "ident";
} else if (ch == "|" && (state.varList || state.lastTok == "{" || state.lastTok == "do")) {
curPunc = "|";
return null;
} else if (/[\(\)\[\]{}\\;]/.test(ch)) {
curPunc = ch;
return null;
} else if (ch == "-" && stream.eat(">")) {
return "arrow";
} else if (/[=+\-\/*:\.^%<>~|]/.test(ch)) {
stream.eatWhile(/[=+\-\/*:\.^%<>~|]/);
return "operator";
} else {
return null;
}
}
function tokenBaseUntilBrace() {
var depth = 1;
return function(stream, state) {
if (stream.peek() == "}") {
depth--;
if (depth == 0) {
state.tokenize.pop();
return state.tokenize[state.tokenize.length-1](stream, state);
}
} else if (stream.peek() == "{") {
depth++;
}
return tokenBase(stream, state);
};
}
function readQuoted(quote, style, embed, unescaped) {
return function(stream, state) {
var escaped = false, ch;
while ((ch = stream.next()) != null) {
if (ch == quote && (unescaped || !escaped)) {
state.tokenize.pop();
break;
}
if (embed && ch == "#" && !escaped && stream.eat("{")) {
state.tokenize.push(tokenBaseUntilBrace(arguments.callee));
break;
}
escaped = !escaped && ch == "\\";
}
return style;
};
}
function readHereDoc(phrase) {
return function(stream, state) {
if (stream.match(phrase)) state.tokenize.pop();
else stream.skipToEnd();
return "string";
};
}
function readBlockComment(stream, state) {
if (stream.sol() && stream.match("=end") && stream.eol())
state.tokenize.pop();
stream.skipToEnd();
return "comment";
}
return {
startState: function() {
return {tokenize: [tokenBase],
indented: 0,
context: {type: "top", indented: -config.indentUnit},
continuedLine: false,
lastTok: null,
varList: false};
},
token: function(stream, state) {
if (stream.sol()) state.indented = stream.indentation();
var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype;
if (style == "ident") {
var word = stream.current();
style = keywords.propertyIsEnumerable(stream.current()) ? "keyword"
: /^[A-Z]/.test(word) ? "tag"
: (state.lastTok == "def" || state.lastTok == "class" || state.varList) ? "def"
: "variable";
if (indentWords.propertyIsEnumerable(word)) kwtype = "indent";
else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent";
else if ((word == "if" || word == "unless") && stream.column() == stream.indentation())
kwtype = "indent";
}
if (curPunc || (style && style != "comment")) state.lastTok = word || curPunc || style;
if (curPunc == "|") state.varList = !state.varList;
if (kwtype == "indent" || /[\(\[\{]/.test(curPunc))
state.context = {prev: state.context, type: curPunc || style, indented: state.indented};
else if ((kwtype == "dedent" || /[\)\]\}]/.test(curPunc)) && state.context.prev)
state.context = state.context.prev;
if (stream.eol())
state.continuedLine = (curPunc == "\\" || style == "operator");
return style;
},
indent: function(state, textAfter) {
if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0;
var firstChar = textAfter && textAfter.charAt(0);
var ct = state.context;
var closing = ct.type == matching[firstChar] ||
ct.type == "keyword" && /^(?:end|until|else|elsif|when|rescue)\b/.test(textAfter);
return ct.indented + (closing ? 0 : config.indentUnit) +
(state.continuedLine ? config.indentUnit : 0);
},
electricChars: "}de" // enD and rescuE
};
});
CodeMirror.defineMIME("text/x-ruby", "ruby");

View File

@@ -1,12 +1,44 @@
CodeMirror.defineMode("xml", function(config, parserConfig) {
var indentUnit = config.indentUnit;
var Kludges = parserConfig.htmlMode ? {
autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true,
"meta": true, "col": true, "frame": true, "base": true, "area": true},
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
'track': true, 'wbr': true},
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
'th': true, 'tr': true},
contextGrabbers: {
'dd': {'dd': true, 'dt': true},
'dt': {'dd': true, 'dt': true},
'li': {'li': true},
'option': {'option': true, 'optgroup': true},
'optgroup': {'optgroup': true},
'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
'rp': {'rp': true, 'rt': true},
'rt': {'rp': true, 'rt': true},
'tbody': {'tbody': true, 'tfoot': true},
'td': {'td': true, 'th': true},
'tfoot': {'tbody': true},
'th': {'td': true, 'th': true},
'thead': {'tbody': true, 'tfoot': true},
'tr': {'tr': true}
},
doNotIndent: {"pre": true},
allowUnquoted: true,
allowMissing: false
} : {autoSelfClosers: {}, doNotIndent: {}, allowUnquoted: false, allowMissing: false};
} : {
autoSelfClosers: {},
implicitlyClosed: {},
contextGrabbers: {},
doNotIndent: {},
allowUnquoted: false,
allowMissing: false
};
var alignCDATA = parserConfig.alignCDATA;
// Return variables for tokenizers
@@ -162,7 +194,12 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
} else if (type == "closeTag") {
var err = false;
if (curState.context) {
err = curState.context.tagName != tagName;
if (curState.context.tagName != tagName) {
if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {
popContext();
}
err = !curState.context || curState.context.tagName != tagName;
}
} else {
err = true;
}
@@ -174,9 +211,15 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
function endtag(startOfLine) {
return function(type) {
if (type == "selfcloseTag" ||
(type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase())))
(type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) {
maybePopContext(curState.tagName.toLowerCase());
return cont();
if (type == "endTag") {pushContext(curState.tagName, startOfLine); return cont();}
}
if (type == "endTag") {
maybePopContext(curState.tagName.toLowerCase());
pushContext(curState.tagName, startOfLine);
return cont();
}
return cont();
};
}
@@ -188,6 +231,20 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
return cont(arguments.callee);
}
}
function maybePopContext(nextTagName) {
var parentTagName;
while (true) {
if (!curState.context) {
return;
}
parentTagName = curState.context.tagName.toLowerCase();
if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
return;
}
popContext();
}
}
function attributes(type) {
if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}
@@ -264,4 +321,5 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
});
CodeMirror.defineMIME("application/xml", "xml");
CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,25 @@
/* Port of TextMate's Blackboard theme */
.cm-s-blackboard { background: #0C1021; color: #F8F8F8; }
.cm-s-blackboard .CodeMirror-selected { background: #253B76 !important; }
.cm-s-blackboard .CodeMirror-gutter { background: #0C1021; border-right: 0; }
.cm-s-blackboard .CodeMirror-gutter-text { color: #888; }
.cm-s-blackboard .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; }
.cm-s-blackboard .cm-keyword { color: #FBDE2D; }
.cm-s-blackboard .cm-atom { color: #D8FA3C; }
.cm-s-blackboard .cm-number { color: #D8FA3C; }
.cm-s-blackboard .cm-def { color: #8DA6CE; }
.cm-s-blackboard .cm-variable { color: #FF6400; }
.cm-s-blackboard .cm-operator { color: #FBDE2D;}
.cm-s-blackboard .cm-comment { color: #AEAEAE; }
.cm-s-blackboard .cm-string { color: #61CE3C; }
.cm-s-blackboard .cm-string-2 { color: #61CE3C; }
.cm-s-blackboard .cm-meta { color: #D8FA3C; }
.cm-s-blackboard .cm-error { background: #9D1E15; color: #F8F8F8; }
.cm-s-blackboard .cm-builtin { color: #8DA6CE; }
.cm-s-blackboard .cm-tag { color: #8DA6CE; }
.cm-s-blackboard .cm-attribute { color: #8DA6CE; }
.cm-s-blackboard .cm-header { color: #FF6400; }
.cm-s-blackboard .cm-hr { color: #AEAEAE; }
.cm-s-blackboard .cm-link { color: #8DA6CE; }

View File

@@ -0,0 +1,18 @@
.cm-s-cobalt { background: #002240; color: white; }
.cm-s-cobalt div.CodeMirror-selected { background: #b36539 !important; }
.cm-s-cobalt .CodeMirror-gutter { background: #002240; border-right: 1px solid #aaa; }
.cm-s-cobalt .CodeMirror-gutter-text { color: #d0d0d0; }
.cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-cobalt span.cm-comment { color: #08f; }
.cm-s-cobalt span.cm-atom { color: #845dc4; }
.cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; }
.cm-s-cobalt span.cm-keyword { color: #ffee80; }
.cm-s-cobalt span.cm-string { color: #3ad900; }
.cm-s-cobalt span.cm-meta { color: #ff9d00; }
.cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; }
.cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; }
.cm-s-cobalt span.cm-error { color: #9d1e15; }
.cm-s-cobalt span.cm-bracket { color: #d8d8d8; }
.cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; }
.cm-s-cobalt span.cm-link { color: #845dc4; }

View File

@@ -0,0 +1,25 @@
.cm-s-eclipse span.cm-meta {color: #FF1717;}
.cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; }
.cm-s-eclipse span.cm-atom {color: #219;}
.cm-s-eclipse span.cm-number {color: #164;}
.cm-s-eclipse span.cm-def {color: #00f;}
.cm-s-eclipse span.cm-variable {color: black;}
.cm-s-eclipse span.cm-variable-2 {color: #0000C0;}
.cm-s-eclipse span.cm-variable-3 {color: #0000C0;}
.cm-s-eclipse span.cm-property {color: black;}
.cm-s-eclipse span.cm-operator {color: black;}
.cm-s-eclipse span.cm-comment {color: #3F7F5F;}
.cm-s-eclipse span.cm-string {color: #2A00FF;}
.cm-s-eclipse span.cm-string-2 {color: #f50;}
.cm-s-eclipse span.cm-error {color: #f00;}
.cm-s-eclipse span.cm-qualifier {color: #555;}
.cm-s-eclipse span.cm-builtin {color: #30a;}
.cm-s-eclipse span.cm-bracket {color: #cc7;}
.cm-s-eclipse span.cm-tag {color: #170;}
.cm-s-eclipse span.cm-attribute {color: #00c;}
.cm-s-eclipse span.cm-link {color: #219;}
.cm-s-eclipse .CodeMirror-matchingbracket {
border:1px solid grey;
color:black !important;;
}

View File

@@ -0,0 +1,10 @@
.cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom {color: #762;}
.cm-s-elegant span.cm-comment {color: #262; font-style: italic; line-height: 1em;}
.cm-s-elegant span.cm-meta {color: #555; font-style: italic; line-height: 1em;}
.cm-s-elegant span.cm-variable {color: black;}
.cm-s-elegant span.cm-variable-2 {color: #b11;}
.cm-s-elegant span.cm-qualifier {color: #555;}
.cm-s-elegant span.cm-keyword {color: #730;}
.cm-s-elegant span.cm-builtin {color: #30a;}
.cm-s-elegant span.cm-error {background-color: #fdd;}
.cm-s-elegant span.cm-link {color: #762;}

View File

@@ -0,0 +1,45 @@
/*
http://lesscss.org/ dark theme
Ported to CodeMirror by Peter Kroon
*/
.CodeMirror{
line-height: 15px;
}
.cm-s-lesser-dark {
font-family: 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Monaco', Courier, monospace !important;
font-size:12px;
}
.cm-s-lesser-dark { background: #262626; color: #EBEFE7; text-shadow: 0 -1px 1px #262626; }
.cm-s-lesser-dark div.CodeMirror-selected {background: #45443B !important;} /* 33322B*/
.cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-lesser-dark .CodeMirror-lines { margin-left:3px; margin-right:3px; }/*editable code holder*/
div.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/
.cm-s-lesser-dark .CodeMirror-gutter { background: #262626; border-right:1px solid #aaa; padding-right:3px; min-width:2.5em; }
.cm-s-lesser-dark .CodeMirror-gutter-text { color: #777; }
.cm-s-lesser-dark span.cm-keyword { color: #599eff; }
.cm-s-lesser-dark span.cm-atom { color: #C2B470; }
.cm-s-lesser-dark span.cm-number { color: #B35E4D; }
.cm-s-lesser-dark span.cm-def {color: white;}
.cm-s-lesser-dark span.cm-variable { color:#D9BF8C; }
.cm-s-lesser-dark span.cm-variable-2 { color: #669199; }
.cm-s-lesser-dark span.cm-variable-3 { color: white; }
.cm-s-lesser-dark span.cm-property {color: #92A75C;}
.cm-s-lesser-dark span.cm-operator {color: #92A75C;}
.cm-s-lesser-dark span.cm-comment { color: #666; }
.cm-s-lesser-dark span.cm-string { color: #BCD279; }
.cm-s-lesser-dark span.cm-string-2 {color: #f50;}
.cm-s-lesser-dark span.cm-meta { color: #738C73; }
.cm-s-lesser-dark span.cm-error { color: #9d1e15; }
.cm-s-lesser-dark span.cm-qualifier {color: #555;}
.cm-s-lesser-dark span.cm-builtin { color: #ff9e59; }
.cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; }
.cm-s-lesser-dark span.cm-tag { color: #669199; }
.cm-s-lesser-dark span.cm-attribute {color: #00c;}
.cm-s-lesser-dark span.cm-header {color: #a0a;}
.cm-s-lesser-dark span.cm-quote {color: #090;}
.cm-s-lesser-dark span.cm-hr {color: #999;}
.cm-s-lesser-dark span.cm-link {color: #00c;}

View File

@@ -0,0 +1,28 @@
/* Based on Sublime Text's Monokai theme */
.cm-s-monokai {background: #272822; color: #f8f8f2;}
.cm-s-monokai div.CodeMirror-selected {background: #49483E !important;}
.cm-s-monokai .CodeMirror-gutter {background: #272822; border-right: 0px;}
.cm-s-monokai .CodeMirror-gutter-text {color: #d0d0d0;}
.cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;}
.cm-s-monokai span.cm-comment {color: #75715e;}
.cm-s-monokai span.cm-atom {color: #ae81ff;}
.cm-s-monokai span.cm-number {color: #ae81ff;}
.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;}
.cm-s-monokai span.cm-keyword {color: #f92672;}
.cm-s-monokai span.cm-string {color: #e6db74;}
.cm-s-monokai span.cm-variable {color: #a6e22e;}
.cm-s-monokai span.cm-variable-2 {color: #9effff;}
.cm-s-monokai span.cm-def {color: #fd971f;}
.cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;}
.cm-s-monokai span.cm-bracket {color: #f8f8f2;}
.cm-s-monokai span.cm-tag {color: #f92672;}
.cm-s-monokai span.cm-link {color: #ae81ff;}
.cm-s-monokai .CodeMirror-matchingbracket {
text-decoration: underline;
color: white !important;
}

View File

@@ -0,0 +1,9 @@
.cm-s-neat span.cm-comment { color: #a86; }
.cm-s-neat span.cm-keyword { line-height: 1em; font-weight: bold; color: blue; }
.cm-s-neat span.cm-string { color: #a22; }
.cm-s-neat span.cm-builtin { line-height: 1em; font-weight: bold; color: #077; }
.cm-s-neat span.cm-special { line-height: 1em; font-weight: bold; color: #0aa; }
.cm-s-neat span.cm-variable { color: black; }
.cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; }
.cm-s-neat span.cm-meta {color: #555;}
.cm-s-neat span.cm-link { color: #3a3; }

View File

@@ -0,0 +1,21 @@
/* Loosely based on the Midnight Textmate theme */
.cm-s-night { background: #0a001f; color: #f8f8f8; }
.cm-s-night div.CodeMirror-selected { background: #a8f !important; }
.cm-s-night .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; }
.cm-s-night .CodeMirror-gutter-text { color: #f8f8f8; }
.cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-night span.cm-comment { color: #6900a1; }
.cm-s-night span.cm-atom { color: #845dc4; }
.cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; }
.cm-s-night span.cm-keyword { color: #599eff; }
.cm-s-night span.cm-string { color: #37f14a; }
.cm-s-night span.cm-meta { color: #7678e2; }
.cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; }
.cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; }
.cm-s-night span.cm-error { color: #9d1e15; }
.cm-s-night span.cm-bracket { color: #8da6ce; }
.cm-s-night span.cm-comment { color: #6900a1; }
.cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; }
.cm-s-night span.cm-link { color: #845dc4; }

View File

@@ -0,0 +1,21 @@
.cm-s-rubyblue { font:13px/1.4em Trebuchet, Verdana, sans-serif; } /* - customized editor font - */
.cm-s-rubyblue { background: #112435; color: white; }
.cm-s-rubyblue div.CodeMirror-selected { background: #38566F !important; }
.cm-s-rubyblue .CodeMirror-gutter { background: #1F4661; border-right: 7px solid #3E7087; min-width:2.5em; }
.cm-s-rubyblue .CodeMirror-gutter-text { color: white; }
.cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-rubyblue span.cm-comment { color: #999; font-style:italic; line-height: 1em; }
.cm-s-rubyblue span.cm-atom { color: #F4C20B; }
.cm-s-rubyblue span.cm-number, .cm-s-rubyblue span.cm-attribute { color: #82C6E0; }
.cm-s-rubyblue span.cm-keyword { color: #F0F; }
.cm-s-rubyblue span.cm-string { color: #F08047; }
.cm-s-rubyblue span.cm-meta { color: #F0F; }
.cm-s-rubyblue span.cm-variable-2, .cm-s-rubyblue span.cm-tag { color: #7BD827; }
.cm-s-rubyblue span.cm-variable-3, .cm-s-rubyblue span.cm-def { color: white; }
.cm-s-rubyblue span.cm-error { color: #AF2018; }
.cm-s-rubyblue span.cm-bracket { color: #F0F; }
.cm-s-rubyblue span.cm-link { color: #F4C20B; }
.cm-s-rubyblue span.CodeMirror-matchingbracket { color:#F0F !important; }
.cm-s-rubyblue span.cm-builtin, .cm-s-rubyblue span.cm-special { color: #FF9D00; }

View File

@@ -0,0 +1,46 @@
/*
Copyright (C) 2011 by MarkLogic Corporation
Author: Mike Brevoort <mike@brevoort.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
.cm-s-xq-dark { background: #0a001f; color: #f8f8f8; }
.cm-s-xq-dark span.CodeMirror-selected { background: #a8f !important; }
.cm-s-xq-dark .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; }
.cm-s-xq-dark .CodeMirror-gutter-text { color: #f8f8f8; }
.cm-s-xq-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-xq-dark span.cm-keyword {color: #FFBD40;}
.cm-s-xq-dark span.cm-atom {color: #6C8CD5;}
.cm-s-xq-dark span.cm-number {color: #164;}
.cm-s-xq-dark span.cm-def {color: #FFF; text-decoration:underline;}
.cm-s-xq-dark span.cm-variable {color: #FFF;}
.cm-s-xq-dark span.cm-variable-2 {color: #EEE;}
.cm-s-xq-dark span.cm-variable-3 {color: #DDD;}
.cm-s-xq-dark span.cm-property {}
.cm-s-xq-dark span.cm-operator {}
.cm-s-xq-dark span.cm-comment {color: gray;}
.cm-s-xq-dark span.cm-string {color: #9FEE00;}
.cm-s-xq-dark span.cm-meta {color: yellow;}
.cm-s-xq-dark span.cm-error {color: #f00;}
.cm-s-xq-dark span.cm-qualifier {color: #FFF700;}
.cm-s-xq-dark span.cm-builtin {color: #30a;}
.cm-s-xq-dark span.cm-bracket {color: #cc7;}
.cm-s-xq-dark span.cm-tag {color: #FFBD40;}
.cm-s-xq-dark span.cm-attribute {color: #FFF700;}

View File

@@ -1,27 +1,66 @@
ICE coder :: Matt Pass
#ICEcoder
##Web based IDE for smart web development
Demo: http://www.mattpass.com/_coder
Early version of the web based IDE which allows for creation of websites in the web browser. Uses the brilliant CodeMirror for code highlighting & editing, with a slick IDE wrapped around it to make the whole thing work.
Early version of the web based IDE which allows for creation of websites in the web browser.
###Features you'd expect
* Context aware code highlighting
* Supports HTML, CSS, JavaScript, PHP & Ruby
* Smart tab key system (selected text indents line)
* File manager
* Find & replace/replace all
* Document tabs indicate current doc & changes made
* Code folding
* Open last files on load
* Web based, access from anywhere
* Free, open source & customisable
Uses the brilliant CodeMirror plus some other PHP & JS code to deal with file handling and make the whole thing work. Also has the extra plugin 'Adminer' for DB management.
###Cool features you wouldn't expect
* Find & replace in current doc, open docs, files & filenames
* Found match & current position counter
* Indicates content type cursor is on
* Account login to keep certain files secure
* Restrict files, ban files and restrict by IP
* Settings to change functionality & editor theme
* Code Assist system
* Displays nest position of text cursor, hover to select, click to set cursor
* Nest structure OK/broken indicator
* Highlight word and press CTRL+I to Google search that
* Adds end tags as you type and in a context aware way
* Can rename open files (whoaah!)
* CTRL+Enter open current webpage in new tab
* CTRL+S+Enter opens a sticky tab to show live edits
* ESC = Comment/Uncomment line, incl partial lines
* Image viewer
* Colour preview block on CSS colours, ie red, #ff0000 or RGBA(255,0,0,0.5)
* MySQL Database management via Adminer plugin
* Backs up files every 10 mins or on click of backup plugin icon
###Installation
####Step 1: Clone the repo
```
$ git clone git@github:mattpass/ICEcoder
```
####Step 2: Upload all the files
```
Linux or Windows hosting OK
Upload to a new sub-dir URL such as yourdomain.com/_coder
Set public write permissions on the lib/settings.php file
```
####Step 3: Start coding
```
Visit the sub-dir URL in your browser and enter a password
Now you're setup, auto-logged in too and ready to code
```
Suitable for commercial & non-commercial projects, just let me know if it's useful to you and any cool customisations you make to it. I take no responsibility for anything, your usage is all down to you.
Is fully open source and I'd encourage you to take it, make it your own and customise to your hearts content! :)
Suitable for commercial & non-commercial projects, just let me know if it's useful to you and any cool customisations you make to it.
Please feel free to assist with the development of this and maybe in time we can produce a fantastic web based IDE for web devs.
INSTALLATION
1.Open /lib/settings.php and adjust variables to suit
2.Upload all the files to a Linux or Windows host under a new sub-dir URL such as yourdomain.com/_coder. Set public write permissions on the settings.php file
3.Visit this URL in your browser and set a password
4.Now you have top level access and can save (CTRL+S), delete (DEL) etc
Plenty of comments included in the code to assist with understanding.
Plenty of comments included in the code to assist with understanding, customising etc.
Comments, improvements & feedback welcomed!

View File

@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html>
<html style="margin: 0px">
<head>
<title>CodeMirror 2: ICE Coders Editor of Choice</title>
<?php include("lib/settings.php");?>
@@ -11,24 +11,40 @@
<script src="<?php echo $codeMirrorDir; ?>/mode/css/css.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/clike/clike.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/php/php.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/ruby/ruby.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/lib/util/searchcursor.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/lib/util/match-highlighter.js"></script>
<link rel="stylesheet" href="lib/editor.css">
<script src="<?php echo $codeMirrorDir; ?>/lib/util/foldcode.js"></script>
<?php
if ($theme=="default") {
echo '<link rel="stylesheet" href="lib/editor.css">';
} else {
echo '<link rel="stylesheet" href="'.$codeMirrorDir.'/theme/'.$theme.'.css">';
}
?>
<style type="text/css">
.CodeMirror {position: absolute; width: 0px; background-color: #ffffff}
.CodeMirror-scroll {width: 100px; height: 100px;}
.cm-s-visible {display: block; top: 0px}
.cm-s-hidden {display: none; top: 4000px}
.cm-s-activeLine {background: #002 !important;}
// Make sure this next one remains the 5th item, updated with JS
.cm-tab:after {position: relative; display: inline-block; width: 0px; left: -1.4em; overflow: visible; color: #aaa; content: "<?php if ($visibleTabs) {?>\21e5<?;};?>";}
span.CodeMirror-matchhighlight {background: #555555}
.CodeMirror-focused span.CodeMirror-matchhighlight {color: #000000; background: #555555; !important}
</style>
</head>
<body onKeyDown="return top.ICEcoder.interceptKeys('content', event);" onKeyUp="top.ICEcoder.resetKeys(event);">
<body style="margin: 0px" onKeyDown="return top.ICEcoder.interceptKeys('content', event);" onKeyUp="top.ICEcoder.resetKeys(event);">
<script>
function createNewCMInstance(num) {window['cM'+num] = CodeMirror(document.body, {
function createNewCMInstance(num) {
var fileName = top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1];
var codeFold = CodeMirror.newFoldFunction(CodeMirror.tagRangeFinder,'<span style=\"display: inline-block; width: 13px; height: 13px; background-color: #bb0000; color: #ffffff; text-align: center; cursor: pointer\"><span style="position: relative; top: -1px">+</span></span> %N%');
var codeFold_JS_PHP_Ruby = CodeMirror.newFoldFunction(CodeMirror.braceRangeFinder,'<span style=\"display: inline-block; width: 13px; height: 13px; background-color: #bb0000; color: #ffffff; text-align: center; cursor: pointer\"><span style="position: relative; top: -1px">+</span></span> %N%');
window['cM'+num] = CodeMirror(document.body, {
mode: "application/x-httpd-php",
theme: "icecoder",
lineNumbers: true,
lineWrapping: true,
indentUnit: 4,
@@ -52,6 +68,7 @@ function createNewCMInstance(num) {window['cM'+num] = CodeMirror(document.body,
top.ICEcoder.redoTabHighlight(top.ICEcoder.selectedTab);
}
top.ICEcoder.getCaretPosition();
top.ICEcoder.dontUpdateNest = false;
top.ICEcoder.updateCharDisplay();
top.ICEcoder.updateNestingIndicator();
if (top.ICEcoder.findMode) {
@@ -62,7 +79,7 @@ function createNewCMInstance(num) {window['cM'+num] = CodeMirror(document.body,
},
onKeyEvent: function(instance, e) {
top.ICEcoder.redoChangedContent(event);
top.ICEcoder.findReplace('find',true);
top.ICEcoder.findReplace('find',true,false);
top.ICEcoder.getCaretPosition();
top.ICEcoder.updateCharDisplay();
tok = window['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].getTokenAt(window['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].getCursor());
@@ -74,7 +91,9 @@ function createNewCMInstance(num) {window['cM'+num] = CodeMirror(document.body,
canDoEndTag=false;
}
}
fileName = top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1];
if(top.ICEcoder.tagString.slice(0,1)=="/"||top.ICEcoder.tagString.slice(0,1)=="?") {
canDoEndTag=false;
}
if (!top.ICEcoder.codeAssist||fileName.indexOf(".js")>0||fileName.indexOf(".css")>0) {
canDoEndTag=false;
}
@@ -86,7 +105,8 @@ function createNewCMInstance(num) {window['cM'+num] = CodeMirror(document.body,
for (i=0;i<numTabs-1;i++) {
tabs += "\t";
}
endTag = "</" + top.ICEcoder.htmlTagArray[top.ICEcoder.htmlTagArray.length-1] + ">";
//endTag = "</" + top.ICEcoder.htmlTagArray[top.ICEcoder.htmlTagArray.length-1] + ">";
endTag = "</" + top.ICEcoder.tagString + ">";
if (top.ICEcoder.tagString=="script") {endTag="</"+"script>"};
if(top.ICEcoder.tagString=="title"||top.ICEcoder.tagString=="a"||top.ICEcoder.tagString=="li"||top.ICEcoder.tagString=="span"||(top.ICEcoder.tagString.slice(0,1)=="h"&&parseInt(top.ICEcoder.tagString.slice(1,2),10)>=1&&parseInt(top.ICEcoder.tagString.slice(1,2),10)<=7)) {
window['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].replaceSelection(endTag);
@@ -102,25 +122,17 @@ function createNewCMInstance(num) {window['cM'+num] = CodeMirror(document.body,
};
lastKeyCode = e.keyCode;
},
extraKeys: {"Enter": false}
});
onGutterClick: !fileName || (fileName && fileName.indexOf(".js") == -1 && fileName.indexOf(".php") && fileName.indexOf(".rb") == -1) ? codeFold : codeFold_JS_PHP_Ruby,
extraKeys: {
"Tab": function(cm) {CodeMirror.commands[top.tabsIndent ? "defaultTab" : "insertTab"](cm);},
"Shift-Tab": "indentLess"
}
});
// Now create the active line for this CodeMirror object
top.ICEcoder['cMActiveLine'+top.ICEcoder.selectedTab] = window['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].setLineClass(0, "cm-s-activeLine");
// Now create the active line for this CodeMirror object
top.ICEcoder['cMActiveLine'+top.ICEcoder.selectedTab] = window['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].setLineClass(0, "cm-s-activeLine");
};
<?php
//for ($i=1;$i<=10;$i++) {
?>
//cM<?php echo $i;?>.getWrapperElement().getElementsByClassName("CodeMirror-lines")[0].addEventListener("click", function(){
// if (top.ICEcoder.results && top.ICEcoder.results.length>0) {
// top.document.getElementById('results').innerHTML = top.ICEcoder.results.length + " results";
// }
// top.ICEcoder.findMode = false;
//}, false);
<?php
//;};
?>
</script>
</body>

View File

@@ -95,7 +95,7 @@ function fileManager_dir($directory, $return_link, $first_call=true) {
$fileManager .= fileManager_dir("$directory/$this_file", $return_link , false);
$fileManager .= "</li>";
} else {
$fileManager .= "<li class=\"pft-directory\" style=\"cursor: default\"><span style=\"position: relative; left:-22px; color: #888888\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [HIDDEN] ".$fileAtts."</span></li>";
$fileManager .= "<li class=\"pft-directory\" style=\"cursor: pointer\"><span style=\"position: relative; left:-22px; color: #888888\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [HIDDEN] ".$fileAtts."</span></li>";
}
} else {
// File
@@ -117,7 +117,7 @@ function fileManager_dir($directory, $return_link, $first_call=true) {
$chmodInfo = substr(sprintf('%o', fileperms($link)), -4);
$fileAtts = '<span style="color: #888888; font-size: 8px">'.$chmodInfo.'</span>';
}
$fileManager .= "<li class=\"pft-file " . strtolower($ext) . "\"><a nohref onMouseOver=\"top.ICEcoder.overFileFolder('file','$link')\" onMouseOut=\"top.ICEcoder.overFileFolder('file','')\" style=\"position: relative; left:-22px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span id=\"".str_replace("/","|",str_replace($docRoot,"",$link))."\">" . htmlspecialchars($this_file) . "</span> ".$fileAtts."</a></li>";
$fileManager .= "<li class=\"pft-file " . strtolower($ext) . "\"><a nohref onMouseOver=\"top.ICEcoder.overFileFolder('file','$link')\" onMouseOut=\"top.ICEcoder.overFileFolder('file','')\" style=\"position: relative; left:-22px; cursor: pointer\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span id=\"".str_replace("/","|",str_replace($docRoot,"",$link))."\">" . htmlspecialchars($this_file) . "</span> ".$fileAtts."</a></li>";
} else {
$fileAtts = "<img src=\"images/file-manager-icons/padlock.png\" style=\"cursor: pointer\" onClick=\"alert('Sorry, you need higher admin level rights to view.')\">";
$fileManager .= "<li class=\"pft-file " . strtolower($ext) . "\" style=\"cursor: default\"><span style=\"position: relative; left:-22px; color: #888888\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [HIDDEN] ".$fileAtts."</span></li>";
@@ -142,14 +142,15 @@ function php4_scandir($dir) {
?>
<!DOCTYPE html>
<html onMouseDown="top.ICEcoder.mouseDown=true" onMouseUp="top.ICEcoder.mouseDown=false" onMouseMove="top.ICEcoder.getMouseXY(event);top.ICEcoder.canResizeFilesW()" onContextMenu="top.ICEcoder.rightClickedFile=top.ICEcoder.thisFileFolderLink; top.ICEcoder.selectFileFolder(); return top.ICEcoder.showMenu()" onClick="top.document.getElementById('fileMenu').style.display='none'">
<html onMouseDown="top.ICEcoder.mouseDown=true" onMouseUp="top.ICEcoder.mouseDown=false" onMouseMove="top.ICEcoder.getMouseXY(event);top.ICEcoder.canResizeFilesW()" onContextMenu="top.ICEcoder.rightClickedFile=top.ICEcoder.thisFileFolderLink; return top.ICEcoder.showMenu()" onClick="top.ICEcoder.selectFileFolder()">
<head>
<title>ICE Coder File Manager</title>
<link rel="stylesheet" type="text/css" href="lib/files.css">
<script src="lib/coder.js" type="text/javascript"></script>
</head>
<body onLoad="top.ICEcoder.fileManager()" onClick="top.ICEcoder.selectFileFolder()" onDblClick="top.ICEcoder.openFile()" onKeyDown="return top.ICEcoder.interceptKeys('files', event);" onKeyUp="top.ICEcoder.resetKeys(event);">
<body onLoad="top.ICEcoder.fileManager()" onDblClick="top.ICEcoder.openFile()" onKeyDown="return top.ICEcoder.interceptKeys('files', event);" onKeyUp="top.ICEcoder.resetKeys(event);">
<div onClick="top.ICEcoder.refreshFileManager()" class="refresh"><img src="images/file-manager-icons/refresh.png"></div>
<?php
echo fileManager($_SERVER['DOCUMENT_ROOT'], "[link]");
?>

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

BIN
images/delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 B

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 618 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 537 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 651 B

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 734 B

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 668 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 447 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 538 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 856 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 626 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 859 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 B

After

Width:  |  Height:  |  Size: 56 B

BIN
images/new-file.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

BIN
images/new-folder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
images/open.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
images/rename.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

BIN
images/save.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
images/view.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

View File

@@ -1,8 +1,8 @@
<?php
include("lib/settings.php");
$allowedIP = false;
for($i=0;$i<count($allowedIPs);$i++) {
if ($allowedIPs[$i]==$_SERVER["REMOTE_ADDR"]||$allowedIPs[$i]=="*") {
for($i=0;$i<count($_SESSION['allowedIPs']);$i++) {
if ($_SESSION['allowedIPs'][$i]==$_SERVER["REMOTE_ADDR"]||$_SESSION['allowedIPs'][$i]=="*") {
$allowedIP = true;
}
}
@@ -27,22 +27,35 @@ if ($testcMVersion) {
<link rel="stylesheet" type="text/css" href="lib/coder.css">
<script>
shortURLStarts = "<?php echo $shortURLStarts;?>";
theme = "<?php if ($theme=="default") {echo 'icecoder';} else {echo $theme;};?>";
tabsIndent = <?php if ($tabsIndent) {echo 'true';} else {echo 'false';};?>;
<?
$docRoot = str_replace("\\","/",$_SERVER['DOCUMENT_ROOT']);
if (strrpos($docRoot,"/")==strlen($docRoot)-1) {$docRoot = substr($docRoot,0,strlen($docRoot)-1);};
echo 'fullPath = "'.$docRoot.'";'.PHP_EOL;
?>
window.onbeforeunload = function() {
for (var i=0; i<=top.ICEcoder.changedContent.length; i++) {
if (top.ICEcoder.changedContent[i]==1) {
return "You have some unsaved changes.";
}
}
}
lastOpenFiles = [<?php
if ($lastOpenedFiles!="" && $_SESSION['userLevel'] == 10) {
$openFilesArray = explode(",",$lastOpenedFiles);
for ($i=0;$i<count($openFilesArray);$i++) {
echo "'".$openFilesArray[$i]."'";
if ($i<count($openFilesArray)-1) {echo ",";};
}
}
?>];
</script>
<script language="JavaScript" src="lib/coder.js"></script>
</head><?php
$onLoadExtras = "";
for ($i=0;$i<count($plugins);$i++) {
if ($plugins[$i][5]!="") {
$onLoadExtras .= ";ICEcoder.startPluginIntervals('".$plugins[$i][3]."','".$plugins[$i][4]."','".$plugins[$i][5]."')";
};
};
?>
<body onLoad="ICEcoder.init()<?php echo $onLoadExtras;?>" onResize="ICEcoder.setLayout()" onMouseMove="top.ICEcoder.getMouseXY(event);top.ICEcoder.canResizeFilesW()" onMouseDown="top.ICEcoder.mouseDown=true" onMouseUp="top.ICEcoder.mouseDown=false" onKeyDown="return ICEcoder.interceptKeys('coder', event);" onKeyUp="parent.ICEcoder.resetKeys(event);">
</head>
<body onLoad="ICEcoder.init(<?php if ($_SESSION['userLevel'] == 10) {echo "'login'";} ?>)<?php echo $onLoadExtras;?>" onResize="ICEcoder.setLayout()" onMouseMove="top.ICEcoder.getMouseXY(event);top.ICEcoder.canResizeFilesW()" onMouseDown="top.ICEcoder.mouseDown=true" onMouseUp="top.ICEcoder.mouseDown=false" onKeyDown="return ICEcoder.interceptKeys('coder', event);" onKeyUp="parent.ICEcoder.resetKeys(event);">
<div id="blackMask" class="blackMask" onClick="ICEcoder.showHide('hide',this)">
<div class="popupVCenter">
@@ -57,37 +70,50 @@ echo 'fullPath = "'.$docRoot.'";'.PHP_EOL;
<div class="popup">
<div class="circleOutside"></div>
<div class="circleInside"></div>
&nbsp;&nbsp;&nbsp;loading...
&nbsp;&nbsp;&nbsp;working...
</div>
</div>
</div>
<div id="fileMenu" class="fileMenu" onMouseOut="this.style.display='none'" onMouseOver="ICEcoder.changeFilesW('expand')" onMouseOut="ICEcoder.changeFilesW('contract')">
<a href="javascript:top.ICEcoder.newFile()" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">New File</a>
<a href="javascript:top.ICEcoder.newFolder()" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">New Folder</a>
<div id="fileMenu" class="fileMenu" onMouseOver="ICEcoder.changeFilesW('expand')" onMouseOut="ICEcoder.changeFilesW('contract')">
<span id="folderMenuItems">
<a href="javascript:top.ICEcoder.newFile()" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">New File</a>
<a href="javascript:top.ICEcoder.newFolder()" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">New Folder</a>
</span>
<a href="javascript:top.ICEcoder.deleteFile(top.ICEcoder.rightClickedFile)" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">Delete</a>
<a href="javascript:top.ICEcoder.renameFile(top.ICEcoder.rightClickedFile)" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">Rename</a>
<a href="javascript:window.open(top.ICEcoder.rightClickedFile.substr((top.ICEcoder.rightClickedFile.indexOf(shortURLStarts)+top.shortURLStarts.length),top.ICEcoder.rightClickedFile.length))" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">View Webpage</a>
<span id="singleFileMenuItems">
<a href="javascript:top.ICEcoder.renameFile(top.ICEcoder.rightClickedFile)" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">Rename</a>
<a href="javascript:window.open(top.ICEcoder.rightClickedFile.substr((top.ICEcoder.rightClickedFile.indexOf(shortURLStarts)+top.shortURLStarts.length),top.ICEcoder.rightClickedFile.length))" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">View Webpage</a>
</span>
</div>
<div id="header" class="header" onContextMenu="return false">
<div class="plugins">
<?php
for ($i=0;$i<count($plugins);$i++) {
echo '<a href="'.$plugins[$i][3].'" target="'.$plugins[$i][4].'"><img src="'.$plugins[$i][1].'" style="'.$plugins[$i][2].'" alt="'.$plugins[$i][0].'"></a>';
};
?>
<div class="plugins" id="pluginsContainer">
<?php echo $pluginsDisplay; ?>
</div>
<div class="version"><?php echo $versionNo;?></div>
<img src="images/ice-coder.gif" class="logo">
<img src="images/ice-coder.gif" class="logo" onClick="ICEcoder.helpScreen('show')" onContextMenu="ICEcoder.settingsScreen('show')">
</div>
<div id="files" class="files" onMouseOver="ICEcoder.changeFilesW('expand')" onMouseOut="ICEcoder.changeFilesW('contract'); top.document.getElementById('fileMenu').style.display='none';">
<div class="account" id="account">
<form name="login" action="index.php" method="POST">
<input type="password" name="loginPassword" class="accountPassword">
<input type="submit" name="submit" value="Login" class="button">
</form>
<div class="accountLoginContainer" id="accountLoginContainer">
<div class="accountLogin" id="accountLogin">
<form name="login" action="lib/settings.php" method="POST" target="ff">
<input type="password" name="loginPassword" class="accountPassword">
<input type="submit" name="submit" value="Login" class="button">
</form>
</div>
</div>
<div class="accountOptions">
<a nohref title="Save" onClick="ICEcoder.fMIcon('save')"><img src="images/save.png" alt="Save" id="fMSave" style="opacity: 0.3"></a>
<a nohref title="Open" onClick="ICEcoder.fMIcon('open')"><img src="images/open.png" alt="Open" id="fMOpen" style="margin-left: 7px; opacity: 0.3"></a>
<a nohref title="New File" onClick="ICEcoder.fMIcon('newFile')"><img src="images/new-file.png" alt="New File" id="fMNewFile" style="margin: 8px 0px 0px 10px; opacity: 0.3"></a>
<a nohref title="New Folder" onClick="ICEcoder.fMIcon('newFolder')"><img src="images/new-folder.png" alt="New Folder" id="fMNewFolder" style="margin: 9px 0px 0px 5px; opacity: 0.3"></a>
<a nohref title="Delete" onClick="ICEcoder.fMIcon('delete')"><img src="images/delete.png" alt="Delete" id="fMDelete" style="margin: 9px 0px 0px 5px; opacity: 0.3"></a>
<a nohref title="Rename" onClick="ICEcoder.fMIcon('rename')"><img src="images/rename.png" alt="Rename" id="fMRename" style="margin: 9px 0px 0px 5px; opacity: 0.3"></a>
<a nohref title="View" onClick="ICEcoder.fMIcon('view')"><img src="images/view.png" alt="View" id="fMView" style="margin: 9px 0px 0px 5px; opacity: 0.3"></a>
</div>
<a nohref style="cursor: pointer" onClick="ICEcoder.lockUnlockNav()"><img src="images/file-manager-icons/padlock.png" id="fmLock" class="lock"></a>
</div>
<iframe id="filesFrame" class="frame" name="ff" src="files.php" style="opacity: 0" onLoad="this.style.opacity='1'"></iframe>
@@ -106,27 +132,33 @@ echo 'fullPath = "'.$docRoot.'";'.PHP_EOL;
<form name="findAndReplace">
<div class="findReplace">
<div class="findText">Find</div>
<input type="text" name="find" value="" id="find" class="textbox find" onKeyUp="ICEcoder.findReplace('find',true)">
<input type="text" name="find" value="" id="find" class="textbox find" onKeyUp="ICEcoder.findReplace('find',true,false)">
<div class="findTextPlural">'s</div>
<select name="connector" onChange="ICEcoder.findReplaceOptions()">
<option>in</option>
<option>and</option>
</select>
<div class="replaceText" id="rText" style="display: none">replace with</div>
<div class="replaceText" id="rText" style="display: none">
<select name="replaceAction" class="replaceAction">
<option>replace</option>
<option>replace all</option>
</select>
with
</div>
<input type="text" name="replace" value="" id="replace" class="textbox replace" style="display: none">
<div class="targetText" id="rTarget" style="display: none">in</div>
<select name="target">
<select name="target" onChange="ICEcoder.updateResultsDisplay(this.value=='this document' ? 'show' : 'hide')">
<option>this document</option>
<option>open documents</option>
<option>all files</option>
<option>all filenames</option>
</select>
<input type="button" name="submit" value="&gt;&gt;" class="submit" onClick="ICEcoder.findReplace('findReplace',false)">
<input type="button" name="submit" value="&gt;&gt;" class="submit" onClick="ICEcoder.findReplace('findReplace',false,true)">
<div class="results" id="results"></div>
</div>
</form>
<form onSubmit="return ICEcoder.goToLine()">
<div class="codeAssist"><input type="checkbox" name="codeAssist" checked onClick="top.ICEcoder.codeAssistToggle()">Code Assist</div>
<div class="codeAssist"><input type="checkbox" name="codeAssist" id="codeAssist" checked onClick="top.ICEcoder.codeAssistToggle()">Code Assist</div>
<div class="goLine">Go to Line<input type="text" name="goToLine" value="" id="goToLineNo" class="textbox goToLine">
</form>
</div>

View File

@@ -18,15 +18,24 @@ table, caption, tbody, tfoot, thead, tr, th, td {
}
body {overflow: hidden;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select:none;
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select:none;
user-select: none;
background-color: #222222;
}
h1 {font-size: 36px; font-weight: normal; color: #888888; margin-bottom: 20px}
h2 {font-size: 18px; font-weight: normal; color: #ffffff}
.blackMask {position: fixed; display: table; width: 100%; height: 100%; top: 0px; left: 0px; visibility: hidden; background-color: rgba(0,0,0,0.8); text-align: center; z-index: 100}
.blackMask .popupVCenter {#position: absolute; display: table-cell; #top: 50%; vertical-align: middle; text-align: center}
.popupVCenter .popup {#position: relative; #top: -50%; text-align: center; color: #ffffff; font-size: 10px}
.whiteGlow {
-webkit-box-shadow: 0px 0px 8px 2px rgba(255,255,255,0.6);
-moz-box-shadow: 0px 0px 8px 2px rgba(255,255,255,0.6);
box-shadow: 0px 0px 8px 2px rgba(255,255,255,0.6);
}
.circleOutside {background-color: rgba(0,0,0,0); border:5px solid rgba(0,183,229,0.9); opacity:.9; border-top:5px solid rgba(0,0,0,0); border-left:5px solid rgba(0,0,0,0); border-radius:50px; box-shadow: 0 0 35px #2187e7;
width:50px; height:50px; margin:0 auto; -moz-animation:spin .5s infinite linear; -webkit-animation:spin .5s infinite linear;
@@ -64,23 +73,38 @@ body {overflow: hidden;
}
.header {position: absolute; display: inline-block; width: 100%; height: 40px; background-color: #ffffff; text-align: right; z-index: 2}
.header .plugins {position: absolute; display: inline-block; left: 27px; top: 3px}
.header .plugins {position: absolute; display: inline-block; left: 15px; top: 3px}
.header .plugins img {position: relative; display: inline-block; margin-right: 15px}
.header .version {position: relative; display: inline-block; margin-top: 25px; font-size: 10px; color: #bbbbbb}
.header .logo {position: relative; margin: 5px 10px 0px 5px}
.header .logo {position: relative; margin: 5px 10px 0px 5px; cursor: pointer}
.files {position: absolute; display: inline-block; height: 100%; width: 250px; background-color: #e0e0e0; background-image: url('../images/files-arrow.gif'); background-repeat: no-repeat; background-position: 100% 50%; overflow: hidden; z-index: 1;
.files {position: absolute; display: inline-block; height: 100%; width: 250px; background-color: #444444; background-image: url('../images/files-arrow.gif'); background-repeat: no-repeat; background-position: 100% 50%; overflow: hidden; z-index: 1;
-webkit-box-shadow: 0px 0px 10px 4px rgba(0,0,0,0.4);
-moz-box-shadow: 0px 0px 10px 4px rgba(0,0,0,0.4);
box-shadow: 0px 0px 10px 4px rgba(0,0,0,0.4);
}
.files .account {display: inline-block; height: 50px; width: 250px; margin-top: 40px; background-color: #888888}
.files .accountLoginContainer {position: absolute; width: 250px; height: 50px; z-index: 1}
.files .accountLoginContainer .accountLogin {position: absolute; width: 250px; height: 50px; top: 0px; background-color: #666666;
-webkit-transition: top 0.3s;
-moz-transition: top 0.3s;
-o-transition: top 0.3s;
transition: top 0.3s;
}
.files .accountOptions {position: relative; height: 31px; width: 200px; margin-left: 15px; margin-top: 8px}
.files .accountOptions img {cursor: pointer}
.files .accountPassword {position: relative; border: 1px solid #888888; background-color: #999999; height: 18px; width: 140px; margin-left: 14px; margin-top: 15px}
.files input:focus, .findReplace input:focus, .findReplace select:focus, .accountPassword:focus {
outline: none;
-webkit-box-shadow: 0px 0px 10px 1px rgba(0,198,255,0.7);
-moz-box-shadow: 0px 0px 10px 1px rgba(0,198,255,0.7);
box-shadow: 0px 0px 10px 1px rgba(0,198,255,0.7);
}
.files .button {position: absolute; border: 0px; background: #999999; color: #555555; height:20px; margin-top: 16px; margin-left: 5px; font-size: 11px; cursor: pointer}
.files .button:hover {background-color: #444444; color: #eeeeee}
.files .lock {margin-left: 225px; margin-top: -20px}
.files .lock {position: relative; margin-left: 225px; margin-top: -20px; z-index: 1}
.files .frame {display: inline-block; width: 250px}
.files .serverMessage {position: absolute; display: inline-block; width: 180px; bottom: 0px; margin-bottom: 30px; background-color: rgba(255,255,255,0.8); font-size: 10px; padding: 7px 12px; opacity: 0;
.files .serverMessage {position: absolute; display: inline-block; width: 450px; bottom: 0px; margin-bottom: 30px; background-color: rgba(255,255,255,0.8); font-size: 10px; padding: 7px 12px; opacity: 0;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-o-transition: all 0.2s;
@@ -88,22 +112,23 @@ body {overflow: hidden;
}
.files .serverMessage b {font-size: 10px}
.editor {position: absolute; display: inline-block; top: 0px; left: 15px; width: 2400px; background-color: #fbfbfb;}
.editor .tabsBar {display: inline-block; height: 21px; width: 2400px; margin-top: 40px; padding-left: 41px; border-bottom: solid 1px #888888; background-color: #eeeeee;}
.tabsBar .tab {display: inline-block; display: none; background-image: url('../images/nav-bg.gif'); background-repeat: repeat-x; background-position: 0px 0px; padding: 4px 8px 2px 8px; font-size: 10px; border-left: solid 1px #ffffff; border-right: solid 1px #bbbbbb; color: #ffffff; cursor: pointer;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
.editor {position: absolute; display: inline-block; top: 0px; left: 15px; width: 2400px}
.editor .tabsBar {display: inline-block; height: 22px; width: 2400px; margin-top: 40px; padding-left: 41px; background-color: #888888;}
.tabsBar .tab {display: inline-block; display: none; background-image: url('../images/nav-bg.gif'); background-repeat: repeat-x; background-position: 0px 0px; padding: 5px 8px 2px 8px; font-size: 10px; border-left: solid 1px #ffffff; border-right: solid 1px #777777; color: #ffffff; cursor: pointer;
-webkit-transition: all 0.15s;
-moz-transition: all 0.15s;
-o-transition: all 0.15s;
transition: all 0.15s;
}
.tabsBar .tab img {margin: 1px 0px 0px 5px}
.tabsBar .newTab {display: inline-block; background-image: url('../images/nav-bg.gif'); background-repeat: repeat-x; background-position: 0px 0px; padding: 5px 5px 1px 5px; border-left: solid 1px #ffffff; border-right: solid 1px #bbbbbb; cursor: pointer;}
.editor .findBar {display: inline-block; height: 28px; width: 2400px; background-color: #eeeeee}
.tabsBar .tab .closeTab {margin: 1px 0px 0px 5px; border-radius: 6px}
.tabsBar .newTab {display: inline-block; background-image: url('../images/nav-bg.gif'); background-repeat: repeat-x; background-position: 0px 0px; padding: 6px 5px 1px 5px; border-left: solid 1px #ffffff; border-right: solid 1px #777777; cursor: pointer;}
.editor .findBar {display: inline-block; height: 28px; width: 2400px; color: #ffffff; background-color: #141414}
.findBar .findReplace {position: absolute; z-index: 1}
.findReplace select {position: relative; font-size: 10px; margin: 8px 2px 0px 2px; top: -2px;}
.findReplace .findText {display: inline-block; height: 21px; font-size: 10px; margin: 8px 2px 0px 2px; margin-left: 43px}
.findReplace .find {position: relative; width: 120px; height: 16px; border: 0; top: -2px; font-size: 10px; padding-left: 5px}
.findReplace .findTextPlural {display: inline-block; height: 21px; font-size: 10px; margin: 8px 2px 0px 0px}
.findReplace .replaceAction {margin: 0px 2px 0px 0px; top: -2px}
.findReplace .replaceText {height: 21px; font-size: 10px; margin: 8px 2px 0px 2px}
.findReplace .replace {position: relative; width: 120px; height: 16px; border: 0; top: -2px; font-size: 10px; padding-left: 5px}
.findReplace .targetText {height: 21px; font-size: 10px; margin: 8px 2px 0px 2px}
@@ -136,4 +161,4 @@ body {overflow: hidden;
.screenVCenter .screenCenter {#position: relative; #top: -50%; text-align: center; display: inline}
.screenCenter .version {position: relative; display: block; margin: 5px 0px 15px 0px; font-size: 10px; color: #bbbbbb}
.screenCenter .accountPassword {border: 1px solid #888888; height: 18px}
.screenCenter .button {border: 0px; background: #666666; color: #ffffff; height: 22px}
.screenCenter .button {border: 0px; background: #666666; color: #ffffff; height: 22px; cursor: pointer}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,4 @@
html, body {margin: 0px}
/* Based VERY loosely on the Monokai theme */
/* ICE coder default theme: Based VERY loosely on Monokai */
.cm-s-icecoder {font-size: 12px; color: #666; background: #1c1c19;}
@@ -35,11 +33,8 @@ html, body {margin: 0px}
.cm-s-icecoder span.cm-hr {color: #999;}
.cm-s-icecoder span.cm-link {color: #ff0;}
.cm-s-icecoder .CodeMirror-selected {background: #037 !important;}
.cm-s-icecoder .CodeMirror-gutter {background: #333; border-right: 1px solid #e8e8e8;}
.cm-s-icecoder .CodeMirror-gutter-text {color: #999; width: 35px;}
.cm-s-icecoder .CodeMirror-cursor {border-left: 1px solid white !important;}
.cm-s-icecoder .CodeMirror-matchingbracket{border: 1px solid grey; color: black !important;}
span.CodeMirror-matchhighlight {background: #555555}
.CodeMirror-focused span.CodeMirror-matchhighlight {color: #000000; background: #555555; !important}
.cm-s-icecoder .CodeMirror-selected {background: #037 !important;}
.cm-s-icecoder .CodeMirror-gutter {background: #333; border-right: 1px solid #e8e8e8}
.cm-s-icecoder .CodeMirror-gutter-text {color: #999; width: 35px; cursor: default}
.cm-s-icecoder .CodeMirror-matchingbracket {border: 1px solid grey; color: black !important;}

View File

@@ -28,7 +28,9 @@ if ($_GET['action']=="load") {
}
}
if ($_SESSION['userLevel'] == 10 || ($_SESSION['userLevel'] < 10 && $bannedFile==false)) {
echo '<script>fileType="text";</script>';
echo '<script>fileType="text";top.ICEcoder.rightClickedFile=top.ICEcoder.thisFileFolderLink=\''.$file.'\';';
echo 'shortURL = top.ICEcoder.thisFileFolderLink.replace(/\|/g,"/");';
echo 'top.ICEcoder.shortURL = shortURL.substr((shortURL.indexOf(top.shortURLStarts)+top.shortURLStarts.length),shortURL.length);</script>';
$loadedFile = file_get_contents($file);
echo '<textarea name="loadedFile" id="loadedFile">'.str_replace("</textarea>","<ICEcoder:/:textarea>",$loadedFile).'</textarea>';
} else {
@@ -135,22 +137,29 @@ if ($_GET['action']=="save") {
}
$saveFile = str_replace("\\","/",$_SERVER['DOCUMENT_ROOT']).$file;
$saveFile = str_replace("//","/",$saveFile);
if (is_writable($saveFile)) {
$fh = fopen($saveFile, 'w') or die("can't open file");
fwrite($fh, $_POST['contents']);
fclose($fh);
if ((file_exists($saveFile) && is_writable($saveFile)) || $_POST['newFileName']!="") {
if (filemtime($saveFile)==$_GET['fileMDT']||!(isset($_GET['fileMDT']))) {
$fh = fopen($saveFile, 'w') or die("Sorry, cannot save");
fwrite($fh, $_POST['contents']);
fclose($fh);
clearstatcache();
echo '<script>top.ICEcoder.openFileMDTs[top.ICEcoder.selectedTab-1]="'.filemtime($saveFile).'";</script>';
if (isset($_POST['newFileName'])&&$_POST['newFileName']!="") {
// Reload file manager & stop CTRL+s being sticky
$fileName = substr($file,strrpos($file,"/")+1);
$fileLoc = substr($file,0,strrpos($file,"/"));
if ($fileLoc=="") {$fileLoc = "/";};
echo '<script>top.ICEcoder.selectedFiles=[];top.ICEcoder.updateFileManagerList(\'add\',\''.$fileLoc.'\',\''.$fileName.'\')</script>';
if (isset($_POST['newFileName'])&&$_POST['newFileName']!="") {
// Reload file manager & stop CTRL+s being sticky
$fileName = substr($file,strrpos($file,"/")+1);
$fileLoc = substr($file,0,strrpos($file,"/"));
if ($fileLoc=="") {$fileLoc = "/";};
echo '<script>top.ICEcoder.selectedFiles=[];top.ICEcoder.updateFileManagerList(\'add\',\''.$fileLoc.'\',\''.$fileName.'\')</script>';
}
if (isset($_POST['newFileName'])&&$_POST['newFileName']!="") {
echo '<script>top.ICEcoder.renameTab(top.ICEcoder.selectedTab,\''.$file.'\');</script>';
}
echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);if (top.ICEcoder.stickyTabWindow.location) {top.ICEcoder.stickyTabWindow.location.reload()};action="doneSave";</script>';
} else {
echo "<script>alert('Sorry, this file has changed, cannot save\\n".$file."');</script>";
echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);action="nothing";</script>';
}
if (isset($_POST['newFileName'])&&$_POST['newFileName']!="") {
echo '<script>top.ICEcoder.renameTab(top.ICEcoder.selectedTab,\''.$file.'\');</script>';
}
echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);action="doneSave";</script>';
} else {
echo "<script>alert('Sorry, cannot write\\n".$file."');</script>";
echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);action="nothing";</script>';
@@ -191,19 +200,21 @@ if (action=="load") {
top.ICEcoder.content.contentWindow['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].setLineClass(top.ICEcoder['cMActiveLine'+top.ICEcoder.selectedTab], null);
top.ICEcoder['cMActiveLine'+top.ICEcoder.selectedTab] = top.ICEcoder.content.contentWindow['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].setLineClass(0, "cm-s-activeLine");
top.ICEcoder.nextcMInstance++;
top.ICEcoder.serverMessage();
top.ICEcoder.serverQueue("del",0);
top.ICEcoder.openFileMDTs.push('<?php echo filemtime($file); ?>');
top.ICEcoder.loadingFile = false;
}
if (fileType=="image") {
top.document.getElementById('blackMask').style.visibility = "visible";
top.document.getElementById('mediaContainer').innerHTML = "<img src=\"<?php echo str_replace($docRoot,"",$file);?>\" style=\"border: solid 10px #ffffff; max-width: 700px; max-height: 500px\" onClick=\"return false\"><br><span style=\"border: solid 10px #ffffff; background-color: #ffffff\" onClick=\"return false\"><?php echo str_replace($docRoot,"",$file);?></span>";
top.document.getElementById('mediaContainer').innerHTML = "<img src=\"<?php echo str_replace($docRoot,"",$file);?>\" class=\"whiteGlow\" style=\"border: solid 10px #ffffff; max-width: 700px; max-height: 500px\" onClick=\"return false\"><br><span class=\"whiteGlow\" style=\"border: solid 10px #ffffff; color: #000000; background-color: #ffffff\" onClick=\"return false\"><?php echo str_replace($docRoot,"",$file);?></span>";
}
top.ICEcoder.serverMessage();
top.ICEcoder.serverQueue("del",0);
}
</script>
<form name="saveFile" action="file-control.php?action=save&file=<?php if (isset($file)) {echo $file;};?>" method="POST">
<form name="saveFile" action="file-control.php?action=save&file=<?php if (isset($file)) {echo $file;}; if (isset($_GET['fileMDT']) && $_GET['fileMDT']!="undefined") {echo "&fileMDT=".$_GET['fileMDT'];};?>" method="POST">
<textarea name="contents"></textarea>
<input type="hidden" name="newFileName" value="">
</form>
@@ -219,10 +230,21 @@ if (action=="save") {
} else {
newFileName = prompt('Enter Filename','/');
}
if (newFileName && top.document.getElementById('filesFrame').contentWindow.document.getElementById(newFileName.replace(/\//g,"|"))) {
overwriteOK = confirm('That file exists already, overwrite?');
}
document.saveFile.newFileName.value = newFileName;
<?php ;};?>
document.saveFile.contents.innerHTML = top.document.getElementById('saveTemp1').value;
document.saveFile.submit();
if ("undefined" == typeof newFileName || (newFileName && "undefined" == typeof overwriteOK) || ("undefined" != typeof overwriteOK && overwriteOK)) {
if ("undefined" != typeof newFileName) {
top.ICEcoder.serverMessage('<b>Saving</b><br>'+newFileName);
}
document.saveFile.contents.innerHTML = top.document.getElementById('saveTemp1').value;
document.saveFile.submit();
} else {
top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);
action=="nothing";
}
}
</script>

View File

@@ -19,6 +19,8 @@ table, caption, tbody, tfoot, thead, tr, th, td {
body {margin: 0px; overflow: auto}
.refresh {float: right; margin-right: 15px; cursor: pointer}
.fileManager {
margin: 15px 0px 15px 22px;
-webkit-user-select: none;
@@ -28,71 +30,34 @@ body {margin: 0px; overflow: auto}
}
.fileManager span {font-family: helvetica, arial, swiss, verdana;}
.fileManager a {color: #000000; text-decoration: none;}
.fileManager a {color: #eeeeee; text-decoration: none;}
.fileManager .open {font-style: italic;}
.fileManager .closed {font-style: normal;}
.fileManager .pft-directory {list-style-image: url(../images/file-manager-icons/directory.png);}
.fileManager li {margin-left: 15px;}
/* Default file */
.fileManager LI.pft-file { list-style-image: url(../images/file-manager-icons/file.png); cursor: pointer;}
.fileManager LI.pft-file { list-style-image: url(../images/file-manager-icons/file.png); }
/* Additional file types */
.fileManager LI.ext-3gp { list-style-image: url(../images/file-manager-icons/film.png); }
.fileManager LI.ext-afp { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-afpa { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-asp { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-aspx { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-avi { list-style-image: url(../images/file-manager-icons/film.png); }
.fileManager LI.ext-bat { list-style-image: url(../images/file-manager-icons/application.png); }
.fileManager LI.ext-bmp { list-style-image: url(../images/file-manager-icons/picture.png); }
.fileManager LI.ext-c { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-cfm { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-cgi { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-com { list-style-image: url(../images/file-manager-icons/application.png); }
.fileManager LI.ext-cpp { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-css { list-style-image: url(../images/file-manager-icons/css.png); }
.fileManager LI.ext-doc { list-style-image: url(../images/file-manager-icons/doc.png); }
.fileManager LI.ext-exe { list-style-image: url(../images/file-manager-icons/application.png); }
.fileManager LI.ext-gif { list-style-image: url(../images/file-manager-icons/picture.png); }
.fileManager LI.ext-fla { list-style-image: url(../images/file-manager-icons/flash.png); }
.fileManager LI.ext-h { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-gif { list-style-image: url(../images/file-manager-icons/gif.png); }
.fileManager LI.ext-htm { list-style-image: url(../images/file-manager-icons/html.png); }
.fileManager LI.ext-html { list-style-image: url(../images/file-manager-icons/html.png); }
.fileManager LI.ext-jar { list-style-image: url(../images/file-manager-icons/java.png); }
.fileManager LI.ext-jpg { list-style-image: url(../images/file-manager-icons/picture.png); }
.fileManager LI.ext-jpeg { list-style-image: url(../images/file-manager-icons/picture.png); }
.fileManager LI.ext-js { list-style-image: url(../images/file-manager-icons/script.png); }
.fileManager LI.ext-lasso { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-log { list-style-image: url(../images/file-manager-icons/txt.png); }
.fileManager LI.ext-m4p { list-style-image: url(../images/file-manager-icons/music.png); }
.fileManager LI.ext-mov { list-style-image: url(../images/file-manager-icons/film.png); }
.fileManager LI.ext-mp3 { list-style-image: url(../images/file-manager-icons/music.png); }
.fileManager LI.ext-mp4 { list-style-image: url(../images/file-manager-icons/film.png); }
.fileManager LI.ext-mpg { list-style-image: url(../images/file-manager-icons/film.png); }
.fileManager LI.ext-mpeg { list-style-image: url(../images/file-manager-icons/film.png); }
.fileManager LI.ext-ogg { list-style-image: url(../images/file-manager-icons/music.png); }
.fileManager LI.ext-pcx { list-style-image: url(../images/file-manager-icons/picture.png); }
.fileManager LI.ext-pdf { list-style-image: url(../images/file-manager-icons/pdf.png); }
.fileManager LI.ext-jpg { list-style-image: url(../images/file-manager-icons/jpg.png); }
.fileManager LI.ext-jpeg { list-style-image: url(../images/file-manager-icons/jpg.png); }
.fileManager LI.ext-js { list-style-image: url(../images/file-manager-icons/js.png); }
/*.fileManager LI.ext-pdf { list-style-image: url(../images/file-manager-icons/pdf.png); } */
.fileManager LI.ext-php { list-style-image: url(../images/file-manager-icons/php.png); }
.fileManager LI.ext-png { list-style-image: url(../images/file-manager-icons/picture.png); }
.fileManager LI.ext-ppt { list-style-image: url(../images/file-manager-icons/ppt.png); }
.fileManager LI.ext-psd { list-style-image: url(../images/file-manager-icons/psd.png); }
.fileManager LI.ext-pl { list-style-image: url(../images/file-manager-icons/script.png); }
.fileManager LI.ext-py { list-style-image: url(../images/file-manager-icons/script.png); }
.fileManager LI.ext-png { list-style-image: url(../images/file-manager-icons/png.png); }
.fileManager LI.ext-rb { list-style-image: url(../images/file-manager-icons/ruby.png); }
.fileManager LI.ext-rbx { list-style-image: url(../images/file-manager-icons/ruby.png); }
.fileManager LI.ext-rhtml { list-style-image: url(../images/file-manager-icons/ruby.png); }
.fileManager LI.ext-rpm { list-style-image: url(../images/file-manager-icons/linux.png); }
.fileManager LI.ext-ruby { list-style-image: url(../images/file-manager-icons/ruby.png); }
.fileManager LI.ext-sql { list-style-image: url(../images/file-manager-icons/db.png); }
.fileManager LI.ext-swf { list-style-image: url(../images/file-manager-icons/flash.png); }
.fileManager LI.ext-tif { list-style-image: url(../images/file-manager-icons/picture.png); }
.fileManager LI.ext-tiff { list-style-image: url(../images/file-manager-icons/picture.png); }
/*.fileManager LI.ext-sql { list-style-image: url(../images/file-manager-icons/sql.png); } */
/*.fileManager LI.ext-swf { list-style-image: url(../images/file-manager-icons/swf.png); } */
.fileManager LI.ext-txt { list-style-image: url(../images/file-manager-icons/txt.png); }
.fileManager LI.ext-vb { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-wav { list-style-image: url(../images/file-manager-icons/music.png); }
.fileManager LI.ext-wmv { list-style-image: url(../images/file-manager-icons/film.png); }
.fileManager LI.ext-xls { list-style-image: url(../images/file-manager-icons/xls.png); }
.fileManager LI.ext-xml { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-zip { list-style-image: url(../images/file-manager-icons/zip.png); }
/*.fileManager LI.ext-xls { list-style-image: url(../images/file-manager-icons/xls.png); } */
/*.fileManager LI.ext-xml { list-style-image: url(../images/file-manager-icons/xml.png); } */
/*.fileManager LI.ext-zip { list-style-image: url(../images/file-manager-icons/zip.png); } */

31
lib/help.css Normal file
View File

@@ -0,0 +1,31 @@
/* First, reset everything to a standard */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
border: 0px;
margin: 0px;
padding: 0px;
outline: 0px;
font-size: 12px;
vertical-align: top;
}
body {overflow: hidden;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select:none;
user-select: none;
}
h1 {font-size: 36px; font-weight: normal; color: #888888; margin-bottom: 20px}
.help {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #ffffff; padding: 20px}
.help .key {display: inline-block; width: 175px; text-align: right; margin-right: 5px; float: left}
.help .key .plus {color: #888888}
.help .shortcut {display: inline-block; width: 175px; color: #888888; margin-left: 5px; float: left}

38
lib/help.php Normal file
View File

@@ -0,0 +1,38 @@
<?php include("settings.php");?>
<!DOCTYPE html>
<html>
<head>
<title>ICE Coder - <?php echo $versionNo;?> :: Help & Shortcuts</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="help.css">
</head>
<body class="help">
<h1 id="title">help</h1>
<h2>In file manager</h2>
<span class="key">Delete</span> <span class="shortcut">Delete file</span><br><br>
<h2>Within document</h2>
<span class="key">CTRL <span class="plus">+</span> I</span> <span class="shortcut">Search selected text</span><br>
<span class="key">Esc</span> <span class="shortcut">Comment / uncomment text</span><br>
<span class="key">Tab</span> <span class="shortcut">Insert tab / indent selected text</span><br><br>
<h2>Anywhere</h2>
<span class="key">CTRL <span class="plus">+</span> F</span> <span class="shortcut">Find</span><br>
<span class="key">CTRL <span class="plus">+</span> G</span> <span class="shortcut">Go to line</span><br>
<span class="key">CTRL <span class="plus">+</span> S</span> <span class="shortcut">Save</span><br>
<span class="key">CTRL <span class="plus">+</span> Shift <span class="plus">+</span> S</span> <span class="shortcut">Save as...</span><br>
<span class="key">CTRL <span class="plus">+</span> Enter</span> <span class="shortcut">View webpage</span><br>
<span class="key">CTRL <span class="plus">+</span> S <span class="plus">+</span> Enter</span> <span class="shortcut">Save & create sticky tab</span><br>
<span class="key">Esc</span> <span class="shortcut">Cancel tasks</span><br><br>
<h2>Clicking logo</h2>
<span class="key">Left click</span> <span class="shortcut">Help</span><br>
<span class="key">Right click</span> <span class="shortcut">Settings</span><br>
</body>
</html>

35
lib/multiple-results.css Normal file
View File

@@ -0,0 +1,35 @@
/* First, reset everything to a standard */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
border: 0px;
margin: 0px;
padding: 0px;
outline: 0px;
font-size: 12px;
vertical-align: top;
}
body {overflow: hidden;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select:none;
user-select: none;
}
h1 {font-size: 36px; font-weight: normal; color: #888888; margin-bottom: 20px}
h2 {font-size: 18px; font-weight: normal; color: #ffffff}
hr {border: 0; height: 1px; background-color: #888888}
.results {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #ffffff}
.results .resultsPane {position: relative; width: 660px; height: 560px; font-size: 10px; padding: 20px; float: left}
.results .resultsPane a {color: rgba(0,198,255,0.7); text-decoration: none}
.results .resultsPane a:hover {text-decoration: underline}
.replace {position: absolute; margin-top: -28px; right: 20px; padding: 5px 10px; font-size: 14px; background-color: rgba(0,198,255,0.7); cursor: pointer}
.replaceAll {position: absolute; bottom: 0px; right: 20px; padding: 5px 10px; font-size: 18px; background-color: rgba(0,198,255,0.7); cursor: pointer}

75
lib/multiple-results.php Normal file
View File

@@ -0,0 +1,75 @@
<?php include("settings.php");?>
<!DOCTYPE html>
<html>
<head>
<title>ICE Coder - <?php echo $versionNo;?> :: Multiple Results Screen</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="multiple-results.css">
</head>
<body class="results">
<div class="resultsPane">
<h1 id="title"></h1>
<div id="results"></div>
</div>
<?php if (isset($_GET['replace'])) { ?>
<div class="replaceAll" id="replaceAll" onClick="replaceAll()" style="opacity: 0.1">replace all</div>
<?php ;}; ?>
<script>
var resultsDisplay = "";
var foundTabArray = [];
var startTab = top.ICEcoder.selectedTab;
var rExp = new RegExp("<?php echo $_GET['find']; ?>","g");
for (var i=1;i<=top.ICEcoder.openFiles.length;i++) {
top.ICEcoder.switchTab(i);
var cM = top.ICEcoder.getcMInstance();
var content = cM.getValue();
if (content.match(rExp)) {
resultsDisplay += '<a href="javascript:gotoTab('+i+')">'+ top.ICEcoder.openFiles[i-1]+ '</a><br><div id="foundCount'+i+'">Found '+content.match(rExp).length+' times</div>';
<?php if (isset($_GET['replace'])) { ?>
resultsDisplay += '<div class="replace" id="replace" onClick="replaceSingle('+i+');this.style.display=\'none\'">replace</div>';
<?php ;}; ?>
resultsDisplay += '<hr>';
foundTabArray.push(i);
}
}
if (startTab!=top.ICEcoder.selectedTab) {
top.ICEcoder.switchTab(startTab);
}
foundTabArray.length==0 ? showHide = "hide" : showHide = "show";
top.ICEcoder.showHide(showHide,top.document.getElementById('blackMask'));
if (foundTabArray.length==0) {alert('No matches found')};
<?php if (isset($_GET['replace'])) { ?>
if (foundTabArray.length!=0) {document.getElementById('replaceAll').style.opacity = 1};
<?php ;}; ?>
foundTabArray.length >= 2 ? plural = "s" : plural = "";
document.getElementById('title').innerHTML = "'<?php echo $_GET['find']; ?>' found in "+foundTabArray.length+" file"+plural;
document.getElementById('results').innerHTML = resultsDisplay;
var gotoTab = function(tab) {
top.ICEcoder.switchTab(tab);
top.ICEcoder.showHide('hide',top.document.getElementById('blackMask'));
}
var replaceSingle = function(tab) {
top.ICEcoder.switchTab(tab);
cM = top.ICEcoder.getcMInstance();
content = cM.getValue();
cM.setValue(cM.getValue().replace(rExp,top.document.getElementById('replace').value));
document.getElementById('foundCount'+tab).innerHTML = document.getElementById('foundCount'+tab).innerHTML.replace('Found','Replaced');
}
var replaceAll = function() {
for (var i=0;i<=foundTabArray.length-1;i++) {
replaceSingle(foundTabArray[i]);
}
top.ICEcoder.showHide('hide',top.document.getElementById('blackMask'));
}
</script>
</body>
</html>

45
lib/settings-screen.css Normal file
View File

@@ -0,0 +1,45 @@
/* First, reset everything to a standard */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
border: 0px;
margin: 0px;
padding: 0px;
outline: 0px;
font-size: 12px;
vertical-align: top;
}
body {overflow: hidden;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select:none;
user-select: none;
}
h1 {font-size: 36px; font-weight: normal; color: #888888; margin-bottom: 20px}
h2 {font-size: 18px; font-weight: normal; color: #ffffff}
.settings {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #ffffff}
.settings .infoPane {position: relative; width: 230px; height: 560px; font-size: 10px; color: #bbbbbb; background-color: #ffffff; padding: 20px; float: left}
.settings .infoPane a {color: #888888; text-decoration: none}
.settings .infoPane a:hover {text-decoration: underline}
.settings .logo {position: relative; margin-top: 2px}
.settings .version {position: relative; display: block; margin-top: 5px; margin-bottom: 10px; font-size: 10px; color: #bbbbbb}
.settings .settingsColumn1 {width: 220px; height: 560px; padding: 20px; float: left}
.settings .settingsColumn2 {width: 420px; height: 560px; padding: 20px 20px 20px 0px; float: left}
.settings input, .settings textarea {border: 1px solid #555555; background-color: #444444; color: #ffffff}
.settings input:focus, .settings textarea:focus {
outline: none;
-webkit-box-shadow: 0px 0px 10px 1px rgba(0,198,255,0.7);
-moz-box-shadow: 0px 0px 10px 1px rgba(0,198,255,0.7);
box-shadow: 0px 0px 10px 1px rgba(0,198,255,0.7);
}
.settings .plugins {font-family: arial, verdana, helvetica, sans-serif; width: 410px; height: 123px; overflow: hidden}
.settings .update {position: absolute; bottom: 0px; right: 20px; padding: 5px 10px; font-size: 18px; background-color: rgba(0,198,255,0.7); opacity: 0.1; cursor: pointer}

205
lib/settings-screen.php Normal file
View File

@@ -0,0 +1,205 @@
<?php include("settings.php");?>
<!DOCTYPE html>
<html>
<head>
<title>ICE Coder - <?php echo $versionNo;?> :: Settings Screen</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="settings-screen.css">
<link rel="stylesheet" href="../<?php echo $codeMirrorDir; ?>/lib/codemirror.css">
<script src="../<?php echo $codeMirrorDir; ?>/lib/codemirror.js"></script>
<script src="../<?php echo $codeMirrorDir; ?>/mode/javascript/javascript.js"></script>
<style type="text/css">
.CodeMirror {position: absolute; width: 0px; background-color: #ffffff; font-family: monospace}
.CodeMirror-scroll {height: 220px; width: 420px; overflow: hidden}
.cm-s-visible {display: block; top: 0px}
.cm-s-hidden {display: none; top: 4000px}
.cm-s-activeLine {background: #002 !important;}
// Make sure this next one remains the 5th item, updated with JS
.cm-tab:after {position: relative; display: inline-block; width: 0px; left: -1.4em; overflow: visible; color: #aaa; content: "<?php if($visibleTabs) {echo '\21e5';};?>";}
span.CodeMirror-matchhighlight {background: #555555}
.CodeMirror-focused span.CodeMirror-matchhighlight {color: #000000; background: #555555; !important}
</style>
<link rel="stylesheet" href="editor.css">
<?php
$themeArray = array("ambiance","blackboard","cobalt","eclipse","elegant","lesser-dark","monokai","neat","night","rubyblue","xq-dark");
for ($i=0;$i<count($themeArray)-1;$i++) {
echo '<link rel="stylesheet" href="../'.$codeMirrorDir.'/theme/'.$themeArray[$i].'.css">'.PHP_EOL;
}
?>
</head>
<body class="settings">
<div class="infoPane">
<img src="../images/ice-coder.gif" class="logo">
<div class="version"><?php echo $versionNo;?></div>
<p>
git:<br>
<a href="http://github.com/mattpass/ICEcoder" target="_blank">http://github.com/mattpass/ICEcoder</a>
<br><br>
codemirror dir:<br>
<?php echo $codeMirrorDir; ?>
<br><br>
codemirror version:<br>
<?php echo $cMThisVer; ?>
<br><br>
doc root:<br>
<?php if($_SESSION['userLevel']==10) { echo $_SERVER['DOCUMENT_ROOT']; } else { echo '[HIDDEN]'; }; ?>
<br><br><br><br>
<div style="font-size: 10px; line-height: 12px">ICE coder by Matt Pass (<a href="http://www.twitter.com/mattpass" style="font-size: 10px" target="_blank">@mattpass</a>)<br><br>
Free to use it for your own purposes, commercial or not, just let me know of any cool uses or customisations. :)<br><br>
No warranty or liability accepted for anything, all responsibility of use is your own.<br><br>
Thanks go to the following people who have inspired me to create this and in the odd case, provided feedback or code:<br>
<?php
$peopleArray = array("marijnjh", "maettig", "wimtibackx", "jakubvrana", "davidwalshblog", "kuvos", "paul_irish", "mathias", "rem");
for ($i=0;$i<count($peopleArray)-1;$i++) {
echo '<a href="http://www.twitter.com/'.$peopleArray[$i].'" style="font-size: 10px" target="_blank">@'.$peopleArray[$i].'</a>';
if ($i<count($peopleArray)-2) {
echo ", ";
}
}
?>
</div>
</p>
</div>
<form name="settings" action="settings.php" method="POST">
<div class="settingsColumn1">
<h1>settings</h1>
<h2>functionality</h2>
<input type="checkbox" onclick="showButton()" name="tabsIndent" value="true"<?php if($tabsIndent) {echo ' checked';};?>> tab indents selection<br>
<input type="checkbox" onclick="showButton()" name="testcMVersion" value="true"<?php if($testcMVersion) {echo ' checked';};?>> test codemirror version on load<br>
<input type="checkbox" onclick="showButton()" name="openLastFiles" value="true"<?php if($openLastFiles) {echo ' checked';};?>> auto open last files on login<br>
<br>
<h2>assisting</h2>
<input type="checkbox" onclick="showButton()" name="codeAssist" value="true"<?php if($codeAssist) {echo ' checked';};?>> code assist<br>
<input type="checkbox" onclick="showButton();showHideTabs()" name="visibleTabs" value="true"<?php if($visibleTabs) {echo ' checked';};?>> visible tabs<br>
<input type="checkbox" onclick="showButton()" name="lockedNav" value="true"<?php if($lockedNav) {echo ' checked';};?>> locked nav<br>
<br>
<h2>security</h2>
new password <span style="font-size: 10px; color: #888888">8 chars</span><br>
<input type="password" name="accountPassword" onkeydown="showButton()"><br>
confirm password<br>
<input type="password" name="confirmPassword" onkeydown="showButton()"><br>
<input type="hidden" name="oldPassword" value="<?php echo $accountPassword; ?>">
<br>
restricted files/folders<br>
<input type="text" onkeydown="document.settings.changedFileSettings.value='true';showButton()" name="restrictedFiles" value="<?php for($i=0;$i<=count($restrictedFiles)-1;$i++) {echo $restrictedFiles[$i]; if ($i<count($restrictedFiles)-1) {echo ', ';};}; ?>"><br>
banned files/folders<br>
<input type="text" onkeydown="document.settings.changedFileSettings.value='true';showButton()" name="bannedFiles" value="<?php for($i=0;$i<=count($bannedFiles)-1;$i++) {echo $bannedFiles[$i]; if ($i<count($bannedFiles)-1) {echo ', ';};}; ?>"><br>
<input type="hidden" name="changedFileSettings" value="false">
<br>
ip addresses<br>
<input type="text" onkeydown="showButton()" name="allowedIPs" value="<?php for($i=0;$i<=count($allowedIPs)-1;$i++) {echo $allowedIPs[$i]; if ($i<count($allowedIPs)-1) {echo ', ';};}; ?>"><br>
</div>
<div class="settingsColumn2">
<h2>plugins</h2>
plugins array <span style="font-size: 10px; color: #888888">name, img src, style, url, target, setInterval (mins)</span><br>
<textarea name="plugins" class="plugins" onkeydown="showButton()"><?php
for($i=0;$i<count($plugins);$i++) {
for($j=0;$j<count($plugins[$i]);$j++) {
echo '"'.$plugins[$i][$j].'"';
if ($j<count($plugins[$i])-1) {
echo ',';
};
if (!($i==count($plugins)-1 && $j==count($plugins[$i])-1)) {
echo PHP_EOL;
}
if (($i<count($plugins)-1 && $j==count($plugins[$i])-1)) {
echo "====================".PHP_EOL;
}
}
}
?></textarea>
<br><br>
<h2>style</h2>
theme<br>
<select onchange="selectTheme();showButton()" id="select" name="theme">
<option<?php if ($theme=="default") {echo ' selected';}; ?>>default</option>
<?php
for ($i=0;$i<count($themeArray)-1;$i++) {
if ($theme==$themeArray[$i]) {$optionSelected = ' selected';} else {$optionSelected = '';};
echo '<option'.$optionSelected.'>'.$themeArray[$i].'</option>'.PHP_EOL;
}
?>
</select>
<br><br>
<textarea id="code" name="code">
function findSequence(goal) {
function find(start,history) {
if (start==goal)
return history;
else if (start>goal)
return null;
else
return find(start+5,"("+history+"+5)") ||
find(start*3,"("+history+"*3)");
}
return find(1,"1");
}</textarea>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
readOnly: "nocursor",
theme: "<?php if ($theme=="default") {echo 'icecoder';} else {echo $theme;}; ?>"
});
var input = document.getElementById("select");
function selectTheme() {
var theme = input.options[input.selectedIndex].innerHTML;
if (theme=="default") {theme = "icecoder"};
editor.setOption("theme", theme);
}
var showButton = function() {
document.getElementById('updateButton').style.opacity = 1;
}
var showHideTabs = function() {
document.all ? strCSS = 'rules' : strCSS = 'cssRules';
document.settings.visibleTabs.checked ? document.styleSheets[2][strCSS][5].style['content'] = '"\\21e5"' : document.styleSheets[2][strCSS][5].style['content'] = '" "';
}
var validatePasswords = function() {
<?php if($_SESSION['userLevel']==10) { ?>
if (document.settings.accountPassword.value != 0 && document.settings.accountPassword.value.length<8) {
alert('Please use at least 8 chars in the password');
} else {
if (document.settings.accountPassword.value != document.settings.confirmPassword.value) {
alert('Sorry, your passwords don\'t match')
} else {
document.settings.submit();
}
}
<?php } else { ?>
alert('Sorry, you need to be logged in to change settings');
<?php ;}; ?>
}
</script>
<div class="update" id="updateButton" onClick="validatePasswords()">update</div>
</div>
</form>
</body>
</html>

View File

@@ -1,22 +1,5 @@
<?php
$versionNo = "v 0.5.9";
$codeMirrorDir = "CodeMirror-2.22";
$cMThisVer = 2.22;
$testcMVersion = false; // test if we're using the latest CodeMirror version
$restrictedFiles = array("wp-",".php",".asp",".aspx");
$bannedFiles = array("_coder","wp-",".exe");
$allowedIPs = array("*"); // allowed IPs, * for any
$plugins = array(
array("Database Admin","images/database.png","margin-top: 3px","plugins/adminer/adminer-3.3.3-mysql-en.php","_blank",""),
array("Batch Image Processor","images/images.png","margin-top: 5px","http://birme.net","_blank",""),
array("Backup","images/backup-open-files.png","margin-top: 3px","plugins/backupOpenFiles/index.php","fileControl:<b>Zipping Open Files</b>","10"),
array("Clipboard","images/clipboard.png","","javascript:alert('Doesn\'t do anything yet but will be a clipboard for copied text items, up to 100 levels')","_self","")
);
$accountPassword = "";
// ---------------
// End of settings
// ---------------
session_start();
// Function to handle salted hashing
define('SALT_LENGTH',9);
@@ -29,7 +12,107 @@ function generateHash($plainText,$salt=null) {
return $salt.sha1($salt.$plainText);
}
session_start();
// -----------------
// Start of settings
// -----------------
$versionNo = "v 0.6.7";
$codeMirrorDir = "CodeMirror-2.24";
$cMThisVer = 2.24;
$tabsIndent = true;
$testcMVersion = false;
$openLastFiles = true;
$codeAssist = true;
$visibleTabs = false;
$lockedNav = true;
$accountPassword = "";
$restrictedFiles = array("wp-",".php",".rb",".sql");
$bannedFiles = array("_coder","wp-",".exe");
$allowedIPs = array("*");
$plugins = array(
array("Database Admin","images/database.png","margin-top: 3px","plugins/adminer/adminer-3.3.3-mysql-en.php","_blank",""),
array("Batch Image Processor","images/images.png","margin-top: 5px","http://birme.net","_blank",""),
array("Backup","images/backup-open-files.png","margin-top: 3px","plugins/backupOpenFiles/index.php","fileControl:<b>Zipping Open Files</b>","10")
);
$theme = "default";
$lastOpenedFiles = "";
// ---------------
// End of settings
// ---------------
// Update this settings file?
if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
$settingsFile = 'settings.php';
$settingsContents = file_get_contents($settingsFile);
// Replace our lastOpenedFiles var with the the current
$repPosStart = strpos($settingsContents,'$tabsIndent');
$repPosEnd = strpos($settingsContents,'$lastOpenedFiles');
// Prepare all our vars
if ($_POST['tabsIndent']) {$tabsIndent = "true";} else {$tabsIndent = "false";};
if ($_POST['testcMVersion']) {$testcMVersion = "true";} else {$testcMVersion = "false";};
if ($_POST['openLastFiles']) {$openLastFiles = "true";} else {$openLastFiles = "false";};
if ($_POST['codeAssist']) {$codeAssist = "true";} else {$codeAssist = "false";};
if ($_POST['visibleTabs']) {$visibleTabs = "true";} else {$visibleTabs = "false";};
if ($_POST['lockedNav']) {$lockedNav = "true";} else {$lockedNav = "false";};
if ($_POST['accountPassword']!="") {$accountPassword = generateHash($_POST['accountPassword']);} else {$accountPassword = $_POST['oldPassword'];};
$restrictedFiles = 'array("'.str_replace(', ','","',$_POST['restrictedFiles']).'")';
$bannedFiles = 'array("'.str_replace(', ','","',$_POST['bannedFiles']).'")';
$allowedIPs = 'array("'.str_replace(', ','","',$_POST['allowedIPs']).'")';
$plugins = 'array('.PHP_EOL.' array('.PHP_EOL.' '.str_replace('====================','),'.PHP_EOL.' array(',$_POST['plugins']).'))';
$theme = $_POST['theme'];
$settingsNew = '$tabsIndent = '.$tabsIndent.';'.PHP_EOL;
$settingsNew .= '$testcMVersion = '.$testcMVersion.';'.PHP_EOL;
$settingsNew .= '$openLastFiles = '.$openLastFiles.';'.PHP_EOL;
$settingsNew .= '$codeAssist = '.$codeAssist.';'.PHP_EOL;
$settingsNew .= '$visibleTabs = '.$visibleTabs.';'.PHP_EOL;
$settingsNew .= '$lockedNav = '.$lockedNav.';'.PHP_EOL;
$settingsNew .= '$accountPassword = "'.$accountPassword.'";'.PHP_EOL;
$settingsNew .= '$restrictedFiles = '.$restrictedFiles.';'.PHP_EOL;
$settingsNew .= '$bannedFiles = '.$bannedFiles.';'.PHP_EOL;
$settingsNew .= '$allowedIPs = '.$allowedIPs.';'.PHP_EOL;
$settingsNew .= '$plugins = '.$plugins.';'.PHP_EOL;
$settingsNew .= '$theme = "'.$theme.'";'.PHP_EOL;
// Compile our new settings
$settingsContents = substr($settingsContents,0,$repPosStart).$settingsNew.substr($settingsContents,($repPosEnd),strlen($settingsContents));
// Now update this file
$fh = fopen($settingsFile, 'w') or die("can't update settings file");
fwrite($fh, $settingsContents);
fclose($fh);
// OK, now this file is updated, update our current session with new arrays
$_SESSION['restrictedFiles'] = $restrictedFiles = explode(", ",$_POST['restrictedFiles']);
$_SESSION['bannedFiles'] = $bannedFiles = explode(", ",$_POST['bannedFiles']);
$_SESSION['allowedIPs'] = $allowedIPs = explode(", ",$_POST['allowedIPs']);
// Work out the theme to use now
if ($theme=="default") {$themeURL="lib/editor.css";} else {$themeURL=$codeMirrorDir."/theme/".$theme.".css";};
// Do we need a file manager refresh?
if ($_POST['changedFileSettings']=="true") {$refreshFM="true";} else {$refreshFM="false";};
// With all that worked out, we can now hide the settings screen and apply the new settings
echo "<script>top.ICEcoder.settingsScreen('hide');top.ICEcoder.useNewSettings('".$themeURL."',".$tabsIndent.",".$codeAssist.",".$lockedNav.",".$visibleTabs.",".$refreshFM.");</script>";
}
// Save the currently opened files for next time
if (isset($_GET["saveFiles"]) && $_GET['saveFiles']) {
if ($_SESSION['userLevel'] == 10) {
$settingsFile = 'settings.php';
$settingsContents = file_get_contents($settingsFile);
// Replace our lastOpenedFiles var with the the current
$repPosStart = strpos($settingsContents,'lastOpenedFiles = "')+19;
$repPosEnd = strpos($settingsContents,'";',$repPosStart)-$repPosStart;
$settingsContents = substr($settingsContents,0,$repPosStart).$_GET['saveFiles'].substr($settingsContents,($repPosStart+$repPosEnd),strlen($settingsContents));
// Now update this file
$fh = fopen($settingsFile, 'w') or die("can't update settings file");
fwrite($fh, $settingsContents);
fclose($fh);
}
echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);</script>';
}
// Establish our user level
if (!isset($_SESSION['userLevel'])) {$_SESSION['userLevel'] = 0;};
if(isset($_POST['loginPassword']) && generateHash($_POST['loginPassword'],$accountPassword)==$accountPassword) {$_SESSION['userLevel'] = 10;};
@@ -37,6 +120,19 @@ $_SESSION['userLevel'] = $_SESSION['userLevel'];
if (!isset($_SESSION['restrictedFiles'])) {$_SESSION['restrictedFiles'] = $restrictedFiles;}
if (!isset($_SESSION['bannedFiles'])) {$_SESSION['bannedFiles'] = $bannedFiles;}
if (!isset($_SESSION['allowedIPs'])) {$_SESSION['allowedIPs'] = $allowedIPs;}
// Determin our allowed IP addresses
$allowedIP = false;
for($i=0;$i<count($_SESSION['allowedIPs']);$i++) {
if ($_SESSION['allowedIPs'][$i]==$_SERVER["REMOTE_ADDR"]||$_SESSION['allowedIPs'][$i]=="*") {
$allowedIP = true;
}
}
// If user not allowed to view, boot to site root
if (!$allowedIP) {
echo '<script>top.window.location="/";</script>';
};
// Establish our shortened URL, explode the path based on server type (Linux or Windows)
if (strpos($_SERVER['DOCUMENT_ROOT'],"/")>-1) {$slashType = "/";} else {$slashType = "\\";};
@@ -47,6 +143,56 @@ $shortURLStarts = explode($slashType,$_SERVER['DOCUMENT_ROOT']);
if ($shortURLStarts[count($shortURLStarts)-1]!="") {$trimArray=1;} else {$trimArray=2;}
$shortURLStarts = $shortURLStarts[count($shortURLStarts)-$trimArray];
// If we're updating or calling from the index.php page, do/redo plugins & last opened files
if ((isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) || strpos($_SERVER['PHP_SELF'],"index.php")>0) {
// If we're updating, we need to recreate the plugins array
if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
$plugins = array();
$pluginsArray = explode("====================",str_replace("\"","",str_replace("\r","",str_replace("\n","",$_POST['plugins']))));
for ($i=0;$i<count($pluginsArray);$i++) {
array_push($plugins, explode(",",$pluginsArray[$i]));
}
}
// Work out the plugins to display to the user
$pluginsDisplay = "";
for ($i=0;$i<count($plugins);$i++) {
$target = explode(":",$plugins[$i][4]);
$pluginsDisplay .= '<a href="'.$plugins[$i][3].'" target="'.$target[0].'"><img src="'.$plugins[$i][1].'" style="'.$plugins[$i][2].'" alt="'.$plugins[$i][0].'"></a>';
};
// If we're updating, replace the plugin display with our newly established one
if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
echo "<script>top.document.getElementById('pluginsContainer').innerHTML = '".$pluginsDisplay."';</script>";
}
// Work out what plugins we'll need to set on a setInterval
$onLoadExtras = "";
for ($i=0;$i<count($plugins);$i++) {
if ($plugins[$i][5]!="") {
$onLoadExtras .= ";top.ICEcoder.startPluginIntervals(".$i.",'".$plugins[$i][3]."','".$plugins[$i][4]."','".$plugins[$i][5]."')";
};
};
// If we're updating our settings, clear existing setIntervals & the array refs, then start new ones
if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
?>
<script>
for (i=0;i<=top.ICEcoder.pluginIntervalRefs.length-1;i++) {
clearInterval(top.ICEcoder['plugTimer'+top.ICEcoder.pluginIntervalRefs[i]]);
}
top.ICEcoder.pluginIntervalRefs = [];
<?php echo $onLoadExtras.PHP_EOL; ?>
</script>
<?php
}
// Finally, open last opened files if we need to (applies to index.php only)
if ($openLastFiles) {
$onLoadExtras .= ";top.ICEcoder.autoOpenFiles()";
}
}
// If we're due to show the settings screen
if ($accountPassword == "" && isset($_GET['settings'])) {
?>
@@ -58,7 +204,7 @@ if ($accountPassword == "" && isset($_GET['settings'])) {
<link rel="stylesheet" type="text/css" href="coder.css">
</head>
<body>
<body style="background-color: #ffffff">
<div class="screenContainer">
<div class="screenVCenter">
@@ -78,7 +224,7 @@ if ($accountPassword == "" && isset($_GET['settings'])) {
</html>
<?php
} else {
// If the password hasn't been set, set it, but only if we're including
// If the password hasn't been set, set it, but only if we're including
// from the index.php file (as this file is included from multiple places)
if ($accountPassword == "" && strpos($_SERVER['PHP_SELF'],"index.php")>0) {
// If we're setting a password
@@ -101,5 +247,15 @@ if ($accountPassword == "" && isset($_GET['settings'])) {
header('Location: lib/settings.php?settings=set');
}
}
// If we're logging in, refresh the file manager and show icons if login is correct
if(isset($_POST['loginPassword'])) {
if(isset($_POST['loginPassword']) && generateHash($_POST['loginPassword'],$accountPassword)==$accountPassword) {
$loginAttempt = 'loginOK';
} else {
$loginAttempt = 'loginFailed';
}
echo "<script>top.ICEcoder.refreshFileManager('".$loginAttempt."');</script>";
}
}
?>

Some files were not shown because too many files have changed in this diff Show More