Updated codemirror to v4.12.

Did a lot of cleanup to limit the size of the plugin.
I kept the emmet plugin.
This commit is contained in:
Francois Delpierre
2015-02-07 18:41:17 +01:00
parent fd0cde4263
commit 11722b9c82
180 changed files with 12165 additions and 5726 deletions
@@ -0,0 +1,427 @@
List of CodeMirror contributors. Updated before every release.
4r2r
Aaron Brooks
Abdelouahab
Abe Fettig
Adam Ahmed
Adam King
adanlobato
Adán Lobato
Adrian Aichner
aeroson
Ahmad Amireh
Ahmad M. Zawawi
ahoward
Akeksandr Motsjonov
Alberto González Palomo
Alberto Pose
Albert Xing
Alexander Pavlov
Alexander Schepanovski
Alexander Shvets
Alexander Solovyov
Alexandre Bique
alexey-k
Alex Piggott
Amsul
amuntean
Amy
Ananya Sen
anaran
AndersMad
Anders Nawroth
Anderson Mesquita
Andrea G
Andreas Reischuck
Andre von Houck
Andrey Fedorov
Andrey Klyuchnikov
Andrey Lushnikov
Andy Joslin
Andy Kimball
Andy Li
angelozerr
angelo.zerr@gmail.com
Ankit
Ankit Ahuja
Ansel Santosa
Anthony Grimes
Anton Kovalyov
areos
as3boyan
AtomicPages LLC
Atul Bhouraskar
Aurelian Oancea
Bastian Müller
Bem Jones-Bey
benbro
Beni Cherniavsky-Paskin
Benjamin DeCoste
Ben Keen
Bernhard Sirlinger
Bert Chang
Billy Moon
binny
B Krishna Chaitanya
Blaine G
blukat29
boomyjee
borawjm
Brandon Frohs
Brandon Wamboldt
Brett Zamir
Brian Grinstead
Brian Sletten
Bruce Mitchener
Chandra Sekhar Pydi
Charles Skelton
Cheah Chu Yeow
Chris Coyier
Chris Granger
Chris Houseknecht
Chris Morgan
Christian Oyarzun
Christopher Brown
ciaranj
CodeAnimal
ComFreek
Curtis Gagliardi
dagsta
daines
Dale Jung
Dan Bentley
Dan Heberden
Daniel, Dao Quang Minh
Daniele Di Sarli
Daniel Faust
Daniel Huigens
Daniel KJ
Daniel Neel
Daniel Parnell
Danny Yoo
darealshinji
Darius Roberts
Dave Myers
David Mignot
David Pathakjee
David Vázquez
deebugger
Deep Thought
Devon Carew
dignifiedquire
Dimage Sapelkin
domagoj412
Dominator008
Domizio Demichelis
Doug Wikle
Drew Bratcher
Drew Hintz
Drew Khoury
Dror BG
duralog
eborden
edsharp
ekhaled
Enam Mijbah Noor
Eric Allam
eustas
Fabien O'Carroll
Fabio Zendhi Nagao
Faiza Alsaied
Fauntleroy
fbuchinger
feizhang365
Felipe Lalanne
Felix Raab
Filip Noetzel
flack
ForbesLindesay
Forbes Lindesay
Ford_Lawnmower
Forrest Oliphant
Frank Wiegand
Gabriel Gheorghian
Gabriel Horner
Gabriel Nahmias
galambalazs
Gautam Mehta
gekkoe
Gerard Braad
Gergely Hegykozi
Glenn Jorde
Glenn Ruehle
Golevka
Gordon Smith
Grant Skinner
greengiant
Gregory Koberger
Guillaume Massé
Guillaume Massé
Gustavo Rodrigues
Hakan Tunc
Hans Engel
Hardest
Hasan Karahan
Herculano Campos
Hiroyuki Makino
hitsthings
Hocdoc
Ian Beck
Ian Dickinson
Ian Wehrman
Ian Wetherbee
Ice White
ICHIKAWA, Yuji
ilvalle
Ingo Richter
Irakli Gozalishvili
Ivan Kurnosov
Jacob Lee
Jakob Miland
Jakub Vrana
Jakub Vrána
James Campos
James Thorne
Jamie Hill
Jan Jongboom
jankeromnes
Jan Keromnes
Jan Odvarko
Jan T. Sott
Jared Forsyth
Jason
Jason Barnabe
Jason Grout
Jason Johnston
Jason San Jose
Jason Siefken
Jaydeep Solanki
Jean Boussier
jeffkenton
Jeff Pickhardt
jem (graphite)
Jeremy Parmenter
Jochen Berger
Johan Ask
John Connor
John Lees-Miller
John Snelson
John Van Der Loo
Jonathan Malmaud
jongalloway
Jon Malmaud
Jon Sangster
Joost-Wim Boekesteijn
Joseph Pecoraro
Joshua Newman
Josh Watzman
jots
jsoojeon
Juan Benavides Romero
Jucovschi Constantin
Juho Vuori
Justin Hileman
jwallers@gmail.com
kaniga
Ken Newman
Ken Rockot
Kevin Sawicki
Kevin Ushey
Klaus Silveira
Koh Zi Han, Cliff
komakino
Konstantin Lopuhin
koops
ks-ifware
kubelsmieci
Lanfei
Lanny
Laszlo Vidacs
leaf corcoran
Leonid Khachaturov
Leon Sorokin
Leonya Khachaturov
Liam Newman
LM
lochel
Lorenzo Stoakes
Luciano Longo
Luke Stagner
lynschinzer
Maksim Lin
Maksym Taran
Malay Majithia
Manuel Rego Casasnovas
Marat Dreizin
Marcel Gerber
Marco Aurélio
Marco Munizaga
Marcus Bointon
Marek Rudnicki
Marijn Haverbeke
Mário Gonçalves
Mario Pietsch
Mark Lentczner
Marko Bonaci
Martin Balek
Martín Gaitán
Martin Hasoň
Mason Malone
Mateusz Paprocki
Mathias Bynens
mats cronqvist
Matthew Beale
Matthias Bussonnier
Matthias BUSSONNIER
Matt McDonald
Matt Pass
Matt Sacks
mauricio
Maximilian Hils
Maxim Kraev
Max Kirsch
Max Xiantu
mbarkhau
Metatheos
Micah Dubinko
Michael Lehenbauer
Michael Zhou
Mighty Guava
Miguel Castillo
Mike
Mike Brevoort
Mike Diaz
Mike Ivanov
Mike Kadin
MinRK
Miraculix87
misfo
mloginov
Moritz Schwörer
mps
mtaran-google
Narciso Jaramillo
Nathan Williams
ndr
nerbert
nextrevision
nguillaumin
Ng Zhi An
Nicholas Bollweg
Nicholas Bollweg (Nick)
Nick Small
Niels van Groningen
nightwing
Nikita Beloglazov
Nikita Vasilyev
Nikolay Kostov
nilp0inter
Nisarg Jhaveri
nlwillia
Norman Rzepka
pablo
Page
Panupong Pasupat
paris
Patil Arpith
Patrick Stoica
Patrick Strawderman
Paul Garvin
Paul Ivanov
Pavel Feldman
Pavel Strashkin
Paweł Bartkiewicz
peteguhl
Peter Flynn
peterkroon
Peter Kroon
prasanthj
Prasanth J
Radek Piórkowski
Rahul
Randall Mason
Randy Burden
Randy Edmunds
Rasmus Erik Voel Jensen
Richard van der Meer
Richard Z.H. Wang
Robert Crossfield
Roberto Abdelkader Martínez Pérez
robertop23
Robert Plummer
Ruslan Osmanov
Ryan Prior
sabaca
Samuel Ainsworth
sandeepshetty
Sander AKA Redsandro
santec
Sascha Peilicke
satchmorun
sathyamoorthi
SCLINIC\jdecker
Scott Aikin
Scott Goodhew
Sebastian Zaha
shaund
shaun gilchrist
Shawn A
sheopory
Shiv Deepak
Shmuel Englard
Shubham Jain
silverwind
snasa
soliton4
sonson
spastorelli
srajanpaliwal
Stanislav Oaserele
Stas Kobzar
Stefan Borsje
Steffen Beyer
Steve O'Hara
stoskov
Taha Jahangir
Takuji Shimokawa
Tarmil
tel
tfjgeorge
Thaddee Tyl
TheHowl
think
Thomas Dvornik
Thomas Schmid
Tim Alby
Tim Baumann
Timothy Farrell
Timothy Hatcher
TobiasBg
Tomas-A
Tomas Varaneckas
Tom Erik Støwer
Tom MacWright
Tony Jian
Travis Heppe
Triangle717
twifkak
Vestimir Markov
vf
Vincent Woo
Volker Mische
wenli
Wesley Wiser
Will Binns-Smith
William Jamieson
William Stein
Willy
Wojtek Ptak
Xavier Mendez
Yassin N. Hassan
YNH Webdev
Yunchi Luo
Yuvi Panda
Zachary Dremann
zziuni
魏鹏刚
@@ -7,17 +7,17 @@
## Getting help ## Getting help
Community discussion, questions, and informal bug reporting is done on the Community discussion, questions, and informal bug reporting is done on the
[CodeMirror Google group](http://groups.google.com/group/codemirror). [discuss.CodeMirror forum](http://discuss.codemirror.net).
## Submitting bug reports ## Submitting bug reports
The preferred way to report bugs is to use the The preferred way to report bugs is to use the
[GitHub issue tracker](http://github.com/marijnh/CodeMirror/issues). Before [GitHub issue tracker](http://github.com/codemirror/CodeMirror/issues). Before
reporting a bug, read these pointers. reporting a bug, read these pointers.
**Note:** The issue tracker is for *bugs*, not requests for help. Questions **Note:** The issue tracker is for *bugs*, not requests for help. Questions
should be asked on the should be asked on the
[CodeMirror Google group](http://groups.google.com/group/codemirror) instead. [discuss.CodeMirror forum](http://discuss.codemirror.net) instead.
### Reporting bugs effectively ### Reporting bugs effectively
@@ -48,7 +48,7 @@ should be asked on the
## Contributing code ## Contributing code
- Make sure you have a [GitHub Account](https://github.com/signup/free) - Make sure you have a [GitHub Account](https://github.com/signup/free)
- Fork [CodeMirror](https://github.com/marijnh/CodeMirror/) - Fork [CodeMirror](https://github.com/codemirror/CodeMirror/)
([how to fork a repo](https://help.github.com/articles/fork-a-repo)) ([how to fork a repo](https://help.github.com/articles/fork-a-repo))
- Make your changes - Make your changes
- If your changes are easy to test or likely to regress, add tests. - If your changes are easy to test or likely to regress, add tests.
@@ -70,3 +70,7 @@ should be asked on the
- Note that the linter (`bin/lint`) which is run after each commit - Note that the linter (`bin/lint`) which is run after each commit
complains about unused variables and functions. Prefix their names complains about unused variables and functions. Prefix their names
with an underscore to muffle it. with an underscore to muffle it.
- CodeMirror does *not* follow JSHint or JSLint prescribed style.
Patches that try to 'fix' code to pass one of these linters will be
unceremoniously discarded.
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (C) 2013 by Marijn Haverbeke <marijnh@gmail.com> and others Copyright (C) 2014 by Marijn Haverbeke <marijnh@gmail.com> and others
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
# CodeMirror # CodeMirror
[![Build Status](https://secure.travis-ci.org/marijnh/CodeMirror.png?branch=master)](http://travis-ci.org/marijnh/CodeMirror) [![Build Status](https://travis-ci.org/codemirror/CodeMirror.svg)](https://travis-ci.org/codemirror/CodeMirror)
[![NPM version](https://badge.fury.io/js/codemirror.png)](http://badge.fury.io/js/codemirror) [![NPM version](https://img.shields.io/npm/v/codemirror.svg)](https://www.npmjs.org/package/codemirror)
CodeMirror is a JavaScript component that provides a code editor in CodeMirror is a JavaScript component that provides a code editor in
the browser. When a mode is available for the language you are coding the browser. When a mode is available for the language you are coding
@@ -8,4 +8,4 @@ in, it will color your code, and optionally help with indentation.
The project page is http://codemirror.net The project page is http://codemirror.net
The manual is at http://codemirror.net/doc/manual.html The manual is at http://codemirror.net/doc/manual.html
The contributing guidelines are in [CONTRIBUTING.md](https://github.com/marijnh/CodeMirror/blob/master/CONTRIBUTING.md) The contributing guidelines are in [CONTRIBUTING.md](https://github.com/codemirror/CodeMirror/blob/master/CONTRIBUTING.md)
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -106,7 +109,7 @@
CodeMirror.defineExtension("uncomment", function(from, to, options) { CodeMirror.defineExtension("uncomment", function(from, to, options) {
if (!options) options = noOptions; if (!options) options = noOptions;
var self = this, mode = self.getModeAt(from); var self = this, mode = self.getModeAt(from);
var end = Math.min(to.line, self.lastLine()), start = Math.min(from.line, end); var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);
// Try finding line comments // Try finding line comments
var lineString = options.lineComment || mode.lineComment, lines = []; var lineString = options.lineComment || mode.lineComment, lines = [];
@@ -150,6 +153,17 @@
!/comment/.test(self.getTokenTypeAt(Pos(end, close + 1)))) !/comment/.test(self.getTokenTypeAt(Pos(end, close + 1))))
return false; return false;
// Avoid killing block comments completely outside the selection.
// Positions of the last startString before the start of the selection, and the first endString after it.
var lastStart = startLine.lastIndexOf(startString, from.ch);
var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length);
if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false;
// Positions of the first endString after the end of the selection, and the last startString before it.
firstEnd = endLine.indexOf(endString, to.ch);
var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch);
lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart;
if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false;
self.operation(function() { self.operation(function() {
self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)), self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)),
Pos(end, close + endString.length)); Pos(end, close + endString.length));
@@ -0,0 +1,85 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
var modes = ["clike", "css", "javascript"];
for (var i = 0; i < modes.length; ++i)
CodeMirror.extendMode(modes[i], {blockCommentContinue: " * "});
function continueComment(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), mode, inserts = [];
for (var i = 0; i < ranges.length; i++) {
var pos = ranges[i].head, token = cm.getTokenAt(pos);
if (token.type != "comment") return CodeMirror.Pass;
var modeHere = CodeMirror.innerMode(cm.getMode(), token.state).mode;
if (!mode) mode = modeHere;
else if (mode != modeHere) return CodeMirror.Pass;
var insert = null;
if (mode.blockCommentStart && mode.blockCommentContinue) {
var end = token.string.indexOf(mode.blockCommentEnd);
var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found;
if (end != -1 && end == token.string.length - mode.blockCommentEnd.length && pos.ch >= end) {
// Comment ended, don't continue it
} else if (token.string.indexOf(mode.blockCommentStart) == 0) {
insert = full.slice(0, token.start);
if (!/^\s*$/.test(insert)) {
insert = "";
for (var j = 0; j < token.start; ++j) insert += " ";
}
} else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 &&
found + mode.blockCommentContinue.length > token.start &&
/^\s*$/.test(full.slice(0, found))) {
insert = full.slice(0, found);
}
if (insert != null) insert += mode.blockCommentContinue;
}
if (insert == null && mode.lineComment && continueLineCommentEnabled(cm)) {
var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment);
if (found > -1) {
insert = line.slice(0, found);
if (/\S/.test(insert)) insert = null;
else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\s*/)[0];
}
}
if (insert == null) return CodeMirror.Pass;
inserts[i] = "\n" + insert;
}
cm.operation(function() {
for (var i = ranges.length - 1; i >= 0; i--)
cm.replaceRange(inserts[i], ranges[i].from(), ranges[i].to(), "+insert");
});
}
function continueLineCommentEnabled(cm) {
var opt = cm.getOption("continueComments");
if (opt && typeof opt == "object")
return opt.continueLineComment !== false;
return true;
}
CodeMirror.defineOption("continueComments", null, function(cm, val, prev) {
if (prev && prev != CodeMirror.Init)
cm.removeKeyMap("continueComment");
if (val) {
var key = "Enter";
if (typeof val == "string")
key = val;
else if (typeof val == "object" && val.key)
key = val.key;
var map = {name: "continueComment"};
map[key] = continueComment;
cm.addKeyMap(map);
}
});
});
+45 -20
View File
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Open simple dialogs on top of an editor. Relies on dialog.css. // Open simple dialogs on top of an editor. Relies on dialog.css.
(function(mod) { (function(mod) {
@@ -12,11 +15,11 @@
var wrap = cm.getWrapperElement(); var wrap = cm.getWrapperElement();
var dialog; var dialog;
dialog = wrap.appendChild(document.createElement("div")); dialog = wrap.appendChild(document.createElement("div"));
if (bottom) { if (bottom)
dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom"; dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
} else { else
dialog.className = "CodeMirror-dialog CodeMirror-dialog-top"; dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
}
if (typeof template == "string") { if (typeof template == "string") {
dialog.innerHTML = template; dialog.innerHTML = template;
} else { // Assuming it's a detached DOM element. } else { // Assuming it's a detached DOM element.
@@ -32,40 +35,59 @@
} }
CodeMirror.defineExtension("openDialog", function(template, callback, options) { CodeMirror.defineExtension("openDialog", function(template, callback, options) {
if (!options) options = {};
closeNotification(this, null); closeNotification(this, null);
var dialog = dialogDiv(this, template, options && options.bottom);
var dialog = dialogDiv(this, template, options.bottom);
var closed = false, me = this; var closed = false, me = this;
function close() { function close(newVal) {
if (closed) return; if (typeof newVal == 'string') {
closed = true; inp.value = newVal;
dialog.parentNode.removeChild(dialog); } else {
if (closed) return;
closed = true;
dialog.parentNode.removeChild(dialog);
me.focus();
if (options.onClose) options.onClose(dialog);
}
} }
var inp = dialog.getElementsByTagName("input")[0], button; var inp = dialog.getElementsByTagName("input")[0], button;
if (inp) { if (inp) {
if (options && options.value) inp.value = options.value; if (options.value) {
inp.value = options.value;
inp.select();
}
if (options.onInput)
CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);});
if (options.onKeyUp)
CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
CodeMirror.on(inp, "keydown", function(e) { CodeMirror.on(inp, "keydown", function(e) {
if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
if (e.keyCode == 13 || e.keyCode == 27) { if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) {
inp.blur(); inp.blur();
CodeMirror.e_stop(e); CodeMirror.e_stop(e);
close(); close();
me.focus();
if (e.keyCode == 13) callback(inp.value);
} }
if (e.keyCode == 13) callback(inp.value, e);
}); });
if (options && options.onKeyUp) {
CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
}
if (options && options.value) inp.value = options.value;
inp.focus(); inp.focus();
CodeMirror.on(inp, "blur", close);
} else if (button = dialog.getElementsByTagName("button")[0]) { } else if (button = dialog.getElementsByTagName("button")[0]) {
CodeMirror.on(button, "click", function() { CodeMirror.on(button, "click", function() {
close(); close();
me.focus(); me.focus();
}); });
if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close);
button.focus(); button.focus();
CodeMirror.on(button, "blur", close);
} }
return close; return close;
}); });
@@ -110,8 +132,8 @@
CodeMirror.defineExtension("openNotification", function(template, options) { CodeMirror.defineExtension("openNotification", function(template, options) {
closeNotification(this, close); closeNotification(this, close);
var dialog = dialogDiv(this, template, options && options.bottom); var dialog = dialogDiv(this, template, options && options.bottom);
var duration = options && (options.duration === undefined ? 5000 : options.duration);
var closed = false, doneTimer; var closed = false, doneTimer;
var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000;
function close() { function close() {
if (closed) return; if (closed) return;
@@ -124,7 +146,10 @@
CodeMirror.e_preventDefault(e); CodeMirror.e_preventDefault(e);
close(); close();
}); });
if (duration) if (duration)
doneTimer = setTimeout(close, options.duration); doneTimer = setTimeout(close, duration);
return close;
}); });
}); });
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -0,0 +1,94 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
CodeMirror.defineExtension("addPanel", function(node, options) {
if (!this.state.panels) initPanels(this);
var info = this.state.panels;
if (options && options.position == "bottom")
info.wrapper.appendChild(node);
else
info.wrapper.insertBefore(node, info.wrapper.firstChild);
var height = (options && options.height) || node.offsetHeight;
this._setSize(null, info.heightLeft -= height);
info.panels++;
return new Panel(this, node, options, height);
});
function Panel(cm, node, options, height) {
this.cm = cm;
this.node = node;
this.options = options;
this.height = height;
this.cleared = false;
}
Panel.prototype.clear = function() {
if (this.cleared) return;
this.cleared = true;
var info = this.cm.state.panels;
this.cm._setSize(null, info.heightLeft += this.height);
info.wrapper.removeChild(this.node);
if (--info.panels == 0) removePanels(this.cm);
};
Panel.prototype.changed = function(height) {
var newHeight = height == null ? this.node.offsetHeight : height;
var info = this.cm.state.panels;
this.cm._setSize(null, info.height += (newHeight - this.height));
this.height = newHeight;
};
function initPanels(cm) {
var wrap = cm.getWrapperElement();
var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle;
var height = parseInt(style.height);
var info = cm.state.panels = {
setHeight: wrap.style.height,
heightLeft: height,
panels: 0,
wrapper: document.createElement("div")
};
wrap.parentNode.insertBefore(info.wrapper, wrap);
var hasFocus = cm.hasFocus();
info.wrapper.appendChild(wrap);
if (hasFocus) cm.focus();
cm._setSize = cm.setSize;
if (height != null) cm.setSize = function(width, newHeight) {
if (newHeight == null) return this._setSize(width, newHeight);
info.setHeight = newHeight;
if (typeof newHeight != "number") {
var px = /^(\d+\.?\d*)px$/.exec(newHeight);
if (px) {
newHeight = Number(px[1]);
} else {
info.wrapper.style.height = newHeight;
newHeight = info.wrapper.offsetHeight;
info.wrapper.style.height = "";
}
}
cm._setSize(width, info.heightLeft += (newHeight - height));
height = newHeight;
};
}
function removePanels(cm) {
var info = cm.state.panels;
cm.state.panels = null;
var wrap = cm.getWrapperElement();
info.wrapper.parentNode.replaceChild(wrap, info.wrapper);
wrap.style.height = info.setHeight;
cm.setSize = cm._setSize;
cm.setSize();
}
});
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -0,0 +1,64 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineOption("rulers", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) {
clearRulers(cm);
cm.off("refresh", refreshRulers);
}
if (val && val.length) {
setRulers(cm);
cm.on("refresh", refreshRulers);
}
});
function clearRulers(cm) {
for (var i = cm.display.lineSpace.childNodes.length - 1; i >= 0; i--) {
var node = cm.display.lineSpace.childNodes[i];
if (/(^|\s)CodeMirror-ruler($|\s)/.test(node.className))
node.parentNode.removeChild(node);
}
}
function setRulers(cm) {
var val = cm.getOption("rulers");
var cw = cm.defaultCharWidth();
var left = cm.charCoords(CodeMirror.Pos(cm.firstLine(), 0), "div").left;
var minH = cm.display.scroller.offsetHeight + 30;
for (var i = 0; i < val.length; i++) {
var elt = document.createElement("div");
elt.className = "CodeMirror-ruler";
var col, cls = null, conf = val[i];
if (typeof conf == "number") {
col = conf;
} else {
col = conf.column;
if (conf.className) elt.className += " " + conf.className;
if (conf.color) elt.style.borderColor = conf.color;
if (conf.lineStyle) elt.style.borderLeftStyle = conf.lineStyle;
if (conf.width) elt.style.borderLeftWidth = conf.width;
cls = val[i].className;
}
elt.style.left = (left + col * cw) + "px";
elt.style.top = "-50px";
elt.style.bottom = "-20px";
elt.style.minHeight = minH + "px";
cm.display.lineSpace.insertBefore(elt, cm.display.cursorDiv);
}
}
function refreshRulers(cm) {
clearRulers(cm);
setRulers(cm);
}
});
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -10,6 +13,8 @@
var DEFAULT_EXPLODE_ON_ENTER = "[]{}"; var DEFAULT_EXPLODE_ON_ENTER = "[]{}";
var SPACE_CHAR_REGEX = /\s/; var SPACE_CHAR_REGEX = /\s/;
var Pos = CodeMirror.Pos;
CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) { CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
if (old != CodeMirror.Init && old) if (old != CodeMirror.Init && old)
cm.removeKeyMap("autoCloseBrackets"); cm.removeKeyMap("autoCloseBrackets");
@@ -26,11 +31,27 @@
}); });
function charsAround(cm, pos) { function charsAround(cm, pos) {
var str = cm.getRange(CodeMirror.Pos(pos.line, pos.ch - 1), var str = cm.getRange(Pos(pos.line, pos.ch - 1),
CodeMirror.Pos(pos.line, pos.ch + 1)); Pos(pos.line, pos.ch + 1));
return str.length == 2 ? str : null; return str.length == 2 ? str : null;
} }
// Project the token type that will exists after the given char is
// typed, and use it to determine whether it would cause the start
// of a string token.
function enteringString(cm, pos, ch) {
var line = cm.getLine(pos.line);
var token = cm.getTokenAt(pos);
if (/\bstring2?\b/.test(token.type)) return false;
var stream = new CodeMirror.StringStream(line.slice(0, pos.ch) + ch + line.slice(pos.ch), 4);
stream.pos = stream.start = token.start;
for (;;) {
var type1 = cm.getMode().token(stream, token.state);
if (stream.pos >= pos.ch + 1) return /\bstring2?\b/.test(type1);
stream.start = stream.pos;
}
}
function buildKeymap(pairs) { function buildKeymap(pairs) {
var map = { var map = {
name : "autoCloseBrackets", name : "autoCloseBrackets",
@@ -44,53 +65,68 @@
} }
for (var i = ranges.length - 1; i >= 0; i--) { for (var i = ranges.length - 1; i >= 0; i--) {
var cur = ranges[i].head; var cur = ranges[i].head;
cm.replaceRange("", CodeMirror.Pos(cur.line, cur.ch - 1), CodeMirror.Pos(cur.line, cur.ch + 1)); cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
} }
} }
}; };
var closingBrackets = ""; var closingBrackets = "";
for (var i = 0; i < pairs.length; i += 2) (function(left, right) { for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
if (left != right) closingBrackets += right; closingBrackets += right;
map["'" + left + "'"] = function(cm) { map["'" + left + "'"] = function(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass; if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), type, next; var ranges = cm.listSelections(), type, next;
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
var range = ranges[i], cur = range.head, curType; var range = ranges[i], cur = range.head, curType;
if (left == "'" && cm.getTokenTypeAt(cur) == "comment") var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
return CodeMirror.Pass; if (!range.empty()) {
var next = cm.getRange(cur, CodeMirror.Pos(cur.line, cur.ch + 1));
if (!range.empty())
curType = "surround"; curType = "surround";
else if (left == right && next == right) } else if (left == right && next == right) {
curType = "skip"; if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left)
else if (left == right && CodeMirror.isWordChar(next)) curType = "skipThree";
return CodeMirror.Pass; else
else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) curType = "skip";
} else if (left == right && cur.ch > 1 &&
cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left &&
(cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left)) {
curType = "addFour";
} else if (left == '"' || left == "'") {
if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, left)) curType = "both";
else return CodeMirror.Pass;
} else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) {
curType = "both"; curType = "both";
else } else {
return CodeMirror.Pass; return CodeMirror.Pass;
}
if (!type) type = curType; if (!type) type = curType;
else if (type != curType) return CodeMirror.Pass; else if (type != curType) return CodeMirror.Pass;
} }
if (type == "skip") { cm.operation(function() {
cm.execCommand("goCharRight"); if (type == "skip") {
} else if (type == "surround") { cm.execCommand("goCharRight");
var sels = cm.getSelections(); } else if (type == "skipThree") {
for (var i = 0; i < sels.length; i++) for (var i = 0; i < 3; i++)
sels[i] = left + sels[i] + right; cm.execCommand("goCharRight");
cm.replaceSelections(sels, "around"); } else if (type == "surround") {
} else if (type == "both") { var sels = cm.getSelections();
cm.replaceSelection(left + right, null); for (var i = 0; i < sels.length; i++)
cm.execCommand("goCharLeft"); sels[i] = left + sels[i] + right;
} cm.replaceSelections(sels, "around");
} else if (type == "both") {
cm.replaceSelection(left + right, null);
cm.execCommand("goCharLeft");
} else if (type == "addFour") {
cm.replaceSelection(left + left + left + left, "before");
cm.execCommand("goCharRight");
}
});
}; };
if (left != right) map["'" + right + "'"] = function(cm) { if (left != right) map["'" + right + "'"] = function(cm) {
var ranges = cm.listSelections(); var ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
var range = ranges[i]; var range = ranges[i];
if (!range.empty() || if (!range.empty() ||
cm.getRange(range.head, CodeMirror.Pos(range.head.line, range.head.ch + 1)) != right) cm.getRange(range.head, Pos(range.head.line, range.head.ch + 1)) != right)
return CodeMirror.Pass; return CodeMirror.Pass;
} }
cm.execCommand("goCharRight"); cm.execCommand("goCharRight");
+58 -8
View File
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
/** /**
* Tag-closer extension for CodeMirror. * Tag-closer extension for CodeMirror.
* *
@@ -55,6 +58,7 @@
var pos = ranges[i].head, tok = cm.getTokenAt(pos); var pos = ranges[i].head, tok = cm.getTokenAt(pos);
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass; if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass;
var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html"; var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html";
var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose); var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent); var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
@@ -68,8 +72,7 @@
tok.type == "tag" && state.type == "closeTag" || tok.type == "tag" && state.type == "closeTag" ||
tok.string.indexOf("/") == (tok.string.length - 1) || // match something like <someTagName /> tok.string.indexOf("/") == (tok.string.length - 1) || // match something like <someTagName />
dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 || dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||
CodeMirror.scanForClosingTag && CodeMirror.scanForClosingTag(cm, pos, tagName, closingTagExists(cm, tagName, pos, state, true))
Math.min(cm.lastLine() + 1, pos.line + 50)))
return CodeMirror.Pass; return CodeMirror.Pass;
var indent = indentTags && indexOf(indentTags, lowerTagName) > -1; var indent = indentTags && indexOf(indentTags, lowerTagName) > -1;
@@ -91,26 +94,73 @@
} }
} }
function autoCloseSlash(cm) { function autoCloseCurrent(cm, typingSlash) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), replacements = []; var ranges = cm.listSelections(), replacements = [];
var head = typingSlash ? "/" : "</";
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass; if (!ranges[i].empty()) return CodeMirror.Pass;
var pos = ranges[i].head, tok = cm.getTokenAt(pos); var pos = ranges[i].head, tok = cm.getTokenAt(pos);
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
if (tok.type == "string" || tok.string.charAt(0) != "<" || if (typingSlash && (tok.type == "string" || tok.string.charAt(0) != "<" ||
tok.start != pos.ch - 1 || inner.mode.name != "xml" || tok.start != pos.ch - 1))
!state.context || !state.context.tagName)
return CodeMirror.Pass; return CodeMirror.Pass;
replacements[i] = "/" + state.context.tagName + ">"; // Kludge to get around the fact that we are not in XML mode
// when completing in JS/CSS snippet in htmlmixed mode. Does not
// work for other XML embedded languages (there is no general
// way to go from a mixed mode to its current XML state).
if (inner.mode.name != "xml") {
if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript")
replacements[i] = head + "script>";
else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css")
replacements[i] = head + "style>";
else
return CodeMirror.Pass;
} else {
if (!state.context || !state.context.tagName ||
closingTagExists(cm, state.context.tagName, pos, state))
return CodeMirror.Pass;
replacements[i] = head + state.context.tagName + ">";
}
} }
cm.replaceSelections(replacements); cm.replaceSelections(replacements);
ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++)
if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)
cm.indentLine(ranges[i].head.line);
} }
function autoCloseSlash(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
autoCloseCurrent(cm, true);
}
CodeMirror.commands.closeTag = function(cm) { return autoCloseCurrent(cm); };
function indexOf(collection, elt) { function indexOf(collection, elt) {
if (collection.indexOf) return collection.indexOf(elt); if (collection.indexOf) return collection.indexOf(elt);
for (var i = 0, e = collection.length; i < e; ++i) for (var i = 0, e = collection.length; i < e; ++i)
if (collection[i] == elt) return i; if (collection[i] == elt) return i;
return -1; return -1;
} }
// If xml-fold is loaded, we use its functionality to try and verify
// whether a given tag is actually unclosed.
function closingTagExists(cm, tagName, pos, state, newTag) {
if (!CodeMirror.scanForClosingTag) return false;
var end = Math.min(cm.lastLine() + 1, pos.line + 500);
var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end);
if (!nextClose || nextClose.tag != tagName) return false;
var cx = state.context;
// If the immediate wrapping context contains onCx instances of
// the same tag, a closing tag only exists if there are at least
// that many closing tags of that type following.
for (var onCx = newTag ? 1 : 0; cx && cx.tagName == tagName; cx = cx.prev) ++onCx;
pos = nextClose.to;
for (var i = 1; i < onCx; i++) {
var next = CodeMirror.scanForClosingTag(cm, pos, null, end);
if (!next || next.tag != tagName) return false;
pos = next.to;
}
return true;
}
}); });
@@ -1,44 +0,0 @@
(function() {
var modes = ["clike", "css", "javascript"];
for (var i = 0; i < modes.length; ++i)
CodeMirror.extendMode(modes[i], {blockCommentStart: "/*",
blockCommentEnd: "*/",
blockCommentContinue: " * "});
function continueComment(cm) {
var pos = cm.getCursor(), token = cm.getTokenAt(pos);
var mode = CodeMirror.innerMode(cm.getMode(), token.state).mode;
var space;
if (token.type == "comment" && mode.blockCommentStart) {
var end = token.string.indexOf(mode.blockCommentEnd);
var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found;
if (end != -1 && end == token.string.length - mode.blockCommentEnd.length) {
// Comment ended, don't continue it
} else if (token.string.indexOf(mode.blockCommentStart) == 0) {
space = full.slice(0, token.start);
if (!/^\s*$/.test(space)) {
space = "";
for (var i = 0; i < token.start; ++i) space += " ";
}
} else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 &&
found + mode.blockCommentContinue.length > token.start &&
/^\s*$/.test(full.slice(0, found))) {
space = full.slice(0, found);
}
}
if (space != null)
cm.replaceSelection("\n" + space + mode.blockCommentContinue, "end");
else
return CodeMirror.Pass;
}
CodeMirror.defineOption("continueComments", null, function(cm, val, prev) {
if (prev && prev != CodeMirror.Init)
cm.removeKeyMap("continueComment");
var map = {name: "continueComment"};
map[typeof val == "string" ? val : "Enter"] = continueComment;
cm.addKeyMap(map);
});
})();
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -8,26 +11,39 @@
})(function(CodeMirror) { })(function(CodeMirror) {
"use strict"; "use strict";
var listRE = /^(\s*)([*+-]|(\d+)\.)(\s*)/, var listRE = /^(\s*)(>[> ]*|[*+-]\s|(\d+)\.)(\s*)/,
unorderedBullets = "*+-"; emptyListRE = /^(\s*)(>[> ]*|[*+-]|(\d+)\.)(\s*)$/,
unorderedListRE = /[*+-]\s/;
CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) { CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass; if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), replacements = []; var ranges = cm.listSelections(), replacements = [];
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
var pos = ranges[i].head, match; var pos = ranges[i].head, match;
var inList = cm.getStateAfter(pos.line).list !== false; var eolState = cm.getStateAfter(pos.line);
var inList = eolState.list !== false;
var inQuote = eolState.quote !== false;
if (!ranges[i].empty() || !inList || !(match = cm.getLine(pos.line).match(listRE))) { if (!ranges[i].empty() || (!inList && !inQuote) || !(match = cm.getLine(pos.line).match(listRE))) {
cm.execCommand("newlineAndIndent"); cm.execCommand("newlineAndIndent");
return; return;
} }
var indent = match[1], after = match[4]; if (cm.getLine(pos.line).match(emptyListRE)) {
var bullet = unorderedBullets.indexOf(match[2]) >= 0 cm.replaceRange("", {
? match[2] line: pos.line, ch: 0
: (parseInt(match[3], 10) + 1) + "."; }, {
line: pos.line, ch: pos.ch + 1
});
replacements[i] = "\n";
replacements[i] = "\n" + indent + bullet + after; } else {
var indent = match[1], after = match[4];
var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0
? match[2]
: (parseInt(match[3], 10) + 1) + ".";
replacements[i] = "\n" + indent + bullet + after;
}
} }
cm.replaceSelections(replacements); cm.replaceSelections(replacements);
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -22,15 +25,24 @@
var style = cm.getTokenTypeAt(Pos(where.line, pos + 1)); var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config); var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
if (found == null) return null;
return {from: Pos(where.line, pos), to: found && found.pos, return {from: Pos(where.line, pos), to: found && found.pos,
match: found && found.ch == match.charAt(0), forward: dir > 0}; match: found && found.ch == match.charAt(0), forward: dir > 0};
} }
// bracketRegex is used to specify which type of bracket to scan
// should be a regexp, e.g. /[[\]]/
//
// Note: If "where" is on an open bracket, then this bracket is ignored.
//
// Returns false when no bracket was found, null when it reached
// maxScanLines and gave up
function scanForBracket(cm, where, dir, style, config) { function scanForBracket(cm, where, dir, style, config) {
var maxScanLen = (config && config.maxScanLineLength) || 10000; var maxScanLen = (config && config.maxScanLineLength) || 10000;
var maxScanLines = (config && config.maxScanLines) || 500; var maxScanLines = (config && config.maxScanLines) || 1000;
var stack = [], re = /[(){}[\]]/; var stack = [];
var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/;
var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1)
: Math.max(cm.firstLine() - 1, where.line - maxScanLines); : Math.max(cm.firstLine() - 1, where.line - maxScanLines);
for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) { for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {
@@ -49,6 +61,7 @@
} }
} }
} }
return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null;
} }
function matchBrackets(cm, autoclear, config) { function matchBrackets(cm, autoclear, config) {
@@ -57,11 +70,10 @@
var marks = [], ranges = cm.listSelections(); var marks = [], ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config); var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config);
if (match && cm.getLine(match.from.line).length <= maxHighlightLen && if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {
match.to && cm.getLine(match.to.line).length <= maxHighlightLen) {
var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style})); marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
if (match.to) if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen)
marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style})); marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style}));
} }
} }
@@ -99,10 +111,10 @@
}); });
CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);}); CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
CodeMirror.defineExtension("findMatchingBracket", function(pos, strict){ CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){
return findMatchingBracket(this, pos, strict); return findMatchingBracket(this, pos, strict, config);
}); });
CodeMirror.defineExtension("scanForBracket", function(pos, dir, style){ CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){
return scanForBracket(this, pos, dir, style); return scanForBracket(this, pos, dir, style, config);
}); });
}); });
@@ -0,0 +1,66 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../fold/xml-fold"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineOption("matchTags", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) {
cm.off("cursorActivity", doMatchTags);
cm.off("viewportChange", maybeUpdateMatch);
clear(cm);
}
if (val) {
cm.state.matchBothTags = typeof val == "object" && val.bothTags;
cm.on("cursorActivity", doMatchTags);
cm.on("viewportChange", maybeUpdateMatch);
doMatchTags(cm);
}
});
function clear(cm) {
if (cm.state.tagHit) cm.state.tagHit.clear();
if (cm.state.tagOther) cm.state.tagOther.clear();
cm.state.tagHit = cm.state.tagOther = null;
}
function doMatchTags(cm) {
cm.state.failedTagMatch = false;
cm.operation(function() {
clear(cm);
if (cm.somethingSelected()) return;
var cur = cm.getCursor(), range = cm.getViewport();
range.from = Math.min(range.from, cur.line); range.to = Math.max(cur.line + 1, range.to);
var match = CodeMirror.findMatchingTag(cm, cur, range);
if (!match) return;
if (cm.state.matchBothTags) {
var hit = match.at == "open" ? match.open : match.close;
if (hit) cm.state.tagHit = cm.markText(hit.from, hit.to, {className: "CodeMirror-matchingtag"});
}
var other = match.at == "close" ? match.open : match.close;
if (other)
cm.state.tagOther = cm.markText(other.from, other.to, {className: "CodeMirror-matchingtag"});
else
cm.state.failedTagMatch = true;
});
}
function maybeUpdateMatch(cm) {
if (cm.state.failedTagMatch) doMatchTags(cm);
}
CodeMirror.commands.toMatchingTag = function(cm) {
var found = CodeMirror.findMatchingTag(cm, cm.getCursor());
if (found) {
var other = found.at == "close" ? found.open : found.close;
if (other) cm.extendSelection(other.to, other.from);
}
};
});
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
+40 -8
View File
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -9,10 +12,14 @@
"use strict"; "use strict";
function doFold(cm, pos, options, force) { function doFold(cm, pos, options, force) {
var finder = options && (options.call ? options : options.rangeFinder); if (options && options.call) {
if (!finder) finder = CodeMirror.fold.auto; var finder = options;
options = null;
} else {
var finder = getOption(cm, options, "rangeFinder");
}
if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0); if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0);
var minSize = options && options.minFoldSize || 0; var minSize = getOption(cm, options, "minFoldSize");
function getRange(allowFolded) { function getRange(allowFolded) {
var range = finder(cm, pos); var range = finder(cm, pos);
@@ -29,14 +36,17 @@
} }
var range = getRange(true); var range = getRange(true);
if (options && options.scanUp) while (!range && pos.line > cm.firstLine()) { if (getOption(cm, options, "scanUp")) while (!range && pos.line > cm.firstLine()) {
pos = CodeMirror.Pos(pos.line - 1, 0); pos = CodeMirror.Pos(pos.line - 1, 0);
range = getRange(false); range = getRange(false);
} }
if (!range || range.cleared || force === "unfold") return; if (!range || range.cleared || force === "unfold") return;
var myWidget = makeWidget(options); var myWidget = makeWidget(cm, options);
CodeMirror.on(myWidget, "mousedown", function() { myRange.clear(); }); CodeMirror.on(myWidget, "mousedown", function(e) {
myRange.clear();
CodeMirror.e_preventDefault(e);
});
var myRange = cm.markText(range.from, range.to, { var myRange = cm.markText(range.from, range.to, {
replacedWith: myWidget, replacedWith: myWidget,
clearOnEnter: true, clearOnEnter: true,
@@ -48,8 +58,8 @@
CodeMirror.signal(cm, "fold", cm, range.from, range.to); CodeMirror.signal(cm, "fold", cm, range.from, range.to);
} }
function makeWidget(options) { function makeWidget(cm, options) {
var widget = (options && options.widget) || "\u2194"; var widget = getOption(cm, options, "widget");
if (typeof widget == "string") { if (typeof widget == "string") {
var text = document.createTextNode(widget); var text = document.createTextNode(widget);
widget = document.createElement("span"); widget = document.createElement("span");
@@ -114,4 +124,26 @@
if (cur) return cur; if (cur) return cur;
} }
}); });
var defaultOptions = {
rangeFinder: CodeMirror.fold.auto,
widget: "\u2194",
minFoldSize: 0,
scanUp: false
};
CodeMirror.defineOption("foldOptions", null);
function getOption(cm, options, name) {
if (options && options[name] !== undefined)
return options[name];
var editorOptions = cm.options.foldOptions;
if (editorOptions && editorOptions[name] !== undefined)
return editorOptions[name];
return defaultOptions[name];
}
CodeMirror.defineExtension("foldOption", function(options, name) {
return getOption(this, options, name);
});
}); });
@@ -10,7 +10,6 @@
} }
.CodeMirror-foldgutter-open, .CodeMirror-foldgutter-open,
.CodeMirror-foldgutter-folded { .CodeMirror-foldgutter-folded {
color: #555;
cursor: pointer; cursor: pointer;
} }
.CodeMirror-foldgutter-open:after { .CodeMirror-foldgutter-open:after {
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("./foldcode")); mod(require("../../lib/codemirror"), require("./foldcode"));
@@ -55,7 +58,7 @@
function marker(spec) { function marker(spec) {
if (typeof spec == "string") { if (typeof spec == "string") {
var elt = document.createElement("div"); var elt = document.createElement("div");
elt.className = spec; elt.className = spec + " CodeMirror-guttermarker-subtle";
return elt; return elt;
} else { } else {
return spec.cloneNode(true); return spec.cloneNode(true);
@@ -64,14 +67,16 @@
function updateFoldInfo(cm, from, to) { function updateFoldInfo(cm, from, to) {
var opts = cm.state.foldGutter.options, cur = from; var opts = cm.state.foldGutter.options, cur = from;
var minSize = cm.foldOption(opts, "minFoldSize");
var func = cm.foldOption(opts, "rangeFinder");
cm.eachLine(from, to, function(line) { cm.eachLine(from, to, function(line) {
var mark = null; var mark = null;
if (isFolded(cm, cur)) { if (isFolded(cm, cur)) {
mark = marker(opts.indicatorFolded); mark = marker(opts.indicatorFolded);
} else { } else {
var pos = Pos(cur, 0), func = opts.rangeFinder || CodeMirror.fold.auto; var pos = Pos(cur, 0);
var range = func && func(cm, pos); var range = func && func(cm, pos);
if (range && range.from.line + 1 < range.to.line) if (range && range.to.line - range.from.line >= minSize)
mark = marker(opts.indicatorOpen); mark = marker(opts.indicatorOpen);
} }
cm.setGutterMarker(line, opts.gutter, mark); cm.setGutterMarker(line, opts.gutter, mark);
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -0,0 +1,49 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.registerHelper("fold", "markdown", function(cm, start) {
var maxDepth = 100;
function isHeader(lineNo) {
var tokentype = cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0));
return tokentype && /\bheader\b/.test(tokentype);
}
function headerLevel(lineNo, line, nextLine) {
var match = line && line.match(/^#+/);
if (match && isHeader(lineNo)) return match[0].length;
match = nextLine && nextLine.match(/^[=\-]+\s*$/);
if (match && isHeader(lineNo + 1)) return nextLine[0] == "=" ? 1 : 2;
return maxDepth;
}
var firstLine = cm.getLine(start.line), nextLine = cm.getLine(start.line + 1);
var level = headerLevel(start.line, firstLine, nextLine);
if (level === maxDepth) return undefined;
var lastLineNo = cm.lastLine();
var end = start.line, nextNextLine = cm.getLine(end + 2);
while (end < lastLineNo) {
if (headerLevel(end + 1, nextLine, nextNextLine) <= level) break;
++end;
nextLine = nextNextLine;
nextNextLine = cm.getLine(end + 2);
}
return {
from: CodeMirror.Pos(start.line, firstLine.length),
to: CodeMirror.Pos(end, cm.getLine(end).length)
};
});
});
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -148,8 +151,9 @@
if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return; if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return;
var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch); var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch);
var start = end && toTagStart(iter); var start = end && toTagStart(iter);
if (!end || end == "selfClose" || !start || cmp(iter, pos) > 0) return; if (!end || !start || cmp(iter, pos) > 0) return;
var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]}; var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]};
if (end == "selfClose") return {open: here, close: null, at: "open"};
if (start[1]) { // closing tag if (start[1]) { // closing tag
return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"}; return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"};
@@ -173,6 +177,6 @@
// Used by addon/edit/closetag.js // Used by addon/edit/closetag.js
CodeMirror.scanForClosingTag = function(cm, pos, name, end) { CodeMirror.scanForClosingTag = function(cm, pos, name, end) {
var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null); var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null);
return !!findMatchingClose(iter, name); return findMatchingClose(iter, name);
}; };
}); });
@@ -0,0 +1,41 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var WORD = /[\w$]+/, RANGE = 500;
CodeMirror.registerHelper("hint", "anyword", function(editor, options) {
var word = options && options.word || WORD;
var range = options && options.range || RANGE;
var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
var end = cur.ch, start = end;
while (start && word.test(curLine.charAt(start - 1))) --start;
var curWord = start != end && curLine.slice(start, end);
var list = [], seen = {};
var re = new RegExp(word.source, "g");
for (var dir = -1; dir <= 1; dir += 2) {
var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
for (; line != endLine; line += dir) {
var text = editor.getLine(line), m;
while (m = re.exec(text)) {
if (line == cur.line && m[0] === curWord) continue;
if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) {
seen[m[0]] = true;
list.push(m[0]);
}
}
}
}
return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
});
});
@@ -0,0 +1,56 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../../mode/css/css"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../../mode/css/css"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var pseudoClasses = {link: 1, visited: 1, active: 1, hover: 1, focus: 1,
"first-letter": 1, "first-line": 1, "first-child": 1,
before: 1, after: 1, lang: 1};
CodeMirror.registerHelper("hint", "css", function(cm) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
var inner = CodeMirror.innerMode(cm.getMode(), token.state);
if (inner.mode.name != "css") return;
var start = token.start, end = cur.ch, word = token.string.slice(0, end - start);
if (/[^\w$_-]/.test(word)) {
word = ""; start = end = cur.ch;
}
var spec = CodeMirror.resolveMode("text/css");
var result = [];
function add(keywords) {
for (var name in keywords)
if (!word || name.lastIndexOf(word, 0) == 0)
result.push(name);
}
var st = inner.state.state;
if (st == "pseudo" || token.type == "variable-3") {
add(pseudoClasses);
} else if (st == "block" || st == "maybeprop") {
add(spec.propertyKeywords);
} else if (st == "prop" || st == "parens" || st == "at" || st == "params") {
add(spec.valueKeywords);
add(spec.colorKeywords);
} else if (st == "media" || st == "media_parens") {
add(spec.mediaTypes);
add(spec.mediaFeatures);
}
if (result.length) return {
list: result,
from: CodeMirror.Pos(cur.line, start),
to: CodeMirror.Pos(cur.line, end)
};
});
});
+5 -2
View File
@@ -1,8 +1,11 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"), require("./xml-hint"));
else if (typeof define == "function" && define.amd) // AMD else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod); define(["../../lib/codemirror", "./xml-hint"], mod);
else // Plain browser env else // Plain browser env
mod(CodeMirror); mod(CodeMirror);
})(function(CodeMirror) { })(function(CodeMirror) {
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -27,15 +30,20 @@
function scriptHint(editor, keywords, getToken, options) { function scriptHint(editor, keywords, getToken, options) {
// Find the token at the cursor // Find the token at the cursor
var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token; var cur = editor.getCursor(), token = getToken(editor, cur);
if (/\b(?:string|comment)\b/.test(token.type)) return; if (/\b(?:string|comment)\b/.test(token.type)) return;
token.state = CodeMirror.innerMode(editor.getMode(), token.state).state; token.state = CodeMirror.innerMode(editor.getMode(), token.state).state;
// If it's not a 'word-style' token, ignore the token. // If it's not a 'word-style' token, ignore the token.
if (!/^[\w$_]*$/.test(token.string)) { if (!/^[\w$_]*$/.test(token.string)) {
token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state, token = {start: cur.ch, end: cur.ch, string: "", state: token.state,
type: token.string == "." ? "property" : null}; type: token.string == "." ? "property" : null};
} else if (token.end > cur.ch) {
token.end = cur.ch;
token.string = token.string.slice(0, cur.ch - token.start);
} }
var tprop = token;
// If it is a property, find out what it is a property of. // If it is a property, find out what it is a property of.
while (tprop.type == "property") { while (tprop.type == "property") {
tprop = getToken(editor, Pos(cur.line, tprop.start)); tprop = getToken(editor, Pos(cur.line, tprop.start));
@@ -90,7 +98,7 @@
"if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" "); "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
function getCompletions(token, context, keywords, options) { function getCompletions(token, context, keywords, options) {
var found = [], start = token.string; var found = [], start = token.string, global = options && options.globalScope || window;
function maybeAdd(str) { function maybeAdd(str) {
if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str); if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);
} }
@@ -108,27 +116,29 @@
if (obj.type && obj.type.indexOf("variable") === 0) { if (obj.type && obj.type.indexOf("variable") === 0) {
if (options && options.additionalContext) if (options && options.additionalContext)
base = options.additionalContext[obj.string]; base = options.additionalContext[obj.string];
base = base || window[obj.string]; if (!options || options.useGlobalScope !== false)
base = base || global[obj.string];
} else if (obj.type == "string") { } else if (obj.type == "string") {
base = ""; base = "";
} else if (obj.type == "atom") { } else if (obj.type == "atom") {
base = 1; base = 1;
} else if (obj.type == "function") { } else if (obj.type == "function") {
if (window.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') && if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
(typeof window.jQuery == 'function')) (typeof global.jQuery == 'function'))
base = window.jQuery(); base = global.jQuery();
else if (window._ != null && (obj.string == '_') && (typeof window._ == 'function')) else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function'))
base = window._(); base = global._();
} }
while (base != null && context.length) while (base != null && context.length)
base = base[context.pop().string]; base = base[context.pop().string];
if (base != null) gatherCompletions(base); if (base != null) gatherCompletions(base);
} else { } else {
// If not, just look in the window object and any local scope // If not, just look in the global object and any local scope
// (reading into JS mode internals to get at the local and global variables) // (reading into JS mode internals to get at the local and global variables)
for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name); for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name); for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
gatherCompletions(window); if (!options || options.useGlobalScope !== false)
gatherCompletions(global);
forEach(keywords, maybeAdd); forEach(keywords, maybeAdd);
} }
return found; return found;
@@ -1,99 +0,0 @@
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
function forEach(arr, f) {
for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
}
function arrayContains(arr, item) {
if (!Array.prototype.indexOf) {
var i = arr.length;
while (i--) {
if (arr[i] === item) {
return true;
}
}
return false;
}
return arr.indexOf(item) != -1;
}
function scriptHint(editor, _keywords, getToken) {
// Find the token at the cursor
var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
// If it's not a 'word-style' token, ignore the token.
if (!/^[\w$_]*$/.test(token.string)) {
token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
className: token.string == ":" ? "python-type" : null};
}
if (!context) var context = [];
context.push(tprop);
var completionList = getCompletions(token, context);
completionList = completionList.sort();
return {list: completionList,
from: CodeMirror.Pos(cur.line, token.start),
to: CodeMirror.Pos(cur.line, token.end)};
}
function pythonHint(editor) {
return scriptHint(editor, pythonKeywordsU, function (e, cur) {return e.getTokenAt(cur);});
}
CodeMirror.registerHelper("hint", "python", pythonHint);
var pythonKeywords = "and del from not while as elif global or with assert else if pass yield"
+ "break except import print class exec in raise continue finally is return def for lambda try";
var pythonKeywordsL = pythonKeywords.split(" ");
var pythonKeywordsU = pythonKeywords.toUpperCase().split(" ");
var pythonBuiltins = "abs divmod input open staticmethod all enumerate int ord str "
+ "any eval isinstance pow sum basestring execfile issubclass print super"
+ "bin file iter property tuple bool filter len range type"
+ "bytearray float list raw_input unichr callable format locals reduce unicode"
+ "chr frozenset long reload vars classmethod getattr map repr xrange"
+ "cmp globals max reversed zip compile hasattr memoryview round __import__"
+ "complex hash min set apply delattr help next setattr buffer"
+ "dict hex object slice coerce dir id oct sorted intern ";
var pythonBuiltinsL = pythonBuiltins.split(" ").join("() ").split(" ");
var pythonBuiltinsU = pythonBuiltins.toUpperCase().split(" ").join("() ").split(" ");
function getCompletions(token, context) {
var found = [], start = token.string;
function maybeAdd(str) {
if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);
}
function gatherCompletions(_obj) {
forEach(pythonBuiltinsL, maybeAdd);
forEach(pythonBuiltinsU, maybeAdd);
forEach(pythonKeywordsL, maybeAdd);
forEach(pythonKeywordsU, maybeAdd);
}
if (context) {
// If this is a property, see if it belongs to some object we can
// find in the current environment.
var obj = context.pop(), base;
if (obj.type == "variable")
base = obj.string;
else if(obj.type == "variable-3")
base = ":" + obj.string;
while (base != null && context.length)
base = base[context.pop().string];
if (base != null) gatherCompletions(base);
}
return found;
}
});
@@ -32,7 +32,7 @@
cursor: pointer; cursor: pointer;
} }
.CodeMirror-hint-active { li.CodeMirror-hint-active {
background: #08f; background: #08f;
color: white; color: white;
} }
+83 -43
View File
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -11,28 +14,35 @@
var HINT_ELEMENT_CLASS = "CodeMirror-hint"; var HINT_ELEMENT_CLASS = "CodeMirror-hint";
var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active"; var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
// This is the old interface, kept around for now to stay
// backwards-compatible.
CodeMirror.showHint = function(cm, getHints, options) { CodeMirror.showHint = function(cm, getHints, options) {
// We want a single cursor position. if (!getHints) return cm.showHint(options);
if (cm.listSelections().length > 1 || cm.somethingSelected()) return; if (options && options.async) getHints.async = true;
if (getHints == null) { var newOpts = {hint: getHints};
if (options && options.async) return; if (options) for (var prop in options) newOpts[prop] = options[prop];
else getHints = CodeMirror.hint.auto; return cm.showHint(newOpts);
}
if (cm.state.completionActive) cm.state.completionActive.close();
var completion = cm.state.completionActive = new Completion(cm, getHints, options || {});
CodeMirror.signal(cm, "startCompletion", cm);
if (completion.options.async)
getHints(cm, function(hints) { completion.showHints(hints); }, completion.options);
else
return completion.showHints(getHints(cm, completion.options));
}; };
function Completion(cm, getHints, options) { CodeMirror.defineExtension("showHint", function(options) {
// We want a single cursor position.
if (this.listSelections().length > 1 || this.somethingSelected()) return;
if (this.state.completionActive) this.state.completionActive.close();
var completion = this.state.completionActive = new Completion(this, options);
var getHints = completion.options.hint;
if (!getHints) return;
CodeMirror.signal(this, "startCompletion", this);
if (getHints.async)
getHints(this, function(hints) { completion.showHints(hints); }, completion.options);
else
return completion.showHints(getHints(this, completion.options));
});
function Completion(cm, options) {
this.cm = cm; this.cm = cm;
this.getHints = getHints; this.options = this.buildOptions(options);
this.options = options;
this.widget = this.onClose = null; this.widget = this.onClose = null;
} }
@@ -53,7 +63,8 @@
pick: function(data, i) { pick: function(data, i) {
var completion = data.list[i]; var completion = data.list[i];
if (completion.hint) completion.hint(this.cm, data, completion); if (completion.hint) completion.hint(this.cm, data, completion);
else this.cm.replaceRange(getText(completion), completion.from||data.from, completion.to||data.to); else this.cm.replaceRange(getText(completion), completion.from || data.from,
completion.to || data.to, "complete");
CodeMirror.signal(data, "pick", completion); CodeMirror.signal(data, "pick", completion);
this.close(); this.close();
}, },
@@ -61,7 +72,7 @@
showHints: function(data) { showHints: function(data) {
if (!data || !data.list.length || !this.active()) return this.close(); if (!data || !data.list.length || !this.active()) return this.close();
if (this.options.completeSingle != false && data.list.length == 1) if (this.options.completeSingle && data.list.length == 1)
this.pick(data, 0); this.pick(data, 0);
else else
this.showWidget(data); this.showWidget(data);
@@ -72,7 +83,7 @@
CodeMirror.signal(data, "shown"); CodeMirror.signal(data, "shown");
var debounce = 0, completion = this, finished; var debounce = 0, completion = this, finished;
var closeOn = this.options.closeCharacters || /[\s()\[\]{};:>,]/; var closeOn = this.options.closeCharacters;
var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length; var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length;
var requestAnimationFrame = window.requestAnimationFrame || function(fn) { var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
@@ -91,15 +102,17 @@
function update() { function update() {
if (finished) return; if (finished) return;
CodeMirror.signal(data, "update"); CodeMirror.signal(data, "update");
if (completion.options.async) var getHints = completion.options.hint;
completion.getHints(completion.cm, finishUpdate, completion.options); if (getHints.async)
getHints(completion.cm, finishUpdate, completion.options);
else else
finishUpdate(completion.getHints(completion.cm, completion.options)); finishUpdate(getHints(completion.cm, completion.options));
} }
function finishUpdate(data_) { function finishUpdate(data_) {
data = data_; data = data_;
if (finished) return; if (finished) return;
if (!data || !data.list.length) return done(); if (!data || !data.list.length) return done();
if (completion.widget) completion.widget.close();
completion.widget = new Widget(completion, data); completion.widget = new Widget(completion, data);
} }
@@ -124,6 +137,17 @@
} }
this.cm.on("cursorActivity", activity); this.cm.on("cursorActivity", activity);
this.onClose = done; this.onClose = done;
},
buildOptions: function(options) {
var editor = this.cm.options.hintOptions;
var out = {};
for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
if (editor) for (var prop in editor)
if (editor[prop] !== undefined) out[prop] = editor[prop];
if (options) for (var prop in options)
if (options[prop] !== undefined) out[prop] = options[prop];
return out;
} }
}; };
@@ -132,7 +156,7 @@
else return completion.text; else return completion.text;
} }
function buildKeyMap(options, handle) { function buildKeyMap(completion, handle) {
var baseMap = { var baseMap = {
Up: function() {handle.moveFocus(-1);}, Up: function() {handle.moveFocus(-1);},
Down: function() {handle.moveFocus(1);}, Down: function() {handle.moveFocus(1);},
@@ -144,7 +168,8 @@
Tab: handle.pick, Tab: handle.pick,
Esc: handle.close Esc: handle.close
}; };
var ourMap = options.customKeys ? {} : baseMap; var custom = completion.options.customKeys;
var ourMap = custom ? {} : baseMap;
function addBinding(key, val) { function addBinding(key, val) {
var bound; var bound;
if (typeof val != "string") if (typeof val != "string")
@@ -156,12 +181,13 @@
bound = val; bound = val;
ourMap[key] = bound; ourMap[key] = bound;
} }
if (options.customKeys) if (custom)
for (var key in options.customKeys) if (options.customKeys.hasOwnProperty(key)) for (var key in custom) if (custom.hasOwnProperty(key))
addBinding(key, options.customKeys[key]); addBinding(key, custom[key]);
if (options.extraKeys) var extra = completion.options.extraKeys;
for (var key in options.extraKeys) if (options.extraKeys.hasOwnProperty(key)) if (extra)
addBinding(key, options.extraKeys[key]); for (var key in extra) if (extra.hasOwnProperty(key))
addBinding(key, extra[key]);
return ourMap; return ourMap;
} }
@@ -175,11 +201,11 @@
function Widget(completion, data) { function Widget(completion, data) {
this.completion = completion; this.completion = completion;
this.data = data; this.data = data;
var widget = this, cm = completion.cm, options = completion.options; var widget = this, cm = completion.cm;
var hints = this.hints = document.createElement("ul"); var hints = this.hints = document.createElement("ul");
hints.className = "CodeMirror-hints"; hints.className = "CodeMirror-hints";
this.selectedHint = options.getDefaultSelection ? options.getDefaultSelection(cm,options,data) : 0; this.selectedHint = data.selectedHint || 0;
var completions = data.list; var completions = data.list;
for (var i = 0; i < completions.length; ++i) { for (var i = 0; i < completions.length; ++i) {
@@ -192,19 +218,19 @@
elt.hintId = i; elt.hintId = i;
} }
var pos = cm.cursorCoords(options.alignWithWord !== false ? data.from : null); var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
var left = pos.left, top = pos.bottom, below = true; var left = pos.left, top = pos.bottom, below = true;
hints.style.left = left + "px"; hints.style.left = left + "px";
hints.style.top = top + "px"; hints.style.top = top + "px";
// If we're at the edge of the screen, then we want the menu to appear on the left of the cursor. // 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); var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight); var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
(options.container || document.body).appendChild(hints); (completion.options.container || document.body).appendChild(hints);
var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH; var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
if (overlapY > 0) { if (overlapY > 0) {
var height = box.bottom - box.top, curTop = box.top - (pos.bottom - pos.top); var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
if (curTop - height > 0) { // Fits above cursor if (curTop - height > 0) { // Fits above cursor
hints.style.top = (top = curTop - height) + "px"; hints.style.top = (top = pos.top - height) + "px";
below = false; below = false;
} else if (height > winH) { } else if (height > winH) {
hints.style.height = (winH - 5) + "px"; hints.style.height = (winH - 5) + "px";
@@ -217,7 +243,7 @@
} }
} }
} }
var overlapX = box.left - winW; var overlapX = box.right - winW;
if (overlapX > 0) { if (overlapX > 0) {
if (box.right - box.left > winW) { if (box.right - box.left > winW) {
hints.style.width = (winW - 5) + "px"; hints.style.width = (winW - 5) + "px";
@@ -226,7 +252,7 @@
hints.style.left = (left = pos.left - overlapX) + "px"; hints.style.left = (left = pos.left - overlapX) + "px";
} }
cm.addKeyMap(this.keyMap = buildKeyMap(options, { cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); }, moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
setFocus: function(n) { widget.changeActive(n); }, setFocus: function(n) { widget.changeActive(n); },
menuSize: function() { return widget.screenAmount(); }, menuSize: function() { return widget.screenAmount(); },
@@ -236,7 +262,7 @@
data: data data: data
})); }));
if (options.closeOnUnfocus !== false) { if (completion.options.closeOnUnfocus) {
var closingOnBlur; var closingOnBlur;
cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); }); cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); }); cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
@@ -262,7 +288,7 @@
var t = getHintElement(hints, e.target || e.srcElement); var t = getHintElement(hints, e.target || e.srcElement);
if (t && t.hintId != null) { if (t && t.hintId != null) {
widget.changeActive(t.hintId); widget.changeActive(t.hintId);
if (options.completeOnSingleClick) widget.pick(); if (completion.options.completeOnSingleClick) widget.pick();
} }
}); });
@@ -282,7 +308,7 @@
this.completion.cm.removeKeyMap(this.keyMap); this.completion.cm.removeKeyMap(this.keyMap);
var cm = this.completion.cm; var cm = this.completion.cm;
if (this.completion.options.closeOnUnfocus !== false) { if (this.completion.options.closeOnUnfocus) {
cm.off("blur", this.onBlur); cm.off("blur", this.onBlur);
cm.off("focus", this.onFocus); cm.off("focus", this.onFocus);
} }
@@ -346,4 +372,18 @@
}); });
CodeMirror.commands.autocomplete = CodeMirror.showHint; CodeMirror.commands.autocomplete = CodeMirror.showHint;
var defaultOptions = {
hint: CodeMirror.hint.auto,
completeSingle: true,
alignWithWord: true,
closeCharacters: /[\s()\[\]{};:>,]/,
closeOnUnfocus: true,
completeOnSingleClick: false,
container: null,
customKeys: null,
extraKeys: null
};
CodeMirror.defineOption("hintOptions", null);
}); });
@@ -0,0 +1,197 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../../mode/sql/sql"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../../mode/sql/sql"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var tables;
var defaultTable;
var keywords;
var CONS = {
QUERY_DIV: ";",
ALIAS_KEYWORD: "AS"
};
var Pos = CodeMirror.Pos;
function getKeywords(editor) {
var mode = editor.doc.modeOption;
if (mode === "sql") mode = "text/x-sql";
return CodeMirror.resolveMode(mode).keywords;
}
function match(string, word) {
var len = string.length;
var sub = word.substr(0, len);
return string.toUpperCase() === sub.toUpperCase();
}
function addMatches(result, search, wordlist, formatter) {
for (var word in wordlist) {
if (!wordlist.hasOwnProperty(word)) continue;
if (Array.isArray(wordlist)) {
word = wordlist[word];
}
if (match(search, word)) {
result.push(formatter(word));
}
}
}
function nameCompletion(cur, token, result, editor) {
var useBacktick = (token.string.charAt(0) == "`");
var string = token.string.substr(1);
var prevToken = editor.getTokenAt(Pos(cur.line, token.start));
if (token.string.charAt(0) == "." || prevToken.string == "."){
//Suggest colunm names
if (prevToken.string == ".") {
var prevToken = editor.getTokenAt(Pos(cur.line, token.start - 1));
}
var table = prevToken.string;
//Check if backtick is used in table name. If yes, use it for columns too.
var useBacktickTable = false;
if (table.match(/`/g)) {
useBacktickTable = true;
table = table.replace(/`/g, "");
}
//Check if table is available. If not, find table by Alias
if (!tables.hasOwnProperty(table))
table = findTableByAlias(table, editor);
var columns = tables[table];
if (!columns) return;
if (useBacktick) {
addMatches(result, string, columns, function(w) {return "`" + w + "`";});
}
else if(useBacktickTable) {
addMatches(result, string, columns, function(w) {return ".`" + w + "`";});
}
else {
addMatches(result, string, columns, function(w) {return "." + w;});
}
}
else {
//Suggest table names or colums in defaultTable
while (token.start && string.charAt(0) == ".") {
token = editor.getTokenAt(Pos(cur.line, token.start - 1));
string = token.string + string;
}
if (useBacktick) {
addMatches(result, string, tables, function(w) {return "`" + w + "`";});
addMatches(result, string, defaultTable, function(w) {return "`" + w + "`";});
}
else {
addMatches(result, string, tables, function(w) {return w;});
addMatches(result, string, defaultTable, function(w) {return w;});
}
}
}
function eachWord(lineText, f) {
if (!lineText) return;
var excepted = /[,;]/g;
var words = lineText.split(" ");
for (var i = 0; i < words.length; i++) {
f(words[i]?words[i].replace(excepted, '') : '');
}
}
function convertCurToNumber(cur) {
// max characters of a line is 999,999.
return cur.line + cur.ch / Math.pow(10, 6);
}
function convertNumberToCur(num) {
return Pos(Math.floor(num), +num.toString().split('.').pop());
}
function findTableByAlias(alias, editor) {
var doc = editor.doc;
var fullQuery = doc.getValue();
var aliasUpperCase = alias.toUpperCase();
var previousWord = "";
var table = "";
var separator = [];
var validRange = {
start: Pos(0, 0),
end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)
};
//add separator
var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);
while(indexOfSeparator != -1) {
separator.push(doc.posFromIndex(indexOfSeparator));
indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);
}
separator.unshift(Pos(0, 0));
separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
//find valid range
var prevItem = 0;
var current = convertCurToNumber(editor.getCursor());
for (var i=0; i< separator.length; i++) {
var _v = convertCurToNumber(separator[i]);
if (current > prevItem && current <= _v) {
validRange = { start: convertNumberToCur(prevItem), end: convertNumberToCur(_v) };
break;
}
prevItem = _v;
}
var query = doc.getRange(validRange.start, validRange.end, false);
for (var i = 0; i < query.length; i++) {
var lineText = query[i];
eachWord(lineText, function(word) {
var wordUpperCase = word.toUpperCase();
if (wordUpperCase === aliasUpperCase && tables.hasOwnProperty(previousWord)) {
table = previousWord;
}
if (wordUpperCase !== CONS.ALIAS_KEYWORD) {
previousWord = word;
}
});
if (table) break;
}
return table;
}
CodeMirror.registerHelper("hint", "sql", function(editor, options) {
tables = (options && options.tables) || {};
var defaultTableName = options && options.defaultTable;
defaultTable = (defaultTableName && tables[defaultTableName] || []);
keywords = keywords || getKeywords(editor);
var cur = editor.getCursor();
var result = [];
var token = editor.getTokenAt(cur), start, end, search;
if (token.end > cur.ch) {
token.end = cur.ch;
token.string = token.string.slice(0, cur.ch - token.start);
}
if (token.string.match(/^[.`\w@]\w*$/)) {
search = token.string;
start = token.start;
end = token.end;
} else {
start = end = cur.ch;
search = "";
}
if (search.charAt(0) == "." || search.charAt(0) == "`") {
nameCompletion(cur, token, result, editor);
} else {
addMatches(result, search, tables, function(w) {return w;});
addMatches(result, search, defaultTable, function(w) {return w;});
addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
}
return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
});
});
+48 -13
View File
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -15,30 +18,55 @@
var quote = (options && options.quoteChar) || '"'; var quote = (options && options.quoteChar) || '"';
if (!tags) return; if (!tags) return;
var cur = cm.getCursor(), token = cm.getTokenAt(cur); var cur = cm.getCursor(), token = cm.getTokenAt(cur);
if (token.end > cur.ch) {
token.end = cur.ch;
token.string = token.string.slice(0, cur.ch - token.start);
}
var inner = CodeMirror.innerMode(cm.getMode(), token.state); var inner = CodeMirror.innerMode(cm.getMode(), token.state);
if (inner.mode.name != "xml") return; if (inner.mode.name != "xml") return;
var result = [], replaceToken = false, prefix; var result = [], replaceToken = false, prefix;
var isTag = token.string.charAt(0) == "<"; var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
if (!inner.state.tagName || isTag) { // Tag completion var tagName = tag && /^\w/.test(token.string), tagStart;
if (isTag) {
prefix = token.string.slice(1); if (tagName) {
replaceToken = true; var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);
} var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;
if (tagType) tagStart = token.start - (tagType == "close" ? 2 : 1);
} else if (tag && token.string == "<") {
tagType = "open";
} else if (tag && token.string == "</") {
tagType = "close";
}
if (!tag && !inner.state.tagName || tagType) {
if (tagName)
prefix = token.string;
replaceToken = tagType;
var cx = inner.state.context, curTag = cx && tags[cx.tagName]; var cx = inner.state.context, curTag = cx && tags[cx.tagName];
var childList = cx ? curTag && curTag.children : tags["!top"]; var childList = cx ? curTag && curTag.children : tags["!top"];
if (childList) { if (childList && tagType != "close") {
for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].lastIndexOf(prefix, 0) == 0) for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].lastIndexOf(prefix, 0) == 0)
result.push("<" + childList[i]); result.push("<" + childList[i]);
} else { } else if (tagType != "close") {
for (var name in tags) if (tags.hasOwnProperty(name) && name != "!top" && (!prefix || name.lastIndexOf(prefix, 0) == 0)) for (var name in tags)
result.push("<" + name); if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || name.lastIndexOf(prefix, 0) == 0))
result.push("<" + name);
} }
if (cx && (!prefix || ("/" + cx.tagName).lastIndexOf(prefix, 0) == 0)) if (cx && (!prefix || tagType == "close" && cx.tagName.lastIndexOf(prefix, 0) == 0))
result.push("</" + cx.tagName + ">"); result.push("</" + cx.tagName + ">");
} else { } else {
// Attribute completion // Attribute completion
var curTag = tags[inner.state.tagName], attrs = curTag && curTag.attrs; var curTag = tags[inner.state.tagName], attrs = curTag && curTag.attrs;
if (!attrs) return; var globalAttrs = tags["!attrs"];
if (!attrs && !globalAttrs) return;
if (!attrs) {
attrs = globalAttrs;
} else if (globalAttrs) { // Combine tag-local and global attributes
var set = {};
for (var nm in globalAttrs) if (globalAttrs.hasOwnProperty(nm)) set[nm] = globalAttrs[nm];
for (var nm in attrs) if (attrs.hasOwnProperty(nm)) set[nm] = attrs[nm];
attrs = set;
}
if (token.type == "string" || token.string == "=") { // A value if (token.type == "string" || token.string == "=") { // A value
var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)), var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),
Pos(cur.line, token.type == "string" ? token.start : token.end)); Pos(cur.line, token.type == "string" ? token.start : token.end));
@@ -47,9 +75,16 @@
if (typeof atValues == 'function') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget if (typeof atValues == 'function') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget
if (token.type == "string") { if (token.type == "string") {
prefix = token.string; prefix = token.string;
var n = 0;
if (/['"]/.test(token.string.charAt(0))) { if (/['"]/.test(token.string.charAt(0))) {
quote = token.string.charAt(0); quote = token.string.charAt(0);
prefix = token.string.slice(1); prefix = token.string.slice(1);
n++;
}
var len = token.string.length;
if (/['"]/.test(token.string.charAt(len - 1))) {
quote = token.string.charAt(len - 1);
prefix = token.string.substr(n, len - 2);
} }
replaceToken = true; replaceToken = true;
} }
@@ -66,7 +101,7 @@
} }
return { return {
list: result, list: result,
from: replaceToken ? Pos(cur.line, token.start) : cur, from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
to: replaceToken ? Pos(cur.line, token.end) : cur to: replaceToken ? Pos(cur.line, token.end) : cur
}; };
} }
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Depends on coffeelint.js from http://www.coffeelint.org/js/coffeelint.js // Depends on coffeelint.js from http://www.coffeelint.org/js/coffeelint.js
// declare global: coffeelint // declare global: coffeelint
@@ -0,0 +1,35 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Depends on csslint.js from https://github.com/stubbornella/csslint
// declare global: CSSLint
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.registerHelper("lint", "css", function(text) {
var found = [];
if (!window.CSSLint) return found;
var results = CSSLint.verify(text), messages = results.messages, message = null;
for ( var i = 0; i < messages.length; i++) {
message = messages[i];
var startLine = message.line -1, endLine = message.line -1, startCol = message.col -1, endCol = message.col;
found.push({
from: CodeMirror.Pos(startLine, startCol),
to: CodeMirror.Pos(endLine, endCol),
message: message.message,
severity : message.type
});
}
return found;
});
});
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -19,6 +22,7 @@
"Unclosed string", "Stopping, unable to continue" ]; "Unclosed string", "Stopping, unable to continue" ];
function validator(text, options) { function validator(text, options) {
if (!window.JSHINT) return [];
JSHINT(text, options); JSHINT(text, options);
var errors = JSHINT.data().errors, result = []; var errors = JSHINT.data().errors, result = [];
if (errors) parseErrors(errors, result); if (errors) parseErrors(errors, result);
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Depends on jsonlint.js from https://github.com/zaach/jsonlint // Depends on jsonlint.js from https://github.com/zaach/jsonlint
// declare global: jsonlint // declare global: jsonlint
+15 -18
View File
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -8,7 +11,6 @@
})(function(CodeMirror) { })(function(CodeMirror) {
"use strict"; "use strict";
var GUTTER_ID = "CodeMirror-lint-markers"; var GUTTER_ID = "CodeMirror-lint-markers";
var SEVERITIES = /^(?:error|warning)$/;
function showTooltip(e, content) { function showTooltip(e, content) {
var tt = document.createElement("div"); var tt = document.createElement("div");
@@ -107,7 +109,7 @@
function annotationTooltip(ann) { function annotationTooltip(ann) {
var severity = ann.severity; var severity = ann.severity;
if (!SEVERITIES.test(severity)) severity = "error"; if (!severity) severity = "error";
var tip = document.createElement("div"); var tip = document.createElement("div");
tip.className = "CodeMirror-lint-message-" + severity; tip.className = "CodeMirror-lint-message-" + severity;
tip.appendChild(document.createTextNode(ann.message)); tip.appendChild(document.createTextNode(ann.message));
@@ -116,10 +118,11 @@
function startLinting(cm) { function startLinting(cm) {
var state = cm.state.lint, options = state.options; var state = cm.state.lint, options = state.options;
var passOptions = options.options || options; // Support deprecated passing of `options` property in options
if (options.async) if (options.async)
options.getAnnotations(cm, updateLinting, options); options.getAnnotations(cm.getValue(), updateLinting, passOptions, cm);
else else
updateLinting(cm, options.getAnnotations(cm.getValue(), options.options)); updateLinting(cm, options.getAnnotations(cm.getValue(), passOptions, cm));
} }
function updateLinting(cm, annotationsNotSorted) { function updateLinting(cm, annotationsNotSorted) {
@@ -138,7 +141,7 @@
for (var i = 0; i < anns.length; ++i) { for (var i = 0; i < anns.length; ++i) {
var ann = anns[i]; var ann = anns[i];
var severity = ann.severity; var severity = ann.severity;
if (!SEVERITIES.test(severity)) severity = "error"; if (!severity) severity = "error";
maxSeverity = getMaxSeverity(maxSeverity, severity); maxSeverity = getMaxSeverity(maxSeverity, severity);
if (options.formatAnnotation) ann = options.formatAnnotation(ann); if (options.formatAnnotation) ann = options.formatAnnotation(ann);
@@ -168,20 +171,14 @@
showTooltipFor(e, annotationTooltip(ann), target); showTooltipFor(e, annotationTooltip(ann), target);
} }
// When the mouseover fires, the cursor might not actually be over
// the character itself yet. These pairs of x,y offsets are used to
// probe a few nearby points when no suitable marked range is found.
var nearby = [0, 0, 0, 5, 0, -5, 5, 0, -5, 0];
function onMouseOver(cm, e) { function onMouseOver(cm, e) {
if (!/\bCodeMirror-lint-mark-/.test((e.target || e.srcElement).className)) return; var target = e.target || e.srcElement;
for (var i = 0; i < nearby.length; i += 2) { if (!/\bCodeMirror-lint-mark-/.test(target.className)) return;
var spans = cm.findMarksAt(cm.coordsChar({left: e.clientX + nearby[i], var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2;
top: e.clientY + nearby[i + 1]}, "client")); var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client"));
for (var j = 0; j < spans.length; ++j) { for (var i = 0; i < spans.length; ++i) {
var span = spans[j], ann = span.__annotation; var ann = spans[i].__annotation;
if (ann) return popupSpanTooltip(ann, e); if (ann) return popupSpanTooltip(ann, e);
}
} }
} }
@@ -0,0 +1,28 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
// Depends on js-yaml.js from https://github.com/nodeca/js-yaml
// declare global: jsyaml
CodeMirror.registerHelper("lint", "yaml", function(text) {
var found = [];
try { jsyaml.load(text); }
catch(e) {
var loc = e.mark;
found.push({ from: CodeMirror.Pos(loc.line, loc.column), to: CodeMirror.Pos(loc.line, loc.column), message: e.message });
}
return found;
});
});
@@ -1,50 +0,0 @@
// From https://code.google.com/p/google-diff-match-patch/ , licensed under the Apache License 2.0
(function(){function diff_match_patch(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=0.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=0.5;this.Patch_Margin=4;this.Match_MaxBits=32}
diff_match_patch.prototype.diff_main=function(a,b,c,d){"undefined"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error("Null input. (diff_main)");if(a==b)return a?[[0,a]]:[];"undefined"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b);c=a.substring(0,f);a=a.substring(f);b=b.substring(f);var f=this.diff_commonSuffix(a,b),g=a.substring(a.length-f);a=a.substring(0,a.length-f);b=b.substring(0,b.length-f);a=this.diff_compute_(a,
b,e,d);c&&a.unshift([0,c]);g&&a.push([0,g]);this.diff_cleanupMerge(a);return a};
diff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[[1,b]];if(!b)return[[-1,a]];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);return-1!=g?(c=[[1,e.substring(0,g)],[0,f],[1,e.substring(g+f.length)]],a.length>b.length&&(c[0][0]=c[2][0]=-1),c):1==f.length?[[-1,a],[1,b]]:(e=this.diff_halfMatch_(a,b))?(f=e[0],a=e[1],g=e[2],b=e[3],e=e[4],f=this.diff_main(f,g,c,d),c=this.diff_main(a,b,c,d),f.concat([[0,e]],c)):c&&100<a.length&&100<b.length?this.diff_lineMode_(a,b,
d):this.diff_bisect_(a,b,d)};
diff_match_patch.prototype.diff_lineMode_=function(a,b,c){var d=this.diff_linesToChars_(a,b);a=d.chars1;b=d.chars2;d=d.lineArray;a=this.diff_main(a,b,!1,c);this.diff_charsToLines_(a,d);this.diff_cleanupSemantic(a);a.push([0,""]);for(var e=d=b=0,f="",g="";b<a.length;){switch(a[b][0]){case 1:e++;g+=a[b][1];break;case -1:d++;f+=a[b][1];break;case 0:if(1<=d&&1<=e){a.splice(b-d-e,d+e);b=b-d-e;d=this.diff_main(f,g,!1,c);for(e=d.length-1;0<=e;e--)a.splice(b,0,d[e]);b+=d.length}d=e=0;g=f=""}b++}a.pop();return a};
diff_match_patch.prototype.diff_bisect_=function(a,b,c){for(var d=a.length,e=b.length,f=Math.ceil((d+e)/2),g=f,h=2*f,j=Array(h),i=Array(h),k=0;k<h;k++)j[k]=-1,i[k]=-1;j[g+1]=0;i[g+1]=0;for(var k=d-e,q=0!=k%2,r=0,t=0,p=0,w=0,v=0;v<f&&!((new Date).getTime()>c);v++){for(var n=-v+r;n<=v-t;n+=2){var l=g+n,m;m=n==-v||n!=v&&j[l-1]<j[l+1]?j[l+1]:j[l-1]+1;for(var s=m-n;m<d&&s<e&&a.charAt(m)==b.charAt(s);)m++,s++;j[l]=m;if(m>d)t+=2;else if(s>e)r+=2;else if(q&&(l=g+k-n,0<=l&&l<h&&-1!=i[l])){var u=d-i[l];if(m>=
u)return this.diff_bisectSplit_(a,b,m,s,c)}}for(n=-v+p;n<=v-w;n+=2){l=g+n;u=n==-v||n!=v&&i[l-1]<i[l+1]?i[l+1]:i[l-1]+1;for(m=u-n;u<d&&m<e&&a.charAt(d-u-1)==b.charAt(e-m-1);)u++,m++;i[l]=u;if(u>d)w+=2;else if(m>e)p+=2;else if(!q&&(l=g+k-n,0<=l&&(l<h&&-1!=j[l])&&(m=j[l],s=g+m-l,u=d-u,m>=u)))return this.diff_bisectSplit_(a,b,m,s,c)}}return[[-1,a],[1,b]]};
diff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d);a=a.substring(c);b=b.substring(d);f=this.diff_main(f,g,!1,e);e=this.diff_main(a,b,!1,e);return f.concat(e)};
diff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b="",c=0,f=-1,g=d.length;f<a.length-1;){f=a.indexOf("\n",c);-1==f&&(f=a.length-1);var r=a.substring(c,f+1),c=f+1;(e.hasOwnProperty?e.hasOwnProperty(r):void 0!==e[r])?b+=String.fromCharCode(e[r]):(b+=String.fromCharCode(g),e[r]=g,d[g++]=r)}return b}var d=[],e={};d[0]="";var f=c(a),g=c(b);return{chars1:f,chars2:g,lineArray:d}};
diff_match_patch.prototype.diff_charsToLines_=function(a,b){for(var c=0;c<a.length;c++){for(var d=a[c][1],e=[],f=0;f<d.length;f++)e[f]=b[d.charCodeAt(f)];a[c][1]=e.join("")}};diff_match_patch.prototype.diff_commonPrefix=function(a,b){if(!a||!b||a.charAt(0)!=b.charAt(0))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(f,e)==b.substring(f,e)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
diff_match_patch.prototype.diff_commonSuffix=function(a,b){if(!a||!b||a.charAt(a.length-1)!=b.charAt(b.length-1))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(a.length-e,a.length-f)==b.substring(b.length-e,b.length-f)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
diff_match_patch.prototype.diff_commonOverlap_=function(a,b){var c=a.length,d=b.length;if(0==c||0==d)return 0;c>d?a=a.substring(c-d):c<d&&(b=b.substring(0,c));c=Math.min(c,d);if(a==b)return c;for(var d=0,e=1;;){var f=a.substring(c-e),f=b.indexOf(f);if(-1==f)return d;e+=f;if(0==f||a.substring(c-e)==b.substring(0,e))d=e,e++}};
diff_match_patch.prototype.diff_halfMatch_=function(a,b){function c(a,b,c){for(var d=a.substring(c,c+Math.floor(a.length/4)),e=-1,g="",h,j,n,l;-1!=(e=b.indexOf(d,e+1));){var m=f.diff_commonPrefix(a.substring(c),b.substring(e)),s=f.diff_commonSuffix(a.substring(0,c),b.substring(0,e));g.length<s+m&&(g=b.substring(e-s,e)+b.substring(e,e+m),h=a.substring(0,c-s),j=a.substring(c+m),n=b.substring(0,e-s),l=b.substring(e+m))}return 2*g.length>=a.length?[h,j,n,l,g]:null}if(0>=this.Diff_Timeout)return null;
var d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.length<d.length)return null;var f=this,g=c(d,e,Math.ceil(d.length/4)),d=c(d,e,Math.ceil(d.length/2)),h;if(!g&&!d)return null;h=d?g?g[4].length>d[4].length?g:d:d:g;var j;a.length>b.length?(g=h[0],d=h[1],e=h[2],j=h[3]):(e=h[0],j=h[1],g=h[2],d=h[3]);h=h[4];return[g,d,e,j,h]};
diff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,j=0,i=0;f<a.length;)0==a[f][0]?(c[d++]=f,g=j,h=i,i=j=0,e=a[f][1]):(1==a[f][0]?j+=a[f][1].length:i+=a[f][1].length,e&&(e.length<=Math.max(g,h)&&e.length<=Math.max(j,i))&&(a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,d--,f=0<d?c[d-1]:-1,i=j=h=g=0,e=null,b=!0)),f++;b&&this.diff_cleanupMerge(a);this.diff_cleanupSemanticLossless(a);for(f=1;f<a.length;){if(-1==a[f-1][0]&&1==a[f][0]){b=a[f-1][1];c=a[f][1];
d=this.diff_commonOverlap_(b,c);e=this.diff_commonOverlap_(c,b);if(d>=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,[0,c.substring(0,d)]),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,[0,b.substring(0,e)]),a[f-1][0]=1,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=-1,a[f+1][1]=b.substring(e),f++;f++}f++}};
diff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_),c=g&&c.match(diff_match_patch.linebreakRegex_),d=h&&d.match(diff_match_patch.linebreakRegex_),i=c&&a.match(diff_match_patch.blanklineEndRegex_),j=d&&b.match(diff_match_patch.blanklineStartRegex_);
return i||j?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c<a.length-1;){if(0==a[c-1][0]&&0==a[c+1][0]){var d=a[c-1][1],e=a[c][1],f=a[c+1][1],g=this.diff_commonSuffix(d,e);if(g)var h=e.substring(e.length-g),d=d.substring(0,d.length-g),e=h+e.substring(0,e.length-g),f=h+f;for(var g=d,h=e,j=f,i=b(d,e)+b(e,f);e.charAt(0)===f.charAt(0);){var d=d+e.charAt(0),e=e.substring(1)+f.charAt(0),f=f.substring(1),k=b(d,e)+b(e,f);k>=i&&(i=k,g=d,h=e,j=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-1,1),c--),a[c][1]=
h,j?a[c+1][1]=j:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\s/;diff_match_patch.linebreakRegex_=/[\r\n]/;diff_match_patch.blanklineEndRegex_=/\n\r?\n$/;diff_match_patch.blanklineStartRegex_=/^\r?\n\r?\n/;
diff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,j=!1,i=!1;f<a.length;){if(0==a[f][0])a[f][1].length<this.Diff_EditCost&&(j||i)?(c[d++]=f,g=j,h=i,e=a[f][1]):(d=0,e=null),j=i=!1;else if(-1==a[f][0]?i=!0:j=!0,e&&(g&&h&&j&&i||e.length<this.Diff_EditCost/2&&3==g+h+j+i))a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,e=null,g&&h?(j=i=!0,d=0):(d--,f=0<d?c[d-1]:-1,j=i=!1),b=!0;f++}b&&this.diff_cleanupMerge(a)};
diff_match_patch.prototype.diff_cleanupMerge=function(a){a.push([0,""]);for(var b=0,c=0,d=0,e="",f="",g;b<a.length;)switch(a[b][0]){case 1:d++;f+=a[b][1];b++;break;case -1:c++;e+=a[b][1];b++;break;case 0:1<c+d?(0!==c&&0!==d&&(g=this.diff_commonPrefix(f,e),0!==g&&(0<b-c-d&&0==a[b-c-d-1][0]?a[b-c-d-1][1]+=f.substring(0,g):(a.splice(0,0,[0,f.substring(0,g)]),b++),f=f.substring(g),e=e.substring(g)),g=this.diff_commonSuffix(f,e),0!==g&&(a[b][1]=f.substring(f.length-g)+a[b][1],f=f.substring(0,f.length-
g),e=e.substring(0,e.length-g))),0===c?a.splice(b-d,c+d,[1,f]):0===d?a.splice(b-c,c+d,[-1,e]):a.splice(b-c-d,c+d,[-1,e],[1,f]),b=b-c-d+(c?1:0)+(d?1:0)+1):0!==b&&0==a[b-1][0]?(a[b-1][1]+=a[b][1],a.splice(b,1)):b++,c=d=0,f=e=""}""===a[a.length-1][1]&&a.pop();c=!1;for(b=1;b<a.length-1;)0==a[b-1][0]&&0==a[b+1][0]&&(a[b][1].substring(a[b][1].length-a[b-1][1].length)==a[b-1][1]?(a[b][1]=a[b-1][1]+a[b][1].substring(0,a[b][1].length-a[b-1][1].length),a[b+1][1]=a[b-1][1]+a[b+1][1],a.splice(b-1,1),c=!0):a[b][1].substring(0,
a[b+1][1].length)==a[b+1][1]&&(a[b-1][1]+=a[b+1][1],a[b][1]=a[b][1].substring(a[b+1][1].length)+a[b+1][1],a.splice(b+1,1),c=!0)),b++;c&&this.diff_cleanupMerge(a)};diff_match_patch.prototype.diff_xIndex=function(a,b){var c=0,d=0,e=0,f=0,g;for(g=0;g<a.length;g++){1!==a[g][0]&&(c+=a[g][1].length);-1!==a[g][0]&&(d+=a[g][1].length);if(c>b)break;e=c;f=d}return a.length!=g&&-1===a[g][0]?f:f+(b-e)};
diff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=/</g,e=/>/g,f=/\n/g,g=0;g<a.length;g++){var h=a[g][0],j=a[g][1],j=j.replace(c,"&amp;").replace(d,"&lt;").replace(e,"&gt;").replace(f,"&para;<br>");switch(h){case 1:b[g]='<ins style="background:#e6ffe6;">'+j+"</ins>";break;case -1:b[g]='<del style="background:#ffe6e6;">'+j+"</del>";break;case 0:b[g]="<span>"+j+"</span>"}}return b.join("")};
diff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;c<a.length;c++)1!==a[c][0]&&(b[c]=a[c][1]);return b.join("")};diff_match_patch.prototype.diff_text2=function(a){for(var b=[],c=0;c<a.length;c++)-1!==a[c][0]&&(b[c]=a[c][1]);return b.join("")};diff_match_patch.prototype.diff_levenshtein=function(a){for(var b=0,c=0,d=0,e=0;e<a.length;e++){var f=a[e][0],g=a[e][1];switch(f){case 1:c+=g.length;break;case -1:d+=g.length;break;case 0:b+=Math.max(c,d),d=c=0}}return b+=Math.max(c,d)};
diff_match_patch.prototype.diff_toDelta=function(a){for(var b=[],c=0;c<a.length;c++)switch(a[c][0]){case 1:b[c]="+"+encodeURI(a[c][1]);break;case -1:b[c]="-"+a[c][1].length;break;case 0:b[c]="="+a[c][1].length}return b.join("\t").replace(/%20/g," ")};
diff_match_patch.prototype.diff_fromDelta=function(a,b){for(var c=[],d=0,e=0,f=b.split(/\t/g),g=0;g<f.length;g++){var h=f[g].substring(1);switch(f[g].charAt(0)){case "+":try{c[d++]=[1,decodeURI(h)]}catch(j){throw Error("Illegal escape in diff_fromDelta: "+h);}break;case "-":case "=":var i=parseInt(h,10);if(isNaN(i)||0>i)throw Error("Invalid number in diff_fromDelta: "+h);h=a.substring(e,e+=i);"="==f[g].charAt(0)?c[d++]=[0,h]:c[d++]=[-1,h];break;default:if(f[g])throw Error("Invalid diff operation in diff_fromDelta: "+
f[g]);}}if(e!=a.length)throw Error("Delta length ("+e+") does not equal source text length ("+a.length+").");return c};diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error("Null input. (match_main)");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};
diff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return!f.Match_Distance?g?1:e:e+g/f.Match_Distance}if(b.length>this.Match_MaxBits)throw Error("Pattern too long for this browser.");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));for(var j=1<<b.length-1,h=-1,i,k,q=b.length+a.length,r,t=0;t<b.length;t++){i=0;for(k=q;i<k;)d(t,c+
k)<=g?i=k:q=k,k=Math.floor((q-i)/2+i);q=k;i=Math.max(1,c-k+1);var p=Math.min(c+k,a.length)+b.length;k=Array(p+2);for(k[p+1]=(1<<t)-1;p>=i;p--){var w=e[a.charAt(p-1)];k[p]=0===t?(k[p+1]<<1|1)&w:(k[p+1]<<1|1)&w|((r[p+1]|r[p])<<1|1)|r[p+1];if(k[p]&j&&(w=d(t,p-1),w<=g))if(g=w,h=p-1,h>c)i=Math.max(1,2*c-h);else break}if(d(t+1,c)>g)break;r=k}return h};
diff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c<a.length;c++)b[a.charAt(c)]=0;for(c=0;c<a.length;c++)b[a.charAt(c)]|=1<<a.length-c-1;return b};
diff_match_patch.prototype.patch_addContext_=function(a,b){if(0!=b.length){for(var c=b.substring(a.start2,a.start2+a.length1),d=0;b.indexOf(c)!=b.lastIndexOf(c)&&c.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)d+=this.Patch_Margin,c=b.substring(a.start2-d,a.start2+a.length1+d);d+=this.Patch_Margin;(c=b.substring(a.start2-d,a.start2))&&a.diffs.unshift([0,c]);(d=b.substring(a.start2+a.length1,a.start2+a.length1+d))&&a.diffs.push([0,d]);a.start1-=c.length;a.start2-=c.length;a.length1+=
c.length+d.length;a.length2+=c.length+d.length}};
diff_match_patch.prototype.patch_make=function(a,b,c){var d;if("string"==typeof a&&"string"==typeof b&&"undefined"==typeof c)d=a,b=this.diff_main(d,b,!0),2<b.length&&(this.diff_cleanupSemantic(b),this.diff_cleanupEfficiency(b));else if(a&&"object"==typeof a&&"undefined"==typeof b&&"undefined"==typeof c)b=a,d=this.diff_text1(b);else if("string"==typeof a&&b&&"object"==typeof b&&"undefined"==typeof c)d=a;else if("string"==typeof a&&"string"==typeof b&&c&&"object"==typeof c)d=a,b=c;else throw Error("Unknown call format to patch_make.");
if(0===b.length)return[];c=[];a=new diff_match_patch.patch_obj;for(var e=0,f=0,g=0,h=d,j=0;j<b.length;j++){var i=b[j][0],k=b[j][1];!e&&0!==i&&(a.start1=f,a.start2=g);switch(i){case 1:a.diffs[e++]=b[j];a.length2+=k.length;d=d.substring(0,g)+k+d.substring(g);break;case -1:a.length1+=k.length;a.diffs[e++]=b[j];d=d.substring(0,g)+d.substring(g+k.length);break;case 0:k.length<=2*this.Patch_Margin&&e&&b.length!=j+1?(a.diffs[e++]=b[j],a.length1+=k.length,a.length2+=k.length):k.length>=2*this.Patch_Margin&&
e&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}1!==i&&(f+=k.length);-1!==i&&(g+=k.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new diff_match_patch.patch_obj;e.diffs=[];for(var f=0;f<d.diffs.length;f++)e.diffs[f]=d.diffs[f].slice();e.start1=d.start1;e.start2=d.start2;e.length1=d.length1;e.length2=d.length2;b[c]=e}return b};
diff_match_patch.prototype.patch_apply=function(a,b){if(0==a.length)return[b,[]];a=this.patch_deepCopy(a);var c=this.patch_addPadding(a);b=c+b+c;this.patch_splitMax(a);for(var d=0,e=[],f=0;f<a.length;f++){var g=a[f].start2+d,h=this.diff_text1(a[f].diffs),j,i=-1;if(h.length>this.Match_MaxBits){if(j=this.match_main(b,h.substring(0,this.Match_MaxBits),g),-1!=j&&(i=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==i||j>=i))j=-1}else j=this.match_main(b,h,g);
if(-1==j)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=j-g,g=-1==i?b.substring(j,j+h.length):b.substring(j,i+this.Match_MaxBits),h==g)b=b.substring(0,j)+this.diff_text2(a[f].diffs)+b.substring(j+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);for(var h=0,k,i=0;i<a[f].diffs.length;i++){var q=a[f].diffs[i];0!==q[0]&&(k=this.diff_xIndex(g,h));1===q[0]?b=b.substring(0,
j+k)+q[1]+b.substring(j+k):-1===q[0]&&(b=b.substring(0,j+k)+b.substring(j+this.diff_xIndex(g,h+q[1].length)));-1!==q[0]&&(h+=q[1].length)}}}b=b.substring(c.length,b.length-c.length);return[b,e]};
diff_match_patch.prototype.patch_addPadding=function(a){for(var b=this.Patch_Margin,c="",d=1;d<=b;d++)c+=String.fromCharCode(d);for(d=0;d<a.length;d++)a[d].start1+=b,a[d].start2+=b;var d=a[0],e=d.diffs;if(0==e.length||0!=e[0][0])e.unshift([0,c]),d.start1-=b,d.start2-=b,d.length1+=b,d.length2+=b;else if(b>e[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;0==e.length||0!=e[e.length-1][0]?(e.push([0,
c]),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};
diff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c<a.length;c++)if(!(a[c].length1<=b)){var d=a[c];a.splice(c--,1);for(var e=d.start1,f=d.start2,g="";0!==d.diffs.length;){var h=new diff_match_patch.patch_obj,j=!0;h.start1=e-g.length;h.start2=f-g.length;""!==g&&(h.length1=h.length2=g.length,h.diffs.push([0,g]));for(;0!==d.diffs.length&&h.length1<b-this.Patch_Margin;){var g=d.diffs[0][0],i=d.diffs[0][1];1===g?(h.length2+=i.length,f+=i.length,h.diffs.push(d.diffs.shift()),
j=!1):-1===g&&1==h.diffs.length&&0==h.diffs[0][0]&&i.length>2*b?(h.length1+=i.length,e+=i.length,j=!1,h.diffs.push([g,i]),d.diffs.shift()):(i=i.substring(0,b-h.length1-this.Patch_Margin),h.length1+=i.length,e+=i.length,0===g?(h.length2+=i.length,f+=i.length):j=!1,h.diffs.push([g,i]),i==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(i.length))}g=this.diff_text2(h.diffs);g=g.substring(g.length-this.Patch_Margin);i=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);""!==i&&
(h.length1+=i.length,h.length2+=i.length,0!==h.diffs.length&&0===h.diffs[h.diffs.length-1][0]?h.diffs[h.diffs.length-1][1]+=i:h.diffs.push([0,i]));j||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c];return b.join("")};
diff_match_patch.prototype.patch_fromText=function(a){var b=[];if(!a)return b;a=a.split("\n");for(var c=0,d=/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;c<a.length;){var e=a[c].match(d);if(!e)throw Error("Invalid patch string: "+a[c]);var f=new diff_match_patch.patch_obj;b.push(f);f.start1=parseInt(e[1],10);""===e[2]?(f.start1--,f.length1=1):"0"==e[2]?f.length1=0:(f.start1--,f.length1=parseInt(e[2],10));f.start2=parseInt(e[3],10);""===e[4]?(f.start2--,f.length2=1):"0"==e[4]?f.length2=0:(f.start2--,f.length2=
parseInt(e[4],10));for(c++;c<a.length;){e=a[c].charAt(0);try{var g=decodeURI(a[c].substring(1))}catch(h){throw Error("Illegal escape in patch_fromText: "+g);}if("-"==e)f.diffs.push([-1,g]);else if("+"==e)f.diffs.push([1,g]);else if(" "==e)f.diffs.push([0,g]);else if("@"==e)break;else if(""!==e)throw Error('Invalid patch mode "'+e+'" in: '+g);c++}}return b};diff_match_patch.patch_obj=function(){this.diffs=[];this.start2=this.start1=null;this.length2=this.length1=0};
diff_match_patch.patch_obj.prototype.toString=function(){var a,b;a=0===this.length1?this.start1+",0":1==this.length1?this.start1+1:this.start1+1+","+this.length1;b=0===this.length2?this.start2+",0":1==this.length2?this.start2+1:this.start2+1+","+this.length2;a=["@@ -"+a+" +"+b+" @@\n"];var c;for(b=0;b<this.diffs.length;b++){switch(this.diffs[b][0]){case 1:c="+";break;case -1:c="-";break;case 0:c=" "}a[b+1]=c+encodeURI(this.diffs[b][1])+"\n"}return a.join("").replace(/%20/g," ")};
this.diff_match_patch=diff_match_patch;this.DIFF_DELETE=-1;this.DIFF_INSERT=1;this.DIFF_EQUAL=0;})();
@@ -62,6 +62,12 @@
color: #44c; color: #44c;
} }
.CodeMirror-merge-copy-reverse {
position: absolute;
cursor: pointer;
color: #44c;
}
.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; } .CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }
.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; } .CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }
@@ -90,3 +96,17 @@
.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; } .CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; } .CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; } .CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
.CodeMirror-merge-collapsed-widget:before {
content: "(...)";
}
.CodeMirror-merge-collapsed-widget {
cursor: pointer;
color: #88b;
background: #eef;
border: 1px solid #ddf;
font-size: 90%;
padding: 0 3px;
border-radius: 4px;
}
.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }
+218 -76
View File
@@ -1,14 +1,17 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"), require("diff_match_patch"));
else if (typeof define == "function" && define.amd) // AMD else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod); define(["../../lib/codemirror", "diff_match_patch"], mod);
else // Plain browser env else // Plain browser env
mod(CodeMirror); mod(CodeMirror, diff_match_patch);
})(function(CodeMirror) { })(function(CodeMirror, diff_match_patch) {
"use strict"; "use strict";
// declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL
var Pos = CodeMirror.Pos; var Pos = CodeMirror.Pos;
var svgNS = "http://www.w3.org/2000/svg"; var svgNS = "http://www.w3.org/2000/svg";
@@ -28,13 +31,15 @@
insert: "CodeMirror-merge-r-inserted", insert: "CodeMirror-merge-r-inserted",
del: "CodeMirror-merge-r-deleted", del: "CodeMirror-merge-r-deleted",
connect: "CodeMirror-merge-r-connect"}; connect: "CodeMirror-merge-r-connect"};
if (mv.options.connect == "align")
this.aligners = [];
} }
DiffView.prototype = { DiffView.prototype = {
constructor: DiffView, constructor: DiffView,
init: function(pane, orig, options) { init: function(pane, orig, options) {
this.edit = this.mv.edit; this.edit = this.mv.edit;
this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: true}, copyObj(options))); this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));
this.diff = getDiff(asString(orig), asString(options.value)); this.diff = getDiff(asString(orig), asString(options.value));
this.diffOutOfDate = false; this.diffOutOfDate = false;
@@ -53,6 +58,14 @@
} }
}; };
function ensureDiff(dv) {
if (dv.diffOutOfDate) {
dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());
dv.diffOutOfDate = false;
CodeMirror.signal(dv.edit, "updateDiff", dv.diff);
}
}
function registerUpdate(dv) { function registerUpdate(dv) {
var edit = {from: 0, to: 0, marked: []}; var edit = {from: 0, to: 0, marked: []};
var orig = {from: 0, to: 0, marked: []}; var orig = {from: 0, to: 0, marked: []};
@@ -60,21 +73,17 @@
function update(mode) { function update(mode) {
if (mode == "full") { if (mode == "full") {
if (dv.svg) clear(dv.svg); if (dv.svg) clear(dv.svg);
clear(dv.copyButtons); if (dv.copyButtons) clear(dv.copyButtons);
clearMarks(dv.edit, edit.marked, dv.classes); clearMarks(dv.edit, edit.marked, dv.classes);
clearMarks(dv.orig, orig.marked, dv.classes); clearMarks(dv.orig, orig.marked, dv.classes);
edit.from = edit.to = orig.from = orig.to = 0; edit.from = edit.to = orig.from = orig.to = 0;
} }
if (dv.diffOutOfDate) { ensureDiff(dv);
dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());
dv.diffOutOfDate = false;
CodeMirror.signal(dv.edit, "updateDiff", dv.diff);
}
if (dv.showDifferences) { if (dv.showDifferences) {
updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes); updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);
updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes); updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
} }
drawConnectors(dv); makeConnections(dv);
} }
function set(slow) { function set(slow) {
clearTimeout(debounceChange); clearTimeout(debounceChange);
@@ -101,10 +110,10 @@
function registerScroll(dv) { function registerScroll(dv) {
dv.edit.on("scroll", function() { dv.edit.on("scroll", function() {
syncScroll(dv, DIFF_INSERT) && drawConnectors(dv); syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
}); });
dv.orig.on("scroll", function() { dv.orig.on("scroll", function() {
syncScroll(dv, DIFF_DELETE) && drawConnectors(dv); syncScroll(dv, DIFF_DELETE) && makeConnections(dv);
}); });
} }
@@ -119,24 +128,29 @@
// (to prevent feedback loops) // (to prevent feedback loops)
if (editor.state.scrollSetBy == dv && (editor.state.scrollSetAt || 0) + 50 > now) return false; if (editor.state.scrollSetBy == dv && (editor.state.scrollSetAt || 0) + 50 > now) return false;
var sInfo = editor.getScrollInfo(), halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen; var sInfo = editor.getScrollInfo();
var mid = editor.lineAtHeight(midY, "local"); if (dv.mv.options.connect == "align") {
var around = chunkBoundariesAround(dv.diff, mid, type == DIFF_INSERT); targetPos = sInfo.top;
var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig); } else {
var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit); var halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;
var ratio = (midY - off.top) / (off.bot - off.top); var mid = editor.lineAtHeight(midY, "local");
var targetPos = (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top); var around = chunkBoundariesAround(dv.diff, mid, type == DIFF_INSERT);
var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);
var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);
var ratio = (midY - off.top) / (off.bot - off.top);
var targetPos = (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top);
var botDist, mix; var botDist, mix;
// Some careful tweaking to make sure no space is left out of view // Some careful tweaking to make sure no space is left out of view
// when scrolling to top or bottom. // when scrolling to top or bottom.
if (targetPos > sInfo.top && (mix = sInfo.top / halfScreen) < 1) { if (targetPos > sInfo.top && (mix = sInfo.top / halfScreen) < 1) {
targetPos = targetPos * mix + sInfo.top * (1 - mix); targetPos = targetPos * mix + sInfo.top * (1 - mix);
} else if ((botDist = sInfo.height - sInfo.clientHeight - sInfo.top) < halfScreen) { } else if ((botDist = sInfo.height - sInfo.clientHeight - sInfo.top) < halfScreen) {
var otherInfo = other.getScrollInfo(); var otherInfo = other.getScrollInfo();
var botDistOther = otherInfo.height - otherInfo.clientHeight - targetPos; var botDistOther = otherInfo.height - otherInfo.clientHeight - targetPos;
if (botDistOther > botDist && (mix = botDist / halfScreen) < 1) if (botDistOther > botDist && (mix = botDist / halfScreen) < 1)
targetPos = targetPos * mix + (otherInfo.height - otherInfo.clientHeight - botDist) * (1 - mix); targetPos = targetPos * mix + (otherInfo.height - otherInfo.clientHeight - botDist) * (1 - mix);
}
} }
other.scrollTo(sInfo.left, targetPos); other.scrollTo(sInfo.left, targetPos);
@@ -154,7 +168,7 @@
function setScrollLock(dv, val, action) { function setScrollLock(dv, val, action) {
dv.lockScroll = val; dv.lockScroll = val;
if (val && action != false) syncScroll(dv, DIFF_INSERT) && drawConnectors(dv); if (val && action != false) syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
dv.lockButton.innerHTML = val ? "\u21db\u21da" : "\u21db&nbsp;&nbsp;\u21da"; dv.lockButton.innerHTML = val ? "\u21db\u21da" : "\u21db&nbsp;&nbsp;\u21da";
} }
@@ -165,7 +179,7 @@
var mark = arr[i]; var mark = arr[i];
if (mark instanceof CodeMirror.TextMarker) { if (mark instanceof CodeMirror.TextMarker) {
mark.clear(); mark.clear();
} else { } else if (mark.parent) {
editor.removeLineClass(mark, "background", classes.chunk); editor.removeLineClass(mark, "background", classes.chunk);
editor.removeLineClass(mark, "background", classes.start); editor.removeLineClass(mark, "background", classes.start);
editor.removeLineClass(mark, "background", classes.end); editor.removeLineClass(mark, "background", classes.end);
@@ -242,47 +256,112 @@
// Updating the gap between editor and original // Updating the gap between editor and original
function drawConnectors(dv) { function makeConnections(dv) {
if (!dv.showDifferences) return; if (!dv.showDifferences) return;
var align = dv.mv.options.connect == "align", oldScrollEdit, oldScrollOrig;
if (align) {
if (!dv.orig.curOp) return dv.orig.operation(function() {
makeConnections(dv);
});
oldScrollEdit = dv.edit.getScrollInfo().top;
oldScrollOrig = dv.orig.getScrollInfo().top;
for (var i = 0; i < dv.aligners.length; i++)
dv.aligners[i].clear();
dv.aligners.length = 0;
var extraSpaceAbove = {edit: 0, orig: 0};
}
if (dv.svg) { if (dv.svg) {
clear(dv.svg); clear(dv.svg);
var w = dv.gap.offsetWidth; var w = dv.gap.offsetWidth;
attrs(dv.svg, "width", w, "height", dv.gap.offsetHeight); attrs(dv.svg, "width", w, "height", dv.gap.offsetHeight);
} }
clear(dv.copyButtons); if (dv.copyButtons) clear(dv.copyButtons);
var flip = dv.type == "left";
var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport(); var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();
var sTopEdit = dv.edit.getScrollInfo().top, sTopOrig = dv.orig.getScrollInfo().top; var sTopEdit = dv.edit.getScrollInfo().top, sTopOrig = dv.orig.getScrollInfo().top;
iterateChunks(dv.diff, function(topOrig, botOrig, topEdit, botEdit) { iterateChunks(dv.diff, function(topOrig, botOrig, topEdit, botEdit) {
if (topEdit > vpEdit.to || botEdit < vpEdit.from || if (topEdit <= vpEdit.to && botEdit >= vpEdit.from &&
topOrig > vpOrig.to || botOrig < vpOrig.from) topOrig <= vpOrig.to && botOrig >= vpOrig.from)
return; drawConnectorsForChunk(dv, topOrig, botOrig, topEdit, botEdit, sTopOrig, sTopEdit, w);
var topLpx = dv.orig.heightAtLine(topOrig, "local") - sTopOrig, top = topLpx; if (align && (topEdit <= vpEdit.to || topOrig <= vpOrig.to)) {
if (dv.svg) { var above = (botEdit < vpEdit.from && botOrig < vpOrig.from);
var topRpx = dv.edit.heightAtLine(topEdit, "local") - sTopEdit; alignChunks(dv, topOrig, botOrig, topEdit, botEdit, above && extraSpaceAbove);
if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }
var botLpx = dv.orig.heightAtLine(botOrig, "local") - sTopOrig;
var botRpx = dv.edit.heightAtLine(botEdit, "local") - sTopEdit;
if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }
var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;
var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;
attrs(dv.svg.appendChild(document.createElementNS(svgNS, "path")),
"d", "M -1 " + topRpx + curveTop + " L " + (w + 2) + " " + botLpx + curveBot + " z",
"class", dv.classes.connect);
} }
var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\u21dd" : "\u21dc",
"CodeMirror-merge-copy"));
copy.title = "Revert chunk";
copy.chunk = {topEdit: topEdit, botEdit: botEdit, topOrig: topOrig, botOrig: botOrig};
copy.style.top = top + "px";
}); });
if (align) {
if (extraSpaceAbove.edit)
dv.aligners.push(padBelow(dv.edit, 0, extraSpaceAbove.edit));
if (extraSpaceAbove.orig)
dv.aligners.push(padBelow(dv.orig, 0, extraSpaceAbove.orig));
dv.edit.scrollTo(null, oldScrollEdit);
dv.orig.scrollTo(null, oldScrollOrig);
}
} }
function copyChunk(dv, chunk) { function drawConnectorsForChunk(dv, topOrig, botOrig, topEdit, botEdit, sTopOrig, sTopEdit, w) {
var flip = dv.type == "left";
var top = dv.orig.heightAtLine(topOrig, "local") - sTopOrig;
if (dv.svg) {
var topLpx = top;
var topRpx = dv.edit.heightAtLine(topEdit, "local") - sTopEdit;
if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }
var botLpx = dv.orig.heightAtLine(botOrig, "local") - sTopOrig;
var botRpx = dv.edit.heightAtLine(botEdit, "local") - sTopEdit;
if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }
var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;
var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;
attrs(dv.svg.appendChild(document.createElementNS(svgNS, "path")),
"d", "M -1 " + topRpx + curveTop + " L " + (w + 2) + " " + botLpx + curveBot + " z",
"class", dv.classes.connect);
}
if (dv.copyButtons) {
var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\u21dd" : "\u21dc",
"CodeMirror-merge-copy"));
var editOriginals = dv.mv.options.allowEditingOriginals;
copy.title = editOriginals ? "Push to left" : "Revert chunk";
copy.chunk = {topEdit: topEdit, botEdit: botEdit, topOrig: topOrig, botOrig: botOrig};
copy.style.top = top + "px";
if (editOriginals) {
var topReverse = dv.orig.heightAtLine(topEdit, "local") - sTopEdit;
var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\u21dd" : "\u21dc",
"CodeMirror-merge-copy-reverse"));
copyReverse.title = "Push to right";
copyReverse.chunk = {topEdit: topOrig, botEdit: botOrig, topOrig: topEdit, botOrig: botEdit};
copyReverse.style.top = topReverse + "px";
dv.type == "right" ? copyReverse.style.left = "2px" : copyReverse.style.right = "2px";
}
}
}
function alignChunks(dv, topOrig, botOrig, topEdit, botEdit, aboveViewport) {
var topOrigPx = dv.orig.heightAtLine(topOrig, "local");
var botOrigPx = dv.orig.heightAtLine(botOrig, "local");
var topEditPx = dv.edit.heightAtLine(topEdit, "local");
var botEditPx = dv.edit.heightAtLine(botEdit, "local");
var origH = botOrigPx -topOrigPx, editH = botEditPx - topEditPx;
var diff = editH - origH;
if (diff > 1) {
if (aboveViewport) aboveViewport.orig += diff;
else dv.aligners.push(padBelow(dv.orig, botOrig - 1, diff));
} else if (diff < -1) {
if (aboveViewport) aboveViewport.edit -= diff;
else dv.aligners.push(padBelow(dv.edit, botEdit - 1, -diff));
}
return 0;
}
function padBelow(cm, line, size) {
var elt = document.createElement("div");
elt.style.height = size + "px"; elt.style.minWidth = "1px";
return cm.addLineWidget(line, elt, {height: size});
}
function copyChunk(dv, to, from, chunk) {
if (dv.diffOutOfDate) return; if (dv.diffOutOfDate) return;
dv.edit.replaceRange(dv.orig.getRange(Pos(chunk.topOrig, 0), Pos(chunk.botOrig, 0)), to.replaceRange(from.getRange(Pos(chunk.topOrig, 0), Pos(chunk.botOrig, 0)),
Pos(chunk.topEdit, 0), Pos(chunk.botEdit, 0)); Pos(chunk.topEdit, 0), Pos(chunk.botEdit, 0));
} }
@@ -291,7 +370,15 @@
var MergeView = CodeMirror.MergeView = function(node, options) { var MergeView = CodeMirror.MergeView = function(node, options) {
if (!(this instanceof MergeView)) return new MergeView(node, options); if (!(this instanceof MergeView)) return new MergeView(node, options);
this.options = options;
var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight; var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight;
if (origLeft && origRight) {
if (options.connect == "align")
throw new Error("connect: \"align\" is not supported for three-way merge views");
if (options.collapseIdentical)
throw new Error("collapseIdentical option is not supported for three-way merge views");
}
var hasLeft = origLeft != null, hasRight = origRight != null; var hasLeft = origLeft != null, hasRight = origRight != null;
var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0); var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0);
var wrap = [], left = this.left = null, right = this.right = null; var wrap = [], left = this.left = null, right = this.right = null;
@@ -316,15 +403,19 @@
(hasRight ? rightPane : editPane).className += " CodeMirror-merge-pane-rightmost"; (hasRight ? rightPane : editPane).className += " CodeMirror-merge-pane-rightmost";
wrap.push(elt("div", null, null, "height: 0; clear: both;")); wrap.push(elt("div", null, null, "height: 0; clear: both;"));
var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-merge CodeMirror-merge-" + panes + "pane")); var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-merge CodeMirror-merge-" + panes + "pane"));
this.edit = CodeMirror(editPane, copyObj(options)); this.edit = CodeMirror(editPane, copyObj(options));
if (left) left.init(leftPane, origLeft, options); if (left) left.init(leftPane, origLeft, options);
if (right) right.init(rightPane, origRight, options); if (right) right.init(rightPane, origRight, options);
if (options.collapseIdentical)
collapseIdenticalStretches(left || right, options.collapseIdentical);
var onResize = function() { var onResize = function() {
if (left) drawConnectors(left); if (left) makeConnections(left);
if (right) drawConnectors(right); if (right) makeConnections(right);
}; };
CodeMirror.on(window, "resize", onResize); CodeMirror.on(window, "resize", onResize);
var resizeInterval = setInterval(function() { var resizeInterval = setInterval(function() {
@@ -338,16 +429,26 @@
lock.title = "Toggle locked scrolling"; lock.title = "Toggle locked scrolling";
var lockWrap = elt("div", [lock], "CodeMirror-merge-scrolllock-wrap"); var lockWrap = elt("div", [lock], "CodeMirror-merge-scrolllock-wrap");
CodeMirror.on(lock, "click", function() { setScrollLock(dv, !dv.lockScroll); }); CodeMirror.on(lock, "click", function() { setScrollLock(dv, !dv.lockScroll); });
dv.copyButtons = elt("div", null, "CodeMirror-merge-copybuttons-" + dv.type); var gapElts = [lockWrap];
CodeMirror.on(dv.copyButtons, "click", function(e) { if (dv.mv.options.revertButtons !== false) {
var node = e.target || e.srcElement; dv.copyButtons = elt("div", null, "CodeMirror-merge-copybuttons-" + dv.type);
if (node.chunk) copyChunk(dv, node.chunk); CodeMirror.on(dv.copyButtons, "click", function(e) {
}); var node = e.target || e.srcElement;
var gapElts = [dv.copyButtons, lockWrap]; if (!node.chunk) return;
var svg = document.createElementNS && document.createElementNS(svgNS, "svg"); if (node.className == "CodeMirror-merge-copy-reverse") {
if (svg && !svg.createSVGRect) svg = null; copyChunk(dv, dv.orig, dv.edit, node.chunk);
dv.svg = svg; return;
if (svg) gapElts.push(svg); }
copyChunk(dv, dv.edit, dv.orig, node.chunk);
});
gapElts.unshift(dv.copyButtons);
}
if (dv.mv.options.connect != "align") {
var svg = document.createElementNS && document.createElementNS(svgNS, "svg");
if (svg && !svg.createSVGRect) svg = null;
dv.svg = svg;
if (svg) gapElts.push(svg);
}
return dv.gap = elt("div", gapElts, "CodeMirror-merge-gap"); return dv.gap = elt("div", gapElts, "CodeMirror-merge-gap");
} }
@@ -362,10 +463,10 @@
if (this.left) this.left.setShowDifferences(val); if (this.left) this.left.setShowDifferences(val);
}, },
rightChunks: function() { rightChunks: function() {
return this.right && getChunks(this.right.diff); return this.right && getChunks(this.right);
}, },
leftChunks: function() { leftChunks: function() {
return this.left && getChunks(this.left.diff); return this.left && getChunks(this.left);
} }
}; };
@@ -416,9 +517,10 @@
f(startOrig, orig.line + 1, startEdit, edit.line + 1); f(startOrig, orig.line + 1, startEdit, edit.line + 1);
} }
function getChunks(diff) { function getChunks(dv) {
ensureDiff(dv);
var collect = []; var collect = [];
iterateChunks(diff, function(topOrig, botOrig, topEdit, botEdit) { iterateChunks(dv.diff, function(topOrig, botOrig, topEdit, botEdit) {
collect.push({origFrom: topOrig, origTo: botOrig, collect.push({origFrom: topOrig, origTo: botOrig,
editFrom: topEdit, editTo: botEdit}); editFrom: topEdit, editTo: botEdit});
}); });
@@ -458,6 +560,46 @@
return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}}; return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}};
} }
function collapseSingle(cm, from, to) {
cm.addLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
var widget = document.createElement("span");
widget.className = "CodeMirror-merge-collapsed-widget";
widget.title = "Identical text collapsed. Click to expand.";
var mark = cm.markText(Pos(from, 0), Pos(to - 1), {
inclusiveLeft: true,
inclusiveRight: true,
replacedWith: widget,
clearOnEnter: true
});
function clear() {
mark.clear();
cm.removeLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
}
widget.addEventListener("click", clear);
return {mark: mark, clear: clear};
}
function collapseStretch(dv, origStart, editStart, size) {
var mOrig = collapseSingle(dv.orig, origStart, origStart + size);
var mEdit = collapseSingle(dv.edit, editStart, editStart + size);
mOrig.mark.on("clear", function() { mEdit.clear(); });
mEdit.mark.on("clear", function() { mOrig.clear(); });
}
function collapseIdenticalStretches(dv, margin) {
if (typeof margin != "number") margin = 2;
var lastOrig = dv.orig.firstLine(), lastEdit = dv.edit.firstLine();
iterateChunks(dv.diff, function(topOrig, botOrig, _topEdit, botEdit) {
var identicalSize = topOrig - margin - lastOrig;
if (identicalSize > margin)
collapseStretch(dv, lastOrig, lastEdit, identicalSize);
lastOrig = botOrig + margin; lastEdit = botEdit + margin;
});
var bottomSize = dv.orig.lastLine() + 1 - lastOrig;
if (bottomSize > margin)
collapseStretch(dv, lastOrig, lastEdit, bottomSize);
}
// General utilities // General utilities
function elt(tag, content, className, style) { function elt(tag, content, className, style) {
+22 -16
View File
@@ -1,11 +1,14 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"), "cjs");
else if (typeof define == "function" && define.amd) // AMD else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod); define(["../../lib/codemirror"], function(CM) { mod(CM, "amd"); });
else // Plain browser env else // Plain browser env
mod(CodeMirror); mod(CodeMirror, "plain");
})(function(CodeMirror) { })(function(CodeMirror, env) {
if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js"; if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";
var loading = {}; var loading = {};
@@ -32,21 +35,24 @@
if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont); if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
if (loading.hasOwnProperty(mode)) return loading[mode].push(cont); if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
var script = document.createElement("script"); var file = CodeMirror.modeURL.replace(/%N/g, mode);
script.src = CodeMirror.modeURL.replace(/%N/g, mode); if (env == "plain") {
var others = document.getElementsByTagName("script")[0]; var script = document.createElement("script");
others.parentNode.insertBefore(script, others); script.src = file;
var list = loading[mode] = [cont]; var others = document.getElementsByTagName("script")[0];
var count = 0, poll = setInterval(function() { var list = loading[mode] = [cont];
if (++count > 100) return clearInterval(poll); CodeMirror.on(script, "load", function() {
if (CodeMirror.modes.hasOwnProperty(mode)) {
clearInterval(poll);
loading[mode] = null;
ensureDeps(mode, function() { ensureDeps(mode, function() {
for (var i = 0; i < list.length; ++i) list[i](); for (var i = 0; i < list.length; ++i) list[i]();
}); });
} });
}, 200); others.parentNode.insertBefore(script, others);
} else if (env == "cjs") {
require(file);
cont();
} else if (env == "amd") {
requirejs([file], cont);
}
}; };
CodeMirror.autoLoadMode = function(instance, mode) { CodeMirror.autoLoadMode = function(instance, mode) {
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function() { (function() {
CodeMirror.defineMode("markdown_with_stex", function(){ CodeMirror.defineMode("markdown_with_stex", function(){
var inner = CodeMirror.getMode({}, "stex"); var inner = CodeMirror.getMode({}, "stex");
+20 -5
View File
@@ -1,10 +1,14 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Utility function that allows modes to be combined. The mode given // Utility function that allows modes to be combined. The mode given
// as the base argument takes care of most of the normal mode // as the base argument takes care of most of the normal mode
// functionality, but a second (typically simple) mode is used, which // functionality, but a second (typically simple) mode is used, which
// can override the style of text. Both modes get to parse all of the // can override the style of text. Both modes get to parse all of the
// text, but when both assign a non-null style to a piece of code, the // text, but when both assign a non-null style to a piece of code, the
// overlay wins, unless the combine argument was true, in which case // overlay wins, unless the combine argument was true and not overridden,
// the styles are combined. // or state.overlay.combineTokens was true, in which case the styles are
// combined.
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
@@ -23,7 +27,8 @@ CodeMirror.overlayMode = function(base, overlay, combine) {
base: CodeMirror.startState(base), base: CodeMirror.startState(base),
overlay: CodeMirror.startState(overlay), overlay: CodeMirror.startState(overlay),
basePos: 0, baseCur: null, basePos: 0, baseCur: null,
overlayPos: 0, overlayCur: null overlayPos: 0, overlayCur: null,
streamSeen: null
}; };
}, },
copyState: function(state) { copyState: function(state) {
@@ -36,6 +41,12 @@ CodeMirror.overlayMode = function(base, overlay, combine) {
}, },
token: function(stream, state) { token: function(stream, state) {
if (stream != state.streamSeen ||
Math.min(state.basePos, state.overlayPos) < stream.start) {
state.streamSeen = stream;
state.basePos = state.overlayPos = stream.start;
}
if (stream.start == state.basePos) { if (stream.start == state.basePos) {
state.baseCur = base.token(stream, state.base); state.baseCur = base.token(stream, state.base);
state.basePos = stream.pos; state.basePos = stream.pos;
@@ -46,10 +57,14 @@ CodeMirror.overlayMode = function(base, overlay, combine) {
state.overlayPos = stream.pos; state.overlayPos = stream.pos;
} }
stream.pos = Math.min(state.basePos, state.overlayPos); stream.pos = Math.min(state.basePos, state.overlayPos);
if (stream.eol()) state.basePos = state.overlayPos = 0;
// state.overlay.combineTokens always takes precedence over combine,
// unless set to null
if (state.overlayCur == null) return state.baseCur; if (state.overlayCur == null) return state.baseCur;
if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur; else if (state.baseCur != null &&
state.overlay.combineTokens ||
combine && state.overlay.combineTokens == null)
return state.baseCur + " " + state.overlayCur;
else return state.overlayCur; else return state.overlayCur;
}, },
@@ -0,0 +1,213 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineSimpleMode = function(name, states) {
CodeMirror.defineMode(name, function(config) {
return CodeMirror.simpleMode(config, states);
});
};
CodeMirror.simpleMode = function(config, states) {
ensureState(states, "start");
var states_ = {}, meta = states.meta || {}, hasIndentation = false;
for (var state in states) if (state != meta && states.hasOwnProperty(state)) {
var list = states_[state] = [], orig = states[state];
for (var i = 0; i < orig.length; i++) {
var data = orig[i];
list.push(new Rule(data, states));
if (data.indent || data.dedent) hasIndentation = true;
}
}
var mode = {
startState: function() {
return {state: "start", pending: null,
local: null, localState: null,
indent: hasIndentation ? [] : null};
},
copyState: function(state) {
var s = {state: state.state, pending: state.pending,
local: state.local, localState: null,
indent: state.indent && state.indent.slice(0)};
if (state.localState)
s.localState = CodeMirror.copyState(state.local.mode, state.localState);
if (state.stack)
s.stack = state.stack.slice(0);
for (var pers = state.persistentStates; pers; pers = pers.next)
s.persistentStates = {mode: pers.mode,
spec: pers.spec,
state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state),
next: s.persistentStates};
return s;
},
token: tokenFunction(states_, config),
innerMode: function(state) { return state.local && {mode: state.local.mode, state: state.localState}; },
indent: indentFunction(states_, meta)
};
if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop))
mode[prop] = meta[prop];
return mode;
};
function ensureState(states, name) {
if (!states.hasOwnProperty(name))
throw new Error("Undefined state " + name + "in simple mode");
}
function toRegex(val, caret) {
if (!val) return /(?:)/;
var flags = "";
if (val instanceof RegExp) {
if (val.ignoreCase) flags = "i";
val = val.source;
} else {
val = String(val);
}
return new RegExp((caret === false ? "" : "^") + "(?:" + val + ")", flags);
}
function asToken(val) {
if (!val) return null;
if (typeof val == "string") return val.replace(/\./g, " ");
var result = [];
for (var i = 0; i < val.length; i++)
result.push(val[i] && val[i].replace(/\./g, " "));
return result;
}
function Rule(data, states) {
if (data.next || data.push) ensureState(states, data.next || data.push);
this.regex = toRegex(data.regex);
this.token = asToken(data.token);
this.data = data;
}
function tokenFunction(states, config) {
return function(stream, state) {
if (state.pending) {
var pend = state.pending.shift();
if (state.pending.length == 0) state.pending = null;
stream.pos += pend.text.length;
return pend.token;
}
if (state.local) {
if (state.local.end && stream.match(state.local.end)) {
var tok = state.local.endToken || null;
state.local = state.localState = null;
return tok;
} else {
var tok = state.local.mode.token(stream, state.localState), m;
if (state.local.endScan && (m = state.local.endScan.exec(stream.current())))
stream.pos = stream.start + m.index;
return tok;
}
}
var curState = states[state.state];
for (var i = 0; i < curState.length; i++) {
var rule = curState[i];
var matches = (!rule.data.sol || stream.sol()) && stream.match(rule.regex);
if (matches) {
if (rule.data.next) {
state.state = rule.data.next;
} else if (rule.data.push) {
(state.stack || (state.stack = [])).push(state.state);
state.state = rule.data.push;
} else if (rule.data.pop && state.stack && state.stack.length) {
state.state = state.stack.pop();
}
if (rule.data.mode)
enterLocalMode(config, state, rule.data.mode, rule.token);
if (rule.data.indent)
state.indent.push(stream.indentation() + config.indentUnit);
if (rule.data.dedent)
state.indent.pop();
if (matches.length > 2) {
state.pending = [];
for (var j = 2; j < matches.length; j++)
if (matches[j])
state.pending.push({text: matches[j], token: rule.token[j - 1]});
stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));
return rule.token[0];
} else if (rule.token && rule.token.join) {
return rule.token[0];
} else {
return rule.token;
}
}
}
stream.next();
return null;
};
}
function cmp(a, b) {
if (a === b) return true;
if (!a || typeof a != "object" || !b || typeof b != "object") return false;
var props = 0;
for (var prop in a) if (a.hasOwnProperty(prop)) {
if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false;
props++;
}
for (var prop in b) if (b.hasOwnProperty(prop)) props--;
return props == 0;
}
function enterLocalMode(config, state, spec, token) {
var pers;
if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next)
if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p;
var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec);
var lState = pers ? pers.state : CodeMirror.startState(mode);
if (spec.persistent && !pers)
state.persistentStates = {mode: mode, spec: spec.spec, state: lState, next: state.persistentStates};
state.localState = lState;
state.local = {mode: mode,
end: spec.end && toRegex(spec.end),
endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false),
endToken: token && token.join ? token[token.length - 1] : token};
}
function indexOf(val, arr) {
for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true;
}
function indentFunction(states, meta) {
return function(state, textAfter, line) {
if (state.local && state.local.mode.indent)
return state.local.mode.indent(state.localState, textAfter, line);
if (state.indent == null || state.local || meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1)
return CodeMirror.Pass;
var pos = state.indent.length - 1, rules = states[state.state];
scan: for (;;) {
for (var i = 0; i < rules.length; i++) {
var rule = rules[i];
if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {
var m = rule.regex.exec(textAfter);
if (m && m[0]) {
pos--;
if (rule.next || rule.push) rules = states[rule.next || rule.push];
textAfter = textAfter.slice(m[0].length);
continue scan;
}
}
}
break;
}
return pos < 0 ? 0 : state.indent[pos];
};
}
});
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("./runmode")); mod(require("../../lib/codemirror"), require("./runmode"));
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
window.CodeMirror = {}; window.CodeMirror = {};
(function() { (function() {
@@ -71,7 +74,11 @@ CodeMirror.startState = function (mode, a1, a2) {
}; };
var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
CodeMirror.defineMode = function (name, mode) { modes[name] = mode; }; CodeMirror.defineMode = function (name, mode) {
if (arguments.length > 2)
mode.dependencies = Array.prototype.slice.call(arguments, 2);
modes[name] = mode;
};
CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; }; CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; };
CodeMirror.resolveMode = function(spec) { CodeMirror.resolveMode = function(spec) {
if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
@@ -139,6 +146,7 @@ CodeMirror.runMode = function (string, modespec, callback, options) {
for (var i = 0, e = lines.length; i < e; ++i) { for (var i = 0, e = lines.length; i < e; ++i) {
if (i) callback("\n"); if (i) callback("\n");
var stream = new CodeMirror.StringStream(lines[i]); var stream = new CodeMirror.StringStream(lines[i]);
if (!stream.string && mode.blankLine) mode.blankLine(state);
while (!stream.eol()) { while (!stream.eol()) {
var style = mode.token(stream, state); var style = mode.token(stream, state);
callback(stream.current(), style, i, stream.start, state); callback(stream.current(), style, i, stream.start, state);
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -57,6 +60,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) {
for (var i = 0, e = lines.length; i < e; ++i) { for (var i = 0, e = lines.length; i < e; ++i) {
if (i) callback("\n"); if (i) callback("\n");
var stream = new CodeMirror.StringStream(lines[i]); var stream = new CodeMirror.StringStream(lines[i]);
if (!stream.string && mode.blankLine) mode.blankLine(state);
while (!stream.eol()) { while (!stream.eol()) {
var style = mode.token(stream, state); var style = mode.token(stream, state);
callback(stream.current(), style, i, stream.start, state); callback(stream.current(), style, i, stream.start, state);
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
/* Just enough of CodeMirror to run runMode under node.js */ /* Just enough of CodeMirror to run runMode under node.js */
// declare global: StringStream // declare global: StringStream
@@ -71,10 +74,8 @@ exports.startState = function(mode, a1, a2) {
var modes = exports.modes = {}, mimeModes = exports.mimeModes = {}; var modes = exports.modes = {}, mimeModes = exports.mimeModes = {};
exports.defineMode = function(name, mode) { exports.defineMode = function(name, mode) {
if (arguments.length > 2) { if (arguments.length > 2)
mode.dependencies = []; mode.dependencies = Array.prototype.slice.call(arguments, 2);
for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
}
modes[name] = mode; modes[name] = mode;
}; };
exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; }; exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; };
@@ -107,6 +108,7 @@ exports.runMode = function(string, modespec, callback, options) {
for (var i = 0, e = lines.length; i < e; ++i) { for (var i = 0, e = lines.length; i < e; ++i) {
if (i) callback("\n"); if (i) callback("\n");
var stream = new exports.StringStream(lines[i]); var stream = new exports.StringStream(lines[i]);
if (!stream.string && mode.blankLine) mode.blankLine(state);
while (!stream.eol()) { while (!stream.eol()) {
var style = mode.token(stream, state); var style = mode.token(stream, state);
callback(stream.current(), style, i, stream.start, state); callback(stream.current(), style, i, stream.start, state);
@@ -0,0 +1,76 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineExtension("annotateScrollbar", function(className) {
return new Annotation(this, className);
});
function Annotation(cm, className) {
this.cm = cm;
this.className = className;
this.annotations = [];
this.div = cm.getWrapperElement().appendChild(document.createElement("div"));
this.div.style.cssText = "position: absolute; right: 0; top: 0; z-index: 7; pointer-events: none";
this.computeScale();
var self = this;
cm.on("refresh", this.resizeHandler = function(){
if (self.computeScale()) self.redraw();
});
}
Annotation.prototype.computeScale = function() {
var cm = this.cm;
var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight) /
cm.heightAtLine(cm.lastLine() + 1, "local");
if (hScale != this.hScale) {
this.hScale = hScale;
return true;
}
};
Annotation.prototype.update = function(annotations) {
this.annotations = annotations;
this.redraw();
};
Annotation.prototype.redraw = function() {
var cm = this.cm, hScale = this.hScale;
if (!cm.display.barWidth) return;
var frag = document.createDocumentFragment(), anns = this.annotations;
for (var i = 0, nextTop; i < anns.length; i++) {
var ann = anns[i];
var top = nextTop || cm.charCoords(ann.from, "local").top * hScale;
var bottom = cm.charCoords(ann.to, "local").bottom * hScale;
while (i < anns.length - 1) {
nextTop = cm.charCoords(anns[i + 1].from, "local").top * hScale;
if (nextTop > bottom + .9) break;
ann = anns[++i];
bottom = cm.charCoords(ann.to, "local").bottom * hScale;
}
var height = Math.max(bottom - top, 3);
var elt = frag.appendChild(document.createElement("div"));
elt.style.cssText = "position: absolute; right: 0px; width: " + Math.max(cm.display.barWidth - 1, 2) + "px; top: " + top + "px; height: " + height + "px";
elt.className = this.className;
}
this.div.textContent = "";
this.div.appendChild(frag);
};
Annotation.prototype.clear = function() {
this.cm.off("refresh", this.resizeHandler);
this.div.parentNode.removeChild(this.div);
};
});
@@ -0,0 +1,46 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineOption("scrollPastEnd", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) {
cm.off("change", onChange);
cm.off("refresh", updateBottomMargin);
cm.display.lineSpace.parentNode.style.paddingBottom = "";
cm.state.scrollPastEndPadding = null;
}
if (val) {
cm.on("change", onChange);
cm.on("refresh", updateBottomMargin);
updateBottomMargin(cm);
}
});
function onChange(cm, change) {
if (CodeMirror.changeEnd(change).line == cm.lastLine())
updateBottomMargin(cm);
}
function updateBottomMargin(cm) {
var padding = "";
if (cm.lineCount() > 1) {
var totalH = cm.display.scroller.clientHeight - 30,
lastLineH = cm.getLineHandle(cm.lastLine()).height;
padding = (totalH - lastLineH) + "px";
}
if (cm.state.scrollPastEndPadding != padding) {
cm.state.scrollPastEndPadding = padding;
cm.display.lineSpace.parentNode.style.paddingBottom = padding;
cm.setSize();
}
}
});
@@ -0,0 +1,66 @@
.CodeMirror-simplescroll-horizontal div, .CodeMirror-simplescroll-vertical div {
position: absolute;
background: #ccc;
-moz-box-sizing: border-box;
box-sizing: border-box;
border: 1px solid #bbb;
border-radius: 2px;
}
.CodeMirror-simplescroll-horizontal, .CodeMirror-simplescroll-vertical {
position: absolute;
z-index: 6;
background: #eee;
}
.CodeMirror-simplescroll-horizontal {
bottom: 0; left: 0;
height: 8px;
}
.CodeMirror-simplescroll-horizontal div {
bottom: 0;
height: 100%;
}
.CodeMirror-simplescroll-vertical {
right: 0; top: 0;
width: 8px;
}
.CodeMirror-simplescroll-vertical div {
right: 0;
width: 100%;
}
.CodeMirror-overlayscroll .CodeMirror-scrollbar-filler, .CodeMirror-overlayscroll .CodeMirror-gutter-filler {
display: none;
}
.CodeMirror-overlayscroll-horizontal div, .CodeMirror-overlayscroll-vertical div {
position: absolute;
background: #bcd;
border-radius: 3px;
}
.CodeMirror-overlayscroll-horizontal, .CodeMirror-overlayscroll-vertical {
position: absolute;
z-index: 6;
}
.CodeMirror-overlayscroll-horizontal {
bottom: 0; left: 0;
height: 6px;
}
.CodeMirror-overlayscroll-horizontal div {
bottom: 0;
height: 100%;
}
.CodeMirror-overlayscroll-vertical {
right: 0; top: 0;
width: 6px;
}
.CodeMirror-overlayscroll-vertical div {
right: 0;
width: 100%;
}
@@ -0,0 +1,141 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
function Bar(cls, orientation, scroll) {
this.orientation = orientation;
this.scroll = scroll;
this.screen = this.total = this.size = 1;
this.pos = 0;
this.node = document.createElement("div");
this.node.className = cls + "-" + orientation;
this.inner = this.node.appendChild(document.createElement("div"));
var self = this;
CodeMirror.on(this.inner, "mousedown", function(e) {
if (e.which != 1) return;
CodeMirror.e_preventDefault(e);
var axis = self.orientation == "horizontal" ? "pageX" : "pageY";
var start = e[axis], startpos = self.pos;
function done() {
CodeMirror.off(document, "mousemove", move);
CodeMirror.off(document, "mouseup", done);
}
function move(e) {
if (e.which != 1) return done();
self.moveTo(startpos + (e[axis] - start) * (self.total / self.size));
}
CodeMirror.on(document, "mousemove", move);
CodeMirror.on(document, "mouseup", done);
});
CodeMirror.on(this.node, "click", function(e) {
CodeMirror.e_preventDefault(e);
var innerBox = self.inner.getBoundingClientRect(), where;
if (self.orientation == "horizontal")
where = e.clientX < innerBox.left ? -1 : e.clientX > innerBox.right ? 1 : 0;
else
where = e.clientY < innerBox.top ? -1 : e.clientY > innerBox.bottom ? 1 : 0;
self.moveTo(self.pos + where * self.screen);
});
function onWheel(e) {
var moved = CodeMirror.wheelEventPixels(e)[self.orientation == "horizontal" ? "x" : "y"];
var oldPos = self.pos;
self.moveTo(self.pos + moved);
if (self.pos != oldPos) CodeMirror.e_preventDefault(e);
}
CodeMirror.on(this.node, "mousewheel", onWheel);
CodeMirror.on(this.node, "DOMMouseScroll", onWheel);
}
Bar.prototype.moveTo = function(pos, update) {
if (pos < 0) pos = 0;
if (pos > this.total - this.screen) pos = this.total - this.screen;
if (pos == this.pos) return;
this.pos = pos;
this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
(pos * (this.size / this.total)) + "px";
if (update !== false) this.scroll(pos, this.orientation);
};
Bar.prototype.update = function(scrollSize, clientSize, barSize) {
this.screen = clientSize;
this.total = scrollSize;
this.size = barSize;
// FIXME clip to min size?
this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
this.screen * (this.size / this.total) + "px";
this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
this.pos * (this.size / this.total) + "px";
};
function SimpleScrollbars(cls, place, scroll) {
this.addClass = cls;
this.horiz = new Bar(cls, "horizontal", scroll);
place(this.horiz.node);
this.vert = new Bar(cls, "vertical", scroll);
place(this.vert.node);
this.width = null;
}
SimpleScrollbars.prototype.update = function(measure) {
if (this.width == null) {
var style = window.getComputedStyle ? window.getComputedStyle(this.horiz.node) : this.horiz.node.currentStyle;
if (style) this.width = parseInt(style.height);
}
var width = this.width || 0;
var needsH = measure.scrollWidth > measure.clientWidth + 1;
var needsV = measure.scrollHeight > measure.clientHeight + 1;
this.vert.node.style.display = needsV ? "block" : "none";
this.horiz.node.style.display = needsH ? "block" : "none";
if (needsV) {
this.vert.update(measure.scrollHeight, measure.clientHeight,
measure.viewHeight - (needsH ? width : 0));
this.vert.node.style.display = "block";
this.vert.node.style.bottom = needsH ? width + "px" : "0";
}
if (needsH) {
this.horiz.update(measure.scrollWidth, measure.clientWidth,
measure.viewWidth - (needsV ? width : 0) - measure.barLeft);
this.horiz.node.style.right = needsV ? width + "px" : "0";
this.horiz.node.style.left = measure.barLeft + "px";
}
return {right: needsV ? width : 0, bottom: needsH ? width : 0};
};
SimpleScrollbars.prototype.setScrollTop = function(pos) {
this.vert.moveTo(pos, false);
};
SimpleScrollbars.prototype.setScrollLeft = function(pos) {
this.horiz.moveTo(pos, false);
};
SimpleScrollbars.prototype.clear = function() {
var parent = this.horiz.node.parentNode;
parent.removeChild(this.horiz.node);
parent.removeChild(this.vert.node);
};
CodeMirror.scrollbarModel.simple = function(place, scroll) {
return new SimpleScrollbars("CodeMirror-simplescroll", place, scroll);
};
CodeMirror.scrollbarModel.overlay = function(place, scroll) {
return new SimpleScrollbars("CodeMirror-overlayscroll", place, scroll);
};
});
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Highlighting text that matches the selection // Highlighting text that matches the selection
// //
// Defines an option highlightSelectionMatches, which, when enabled, // Defines an option highlightSelectionMatches, which, when enabled,
@@ -5,12 +8,15 @@
// document. // document.
// //
// The option can be set to true to simply enable it, or to a // The option can be set to true to simply enable it, or to a
// {minChars, style, showToken} object to explicitly configure it. // {minChars, style, wordsOnly, showToken, delay} object to explicitly
// minChars is the minimum amount of characters that should be // configure it. minChars is the minimum amount of characters that should be
// selected for the behavior to occur, and style is the token style to // selected for the behavior to occur, and style is the token style to
// apply to the matches. This will be prefixed by "cm-" to create an // apply to the matches. This will be prefixed by "cm-" to create an
// actual CSS class name. showToken, when enabled, will cause the // actual CSS class name. If wordsOnly is enabled, the matches will be
// current token to be highlighted when nothing is selected. // highlighted only if the selected text is a word. showToken, when enabled,
// will cause the current token to be highlighted when nothing is selected.
// delay is used to specify how much time to wait, in milliseconds, before
// highlighting the matches.
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
@@ -25,6 +31,7 @@
var DEFAULT_MIN_CHARS = 2; var DEFAULT_MIN_CHARS = 2;
var DEFAULT_TOKEN_STYLE = "matchhighlight"; var DEFAULT_TOKEN_STYLE = "matchhighlight";
var DEFAULT_DELAY = 100; var DEFAULT_DELAY = 100;
var DEFAULT_WORDS_ONLY = false;
function State(options) { function State(options) {
if (typeof options == "object") { if (typeof options == "object") {
@@ -32,10 +39,12 @@
this.style = options.style; this.style = options.style;
this.showToken = options.showToken; this.showToken = options.showToken;
this.delay = options.delay; this.delay = options.delay;
this.wordsOnly = options.wordsOnly;
} }
if (this.style == null) this.style = DEFAULT_TOKEN_STYLE; if (this.style == null) this.style = DEFAULT_TOKEN_STYLE;
if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS; if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS;
if (this.delay == null) this.delay = DEFAULT_DELAY; if (this.delay == null) this.delay = DEFAULT_DELAY;
if (this.wordsOnly == null) this.wordsOnly = DEFAULT_WORDS_ONLY;
this.overlay = this.timeout = null; this.overlay = this.timeout = null;
} }
@@ -76,13 +85,32 @@
cm.addOverlay(state.overlay = makeOverlay(line.slice(start, end), re, state.style)); cm.addOverlay(state.overlay = makeOverlay(line.slice(start, end), re, state.style));
return; return;
} }
if (cm.getCursor("head").line != cm.getCursor("anchor").line) return; var from = cm.getCursor("from"), to = cm.getCursor("to");
var selection = cm.getSelections()[0].replace(/^\s+|\s+$/g, ""); if (from.line != to.line) return;
if (state.wordsOnly && !isWord(cm, from, to)) return;
var selection = cm.getRange(from, to).replace(/^\s+|\s+$/g, "");
if (selection.length >= state.minChars) if (selection.length >= state.minChars)
cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style)); cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style));
}); });
} }
function isWord(cm, from, to) {
var str = cm.getRange(from, to);
if (str.match(/^\w+$/) !== null) {
if (from.ch > 0) {
var pos = {line: from.line, ch: from.ch - 1};
var chr = cm.getRange(pos, from);
if (chr.match(/\W/) === null) return false;
}
if (to.ch < cm.getLine(from.line).length) {
var pos = {line: to.line, ch: to.ch + 1};
var chr = cm.getRange(to, pos);
if (chr.match(/\W/) === null) return false;
}
return true;
} else return false;
}
function boundariesAround(stream, re) { function boundariesAround(stream, re) {
return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) && return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) &&
(stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos))); (stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos)));
@@ -0,0 +1,8 @@
.CodeMirror-search-match {
background: gold;
border-top: 1px solid orange;
border-bottom: 1px solid orange;
-moz-box-sizing: border-box;
box-sizing: border-box;
opacity: .5;
}
@@ -0,0 +1,90 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("./searchcursor"), require("../scroll/annotatescrollbar"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "./searchcursor", "../scroll/annotatescrollbar"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, className) {
return new SearchAnnotation(this, query, caseFold, className);
});
function SearchAnnotation(cm, query, caseFold, className) {
this.cm = cm;
this.annotation = cm.annotateScrollbar(className || "CodeMirror-search-match");
this.query = query;
this.caseFold = caseFold;
this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1};
this.matches = [];
this.update = null;
this.findMatches();
this.annotation.update(this.matches);
var self = this;
cm.on("change", this.changeHandler = function(_cm, change) { self.onChange(change); });
}
var MAX_MATCHES = 1000;
SearchAnnotation.prototype.findMatches = function() {
if (!this.gap) return;
for (var i = 0; i < this.matches.length; i++) {
var match = this.matches[i];
if (match.from.line >= this.gap.to) break;
if (match.to.line >= this.gap.from) this.matches.splice(i--, 1);
}
var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), this.caseFold);
while (cursor.findNext()) {
var match = {from: cursor.from(), to: cursor.to()};
if (match.from.line >= this.gap.to) break;
this.matches.splice(i++, 0, match);
if (this.matches.length > MAX_MATCHES) break;
}
this.gap = null;
};
function offsetLine(line, changeStart, sizeChange) {
if (line <= changeStart) return line;
return Math.max(changeStart, line + sizeChange);
}
SearchAnnotation.prototype.onChange = function(change) {
var startLine = change.from.line;
var endLine = CodeMirror.changeEnd(change).line;
var sizeChange = endLine - change.to.line;
if (this.gap) {
this.gap.from = Math.min(offsetLine(this.gap.from, startLine, sizeChange), change.from.line);
this.gap.to = Math.max(offsetLine(this.gap.to, startLine, sizeChange), change.from.line);
} else {
this.gap = {from: change.from.line, to: endLine + 1};
}
if (sizeChange) for (var i = 0; i < this.matches.length; i++) {
var match = this.matches[i];
var newFrom = offsetLine(match.from.line, startLine, sizeChange);
if (newFrom != match.from.line) match.from = CodeMirror.Pos(newFrom, match.from.ch);
var newTo = offsetLine(match.to.line, startLine, sizeChange);
if (newTo != match.to.line) match.to = CodeMirror.Pos(newTo, match.to.ch);
}
clearTimeout(this.update);
var self = this;
this.update = setTimeout(function() { self.updateAfterChange(); }, 250);
};
SearchAnnotation.prototype.updateAfterChange = function() {
this.findMatches();
this.annotation.update(this.matches);
};
SearchAnnotation.prototype.clear = function() {
this.cm.off("change", this.changeHandler);
this.annotation.clear();
};
});
+30 -21
View File
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Define search commands. Depends on dialog.js or another // Define search commands. Depends on dialog.js or another
// implementation of the openDialog method. // implementation of the openDialog method.
@@ -16,21 +19,21 @@
})(function(CodeMirror) { })(function(CodeMirror) {
"use strict"; "use strict";
function searchOverlay(query, caseInsensitive) { function searchOverlay(query, caseInsensitive) {
var startChar; if (typeof query == "string")
if (typeof query == "string") { query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
startChar = query.charAt(0); else if (!query.global)
query = new RegExp("^" + query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), query = new RegExp(query.source, query.ignoreCase ? "gi" : "g");
caseInsensitive ? "i" : "");
} else {
query = new RegExp("^(?:" + query.source + ")", query.ignoreCase ? "i" : "");
}
return {token: function(stream) { return {token: function(stream) {
if (stream.match(query)) return "searching"; query.lastIndex = stream.pos;
while (!stream.eol()) { var match = query.exec(stream.string);
stream.next(); if (match && match.index == stream.pos) {
if (startChar && !caseInsensitive) stream.pos += match[0].length;
stream.skipTo(startChar) || stream.skipToEnd(); return "searching";
if (stream.match(query, false)) break; } else if (match) {
stream.pos = match.index;
} else {
stream.skipToEnd();
} }
}}; }};
} }
@@ -60,15 +63,15 @@
function parseQuery(query) { function parseQuery(query) {
var isRE = query.match(/^\/(.*)\/([a-z]*)$/); var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
if (isRE) { if (isRE) {
query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
if (query.test("")) query = /x^/; catch(e) {} // Not a regular expression after all, do a string search
} else if (query == "") {
query = /x^/;
} }
if (typeof query == "string" ? query == "" : query.test(""))
query = /x^/;
return query; return query;
} }
var queryDialog = var queryDialog =
'Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>'; 'Search: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
function doSearch(cm, rev) { function doSearch(cm, rev) {
var state = getSearchState(cm); var state = getSearchState(cm);
if (state.query) return findNext(cm, rev); if (state.query) return findNext(cm, rev);
@@ -79,6 +82,10 @@
cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query)); cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query)); state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
cm.addOverlay(state.overlay); cm.addOverlay(state.overlay);
if (cm.showMatchesOnScrollbar) {
if (state.annotate) { state.annotate.clear(); state.annotate = null; }
state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
}
state.posFrom = state.posTo = cm.getCursor(); state.posFrom = state.posTo = cm.getCursor();
findNext(cm, rev); findNext(cm, rev);
}); });
@@ -100,13 +107,15 @@
if (!state.query) return; if (!state.query) return;
state.query = null; state.query = null;
cm.removeOverlay(state.overlay); cm.removeOverlay(state.overlay);
if (state.annotate) { state.annotate.clear(); state.annotate = null; }
});} });}
var replaceQueryDialog = var replaceQueryDialog =
'Replace: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>'; 'Replace: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
var replacementQueryDialog = 'With: <input type="text" style="width: 10em"/>'; var replacementQueryDialog = 'With: <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>"; var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
function replace(cm, all) { function replace(cm, all) {
if (cm.getOption("readOnly")) return;
dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) { dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) {
if (!query) return; if (!query) return;
query = parseQuery(query); query = parseQuery(query);
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -104,7 +107,7 @@
var from = Pos(pos.line, cut); var from = Pos(pos.line, cut);
for (var ln = pos.line + 1, i = 1; i < last; ++i, ++ln) for (var ln = pos.line + 1, i = 1; i < last; ++i, ++ln)
if (target[i] != fold(doc.getLine(ln))) return; if (target[i] != fold(doc.getLine(ln))) return;
if (doc.getLine(ln).slice(0, origTarget[last].length) != target[last]) return; if (fold(doc.getLine(ln).slice(0, origTarget[last].length)) != target[last]) return;
return {from: from, to: Pos(ln, origTarget[last].length)}; return {from: from, to: Pos(ln, origTarget[last].length)};
} }
}; };
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Because sometimes you need to style the cursor's line. // Because sometimes you need to style the cursor's line.
// //
// Adds an option 'styleActiveLine' which, when enabled, gives the // Adds an option 'styleActiveLine' which, when enabled, gives the
@@ -46,7 +49,9 @@
function updateActiveLines(cm, ranges) { function updateActiveLines(cm, ranges) {
var active = []; var active = [];
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
var line = cm.getLineHandleVisualStart(ranges[i].head.line); var range = ranges[i];
if (!range.empty()) continue;
var line = cm.getLineHandleVisualStart(range.head.line);
if (active[active.length - 1] != line) active.push(line); if (active[active.length - 1] != line) active.push(line);
} }
if (sameArray(cm.state.activeLines, active)) return; if (sameArray(cm.state.activeLines, active)) return;
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Because sometimes you need to mark the selected *text*. // Because sometimes you need to mark the selected *text*.
// //
// Adds an option 'styleSelectedText' which, when enabled, gives // Adds an option 'styleSelectedText' which, when enabled, gives
@@ -0,0 +1,95 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineOption("selectionPointer", false, function(cm, val) {
var data = cm.state.selectionPointer;
if (data) {
CodeMirror.off(cm.getWrapperElement(), "mousemove", data.mousemove);
CodeMirror.off(cm.getWrapperElement(), "mouseout", data.mouseout);
cm.off("cursorActivity", reset);
cm.off("scroll", reset);
cm.state.selectionPointer = null;
cm.display.lineDiv.style.cursor = "";
}
if (val) {
data = cm.state.selectionPointer = {
value: typeof val == "string" ? val : "default",
mousemove: function(event) { mousemove(cm, event); },
mouseout: function(event) { mouseout(cm, event); },
rects: null,
mouseX: null, mouseY: null,
willUpdate: false
};
CodeMirror.on(cm.getWrapperElement(), "mousemove", data.mousemove);
CodeMirror.on(cm.getWrapperElement(), "mouseout", data.mouseout);
cm.on("cursorActivity", reset);
cm.on("scroll", reset);
}
});
function mousemove(cm, event) {
var data = cm.state.selectionPointer;
if (event.buttons == null ? event.which : event.buttons) {
data.mouseX = data.mouseY = null;
} else {
data.mouseX = event.clientX;
data.mouseY = event.clientY;
}
scheduleUpdate(cm);
}
function mouseout(cm, event) {
if (!cm.getWrapperElement().contains(event.relatedTarget)) {
var data = cm.state.selectionPointer;
data.mouseX = data.mouseY = null;
scheduleUpdate(cm);
}
}
function reset(cm) {
cm.state.selectionPointer.rects = null;
scheduleUpdate(cm);
}
function scheduleUpdate(cm) {
if (!cm.state.selectionPointer.willUpdate) {
cm.state.selectionPointer.willUpdate = true;
setTimeout(function() {
update(cm);
cm.state.selectionPointer.willUpdate = false;
}, 50);
}
}
function update(cm) {
var data = cm.state.selectionPointer;
if (!data) return;
if (data.rects == null && data.mouseX != null) {
data.rects = [];
if (cm.somethingSelected()) {
for (var sel = cm.display.selectionDiv.firstChild; sel; sel = sel.nextSibling)
data.rects.push(sel.getBoundingClientRect());
}
}
var inside = false;
if (data.mouseX != null) for (var i = 0; i < data.rects.length; i++) {
var rect = data.rects[i];
if (rect.left <= data.mouseX && rect.right >= data.mouseX &&
rect.top <= data.mouseY && rect.bottom >= data.mouseY)
inside = true;
}
var cursor = inside ? data.value : "";
if (cm.display.lineDiv.style.cursor != cursor)
cm.display.lineDiv.style.cursor = cursor;
}
});
@@ -0,0 +1,86 @@
.CodeMirror-Tern-completion {
padding-left: 22px;
position: relative;
}
.CodeMirror-Tern-completion:before {
position: absolute;
left: 2px;
bottom: 2px;
border-radius: 50%;
font-size: 12px;
font-weight: bold;
height: 15px;
width: 15px;
line-height: 16px;
text-align: center;
color: white;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.CodeMirror-Tern-completion-unknown:before {
content: "?";
background: #4bb;
}
.CodeMirror-Tern-completion-object:before {
content: "O";
background: #77c;
}
.CodeMirror-Tern-completion-fn:before {
content: "F";
background: #7c7;
}
.CodeMirror-Tern-completion-array:before {
content: "A";
background: #c66;
}
.CodeMirror-Tern-completion-number:before {
content: "1";
background: #999;
}
.CodeMirror-Tern-completion-string:before {
content: "S";
background: #999;
}
.CodeMirror-Tern-completion-bool:before {
content: "B";
background: #999;
}
.CodeMirror-Tern-completion-guess {
color: #999;
}
.CodeMirror-Tern-tooltip {
border: 1px solid silver;
border-radius: 3px;
color: #444;
padding: 2px 5px;
font-size: 90%;
font-family: monospace;
background-color: white;
white-space: pre-wrap;
max-width: 40em;
position: absolute;
z-index: 10;
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
box-shadow: 2px 3px 5px rgba(0,0,0,.2);
transition: opacity 1s;
-moz-transition: opacity 1s;
-webkit-transition: opacity 1s;
-o-transition: opacity 1s;
-ms-transition: opacity 1s;
}
.CodeMirror-Tern-hint-doc {
max-width: 25em;
margin-top: -3px;
}
.CodeMirror-Tern-fname { color: black; }
.CodeMirror-Tern-farg { color: #70a; }
.CodeMirror-Tern-farg-current { text-decoration: underline; }
.CodeMirror-Tern-type { color: #07c; }
.CodeMirror-Tern-fhint-guess { opacity: .7; }
+670
View File
@@ -0,0 +1,670 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Glue code between CodeMirror and Tern.
//
// Create a CodeMirror.TernServer to wrap an actual Tern server,
// register open documents (CodeMirror.Doc instances) with it, and
// call its methods to activate the assisting functions that Tern
// provides.
//
// Options supported (all optional):
// * defs: An array of JSON definition data structures.
// * plugins: An object mapping plugin names to configuration
// options.
// * getFile: A function(name, c) that can be used to access files in
// the project that haven't been loaded yet. Simply do c(null) to
// indicate that a file is not available.
// * fileFilter: A function(value, docName, doc) that will be applied
// to documents before passing them on to Tern.
// * switchToDoc: A function(name, doc) that should, when providing a
// multi-file view, switch the view or focus to the named file.
// * showError: A function(editor, message) that can be used to
// override the way errors are displayed.
// * completionTip: Customize the content in tooltips for completions.
// Is passed a single argument—the completion's data as returned by
// Tern—and may return a string, DOM node, or null to indicate that
// no tip should be shown. By default the docstring is shown.
// * typeTip: Like completionTip, but for the tooltips shown for type
// queries.
// * responseFilter: A function(doc, query, request, error, data) that
// will be applied to the Tern responses before treating them
//
//
// It is possible to run the Tern server in a web worker by specifying
// these additional options:
// * useWorker: Set to true to enable web worker mode. You'll probably
// want to feature detect the actual value you use here, for example
// !!window.Worker.
// * workerScript: The main script of the worker. Point this to
// wherever you are hosting worker.js from this directory.
// * workerDeps: An array of paths pointing (relative to workerScript)
// to the Acorn and Tern libraries and any Tern plugins you want to
// load. Or, if you minified those into a single script and included
// them in the workerScript, simply leave this undefined.
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
// declare global: tern
CodeMirror.TernServer = function(options) {
var self = this;
this.options = options || {};
var plugins = this.options.plugins || (this.options.plugins = {});
if (!plugins.doc_comment) plugins.doc_comment = true;
if (this.options.useWorker) {
this.server = new WorkerServer(this);
} else {
this.server = new tern.Server({
getFile: function(name, c) { return getFile(self, name, c); },
async: true,
defs: this.options.defs || [],
plugins: plugins
});
}
this.docs = Object.create(null);
this.trackChange = function(doc, change) { trackChange(self, doc, change); };
this.cachedArgHints = null;
this.activeArgHints = null;
this.jumpStack = [];
this.getHint = function(cm, c) { return hint(self, cm, c); };
this.getHint.async = true;
};
CodeMirror.TernServer.prototype = {
addDoc: function(name, doc) {
var data = {doc: doc, name: name, changed: null};
this.server.addFile(name, docValue(this, data));
CodeMirror.on(doc, "change", this.trackChange);
return this.docs[name] = data;
},
delDoc: function(id) {
var found = resolveDoc(this, id);
if (!found) return;
CodeMirror.off(found.doc, "change", this.trackChange);
delete this.docs[found.name];
this.server.delFile(found.name);
},
hideDoc: function(id) {
closeArgHints(this);
var found = resolveDoc(this, id);
if (found && found.changed) sendDoc(this, found);
},
complete: function(cm) {
cm.showHint({hint: this.getHint});
},
showType: function(cm, pos, c) { showContextInfo(this, cm, pos, "type", c); },
showDocs: function(cm, pos, c) { showContextInfo(this, cm, pos, "documentation", c); },
updateArgHints: function(cm) { updateArgHints(this, cm); },
jumpToDef: function(cm) { jumpToDef(this, cm); },
jumpBack: function(cm) { jumpBack(this, cm); },
rename: function(cm) { rename(this, cm); },
selectName: function(cm) { selectName(this, cm); },
request: function (cm, query, c, pos) {
var self = this;
var doc = findDoc(this, cm.getDoc());
var request = buildRequest(this, doc, query, pos);
this.server.request(request, function (error, data) {
if (!error && self.options.responseFilter)
data = self.options.responseFilter(doc, query, request, error, data);
c(error, data);
});
}
};
var Pos = CodeMirror.Pos;
var cls = "CodeMirror-Tern-";
var bigDoc = 250;
function getFile(ts, name, c) {
var buf = ts.docs[name];
if (buf)
c(docValue(ts, buf));
else if (ts.options.getFile)
ts.options.getFile(name, c);
else
c(null);
}
function findDoc(ts, doc, name) {
for (var n in ts.docs) {
var cur = ts.docs[n];
if (cur.doc == doc) return cur;
}
if (!name) for (var i = 0;; ++i) {
n = "[doc" + (i || "") + "]";
if (!ts.docs[n]) { name = n; break; }
}
return ts.addDoc(name, doc);
}
function resolveDoc(ts, id) {
if (typeof id == "string") return ts.docs[id];
if (id instanceof CodeMirror) id = id.getDoc();
if (id instanceof CodeMirror.Doc) return findDoc(ts, id);
}
function trackChange(ts, doc, change) {
var data = findDoc(ts, doc);
var argHints = ts.cachedArgHints;
if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) <= 0)
ts.cachedArgHints = null;
var changed = data.changed;
if (changed == null)
data.changed = changed = {from: change.from.line, to: change.from.line};
var end = change.from.line + (change.text.length - 1);
if (change.from.line < changed.to) changed.to = changed.to - (change.to.line - end);
if (end >= changed.to) changed.to = end + 1;
if (changed.from > change.from.line) changed.from = change.from.line;
if (doc.lineCount() > bigDoc && change.to - changed.from > 100) setTimeout(function() {
if (data.changed && data.changed.to - data.changed.from > 100) sendDoc(ts, data);
}, 200);
}
function sendDoc(ts, doc) {
ts.server.request({files: [{type: "full", name: doc.name, text: docValue(ts, doc)}]}, function(error) {
if (error) window.console.error(error);
else doc.changed = null;
});
}
// Completion
function hint(ts, cm, c) {
ts.request(cm, {type: "completions", types: true, docs: true, urls: true}, function(error, data) {
if (error) return showError(ts, cm, error);
var completions = [], after = "";
var from = data.start, to = data.end;
if (cm.getRange(Pos(from.line, from.ch - 2), from) == "[\"" &&
cm.getRange(to, Pos(to.line, to.ch + 2)) != "\"]")
after = "\"]";
for (var i = 0; i < data.completions.length; ++i) {
var completion = data.completions[i], className = typeToIcon(completion.type);
if (data.guess) className += " " + cls + "guess";
completions.push({text: completion.name + after,
displayText: completion.name,
className: className,
data: completion});
}
var obj = {from: from, to: to, list: completions};
var tooltip = null;
CodeMirror.on(obj, "close", function() { remove(tooltip); });
CodeMirror.on(obj, "update", function() { remove(tooltip); });
CodeMirror.on(obj, "select", function(cur, node) {
remove(tooltip);
var content = ts.options.completionTip ? ts.options.completionTip(cur.data) : cur.data.doc;
if (content) {
tooltip = makeTooltip(node.parentNode.getBoundingClientRect().right + window.pageXOffset,
node.getBoundingClientRect().top + window.pageYOffset, content);
tooltip.className += " " + cls + "hint-doc";
}
});
c(obj);
});
}
function typeToIcon(type) {
var suffix;
if (type == "?") suffix = "unknown";
else if (type == "number" || type == "string" || type == "bool") suffix = type;
else if (/^fn\(/.test(type)) suffix = "fn";
else if (/^\[/.test(type)) suffix = "array";
else suffix = "object";
return cls + "completion " + cls + "completion-" + suffix;
}
// Type queries
function showContextInfo(ts, cm, pos, queryName, c) {
ts.request(cm, queryName, function(error, data) {
if (error) return showError(ts, cm, error);
if (ts.options.typeTip) {
var tip = ts.options.typeTip(data);
} else {
var tip = elt("span", null, elt("strong", null, data.type || "not found"));
if (data.doc)
tip.appendChild(document.createTextNode(" — " + data.doc));
if (data.url) {
tip.appendChild(document.createTextNode(" "));
tip.appendChild(elt("a", null, "[docs]")).href = data.url;
}
}
tempTooltip(cm, tip);
if (c) c();
}, pos);
}
// Maintaining argument hints
function updateArgHints(ts, cm) {
closeArgHints(ts);
if (cm.somethingSelected()) return;
var state = cm.getTokenAt(cm.getCursor()).state;
var inner = CodeMirror.innerMode(cm.getMode(), state);
if (inner.mode.name != "javascript") return;
var lex = inner.state.lexical;
if (lex.info != "call") return;
var ch, argPos = lex.pos || 0, tabSize = cm.getOption("tabSize");
for (var line = cm.getCursor().line, e = Math.max(0, line - 9), found = false; line >= e; --line) {
var str = cm.getLine(line), extra = 0;
for (var pos = 0;;) {
var tab = str.indexOf("\t", pos);
if (tab == -1) break;
extra += tabSize - (tab + extra) % tabSize - 1;
pos = tab + 1;
}
ch = lex.column - extra;
if (str.charAt(ch) == "(") {found = true; break;}
}
if (!found) return;
var start = Pos(line, ch);
var cache = ts.cachedArgHints;
if (cache && cache.doc == cm.getDoc() && cmpPos(start, cache.start) == 0)
return showArgHints(ts, cm, argPos);
ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) {
if (error || !data.type || !(/^fn\(/).test(data.type)) return;
ts.cachedArgHints = {
start: pos,
type: parseFnType(data.type),
name: data.exprName || data.name || "fn",
guess: data.guess,
doc: cm.getDoc()
};
showArgHints(ts, cm, argPos);
});
}
function showArgHints(ts, cm, pos) {
closeArgHints(ts);
var cache = ts.cachedArgHints, tp = cache.type;
var tip = elt("span", cache.guess ? cls + "fhint-guess" : null,
elt("span", cls + "fname", cache.name), "(");
for (var i = 0; i < tp.args.length; ++i) {
if (i) tip.appendChild(document.createTextNode(", "));
var arg = tp.args[i];
tip.appendChild(elt("span", cls + "farg" + (i == pos ? " " + cls + "farg-current" : ""), arg.name || "?"));
if (arg.type != "?") {
tip.appendChild(document.createTextNode(":\u00a0"));
tip.appendChild(elt("span", cls + "type", arg.type));
}
}
tip.appendChild(document.createTextNode(tp.rettype ? ") ->\u00a0" : ")"));
if (tp.rettype) tip.appendChild(elt("span", cls + "type", tp.rettype));
var place = cm.cursorCoords(null, "page");
ts.activeArgHints = makeTooltip(place.right + 1, place.bottom, tip);
}
function parseFnType(text) {
var args = [], pos = 3;
function skipMatching(upto) {
var depth = 0, start = pos;
for (;;) {
var next = text.charAt(pos);
if (upto.test(next) && !depth) return text.slice(start, pos);
if (/[{\[\(]/.test(next)) ++depth;
else if (/[}\]\)]/.test(next)) --depth;
++pos;
}
}
// Parse arguments
if (text.charAt(pos) != ")") for (;;) {
var name = text.slice(pos).match(/^([^, \(\[\{]+): /);
if (name) {
pos += name[0].length;
name = name[1];
}
args.push({name: name, type: skipMatching(/[\),]/)});
if (text.charAt(pos) == ")") break;
pos += 2;
}
var rettype = text.slice(pos).match(/^\) -> (.*)$/);
return {args: args, rettype: rettype && rettype[1]};
}
// Moving to the definition of something
function jumpToDef(ts, cm) {
function inner(varName) {
var req = {type: "definition", variable: varName || null};
var doc = findDoc(ts, cm.getDoc());
ts.server.request(buildRequest(ts, doc, req), function(error, data) {
if (error) return showError(ts, cm, error);
if (!data.file && data.url) { window.open(data.url); return; }
if (data.file) {
var localDoc = ts.docs[data.file], found;
if (localDoc && (found = findContext(localDoc.doc, data))) {
ts.jumpStack.push({file: doc.name,
start: cm.getCursor("from"),
end: cm.getCursor("to")});
moveTo(ts, doc, localDoc, found.start, found.end);
return;
}
}
showError(ts, cm, "Could not find a definition.");
});
}
if (!atInterestingExpression(cm))
dialog(cm, "Jump to variable", function(name) { if (name) inner(name); });
else
inner();
}
function jumpBack(ts, cm) {
var pos = ts.jumpStack.pop(), doc = pos && ts.docs[pos.file];
if (!doc) return;
moveTo(ts, findDoc(ts, cm.getDoc()), doc, pos.start, pos.end);
}
function moveTo(ts, curDoc, doc, start, end) {
doc.doc.setSelection(start, end);
if (curDoc != doc && ts.options.switchToDoc) {
closeArgHints(ts);
ts.options.switchToDoc(doc.name, doc.doc);
}
}
// The {line,ch} representation of positions makes this rather awkward.
function findContext(doc, data) {
var before = data.context.slice(0, data.contextOffset).split("\n");
var startLine = data.start.line - (before.length - 1);
var start = Pos(startLine, (before.length == 1 ? data.start.ch : doc.getLine(startLine).length) - before[0].length);
var text = doc.getLine(startLine).slice(start.ch);
for (var cur = startLine + 1; cur < doc.lineCount() && text.length < data.context.length; ++cur)
text += "\n" + doc.getLine(cur);
if (text.slice(0, data.context.length) == data.context) return data;
var cursor = doc.getSearchCursor(data.context, 0, false);
var nearest, nearestDist = Infinity;
while (cursor.findNext()) {
var from = cursor.from(), dist = Math.abs(from.line - start.line) * 10000;
if (!dist) dist = Math.abs(from.ch - start.ch);
if (dist < nearestDist) { nearest = from; nearestDist = dist; }
}
if (!nearest) return null;
if (before.length == 1)
nearest.ch += before[0].length;
else
nearest = Pos(nearest.line + (before.length - 1), before[before.length - 1].length);
if (data.start.line == data.end.line)
var end = Pos(nearest.line, nearest.ch + (data.end.ch - data.start.ch));
else
var end = Pos(nearest.line + (data.end.line - data.start.line), data.end.ch);
return {start: nearest, end: end};
}
function atInterestingExpression(cm) {
var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos);
if (tok.start < pos.ch && (tok.type == "comment" || tok.type == "string")) return false;
return /\w/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
}
// Variable renaming
function rename(ts, cm) {
var token = cm.getTokenAt(cm.getCursor());
if (!/\w/.test(token.string)) return showError(ts, cm, "Not at a variable");
dialog(cm, "New name for " + token.string, function(newName) {
ts.request(cm, {type: "rename", newName: newName, fullDocs: true}, function(error, data) {
if (error) return showError(ts, cm, error);
applyChanges(ts, data.changes);
});
});
}
function selectName(ts, cm) {
var name = findDoc(ts, cm.doc).name;
ts.request(cm, {type: "refs"}, function(error, data) {
if (error) return showError(ts, cm, error);
var ranges = [], cur = 0;
for (var i = 0; i < data.refs.length; i++) {
var ref = data.refs[i];
if (ref.file == name) {
ranges.push({anchor: ref.start, head: ref.end});
if (cmpPos(cur, ref.start) >= 0 && cmpPos(cur, ref.end) <= 0)
cur = ranges.length - 1;
}
}
cm.setSelections(ranges, cur);
});
}
var nextChangeOrig = 0;
function applyChanges(ts, changes) {
var perFile = Object.create(null);
for (var i = 0; i < changes.length; ++i) {
var ch = changes[i];
(perFile[ch.file] || (perFile[ch.file] = [])).push(ch);
}
for (var file in perFile) {
var known = ts.docs[file], chs = perFile[file];;
if (!known) continue;
chs.sort(function(a, b) { return cmpPos(b.start, a.start); });
var origin = "*rename" + (++nextChangeOrig);
for (var i = 0; i < chs.length; ++i) {
var ch = chs[i];
known.doc.replaceRange(ch.text, ch.start, ch.end, origin);
}
}
}
// Generic request-building helper
function buildRequest(ts, doc, query, pos) {
var files = [], offsetLines = 0, allowFragments = !query.fullDocs;
if (!allowFragments) delete query.fullDocs;
if (typeof query == "string") query = {type: query};
query.lineCharPositions = true;
if (query.end == null) {
query.end = pos || doc.doc.getCursor("end");
if (doc.doc.somethingSelected())
query.start = doc.doc.getCursor("start");
}
var startPos = query.start || query.end;
if (doc.changed) {
if (doc.doc.lineCount() > bigDoc && allowFragments !== false &&
doc.changed.to - doc.changed.from < 100 &&
doc.changed.from <= startPos.line && doc.changed.to > query.end.line) {
files.push(getFragmentAround(doc, startPos, query.end));
query.file = "#0";
var offsetLines = files[0].offsetLines;
if (query.start != null) query.start = Pos(query.start.line - -offsetLines, query.start.ch);
query.end = Pos(query.end.line - offsetLines, query.end.ch);
} else {
files.push({type: "full",
name: doc.name,
text: docValue(ts, doc)});
query.file = doc.name;
doc.changed = null;
}
} else {
query.file = doc.name;
}
for (var name in ts.docs) {
var cur = ts.docs[name];
if (cur.changed && cur != doc) {
files.push({type: "full", name: cur.name, text: docValue(ts, cur)});
cur.changed = null;
}
}
return {query: query, files: files};
}
function getFragmentAround(data, start, end) {
var doc = data.doc;
var minIndent = null, minLine = null, endLine, tabSize = 4;
for (var p = start.line - 1, min = Math.max(0, p - 50); p >= min; --p) {
var line = doc.getLine(p), fn = line.search(/\bfunction\b/);
if (fn < 0) continue;
var indent = CodeMirror.countColumn(line, null, tabSize);
if (minIndent != null && minIndent <= indent) continue;
minIndent = indent;
minLine = p;
}
if (minLine == null) minLine = min;
var max = Math.min(doc.lastLine(), end.line + 20);
if (minIndent == null || minIndent == CodeMirror.countColumn(doc.getLine(start.line), null, tabSize))
endLine = max;
else for (endLine = end.line + 1; endLine < max; ++endLine) {
var indent = CodeMirror.countColumn(doc.getLine(endLine), null, tabSize);
if (indent <= minIndent) break;
}
var from = Pos(minLine, 0);
return {type: "part",
name: data.name,
offsetLines: from.line,
text: doc.getRange(from, Pos(endLine, 0))};
}
// Generic utilities
var cmpPos = CodeMirror.cmpPos;
function elt(tagname, cls /*, ... elts*/) {
var e = document.createElement(tagname);
if (cls) e.className = cls;
for (var i = 2; i < arguments.length; ++i) {
var elt = arguments[i];
if (typeof elt == "string") elt = document.createTextNode(elt);
e.appendChild(elt);
}
return e;
}
function dialog(cm, text, f) {
if (cm.openDialog)
cm.openDialog(text + ": <input type=text>", f);
else
f(prompt(text, ""));
}
// Tooltips
function tempTooltip(cm, content) {
var where = cm.cursorCoords();
var tip = makeTooltip(where.right + 1, where.bottom, content);
function clear() {
if (!tip.parentNode) return;
cm.off("cursorActivity", clear);
fadeOut(tip);
}
setTimeout(clear, 1700);
cm.on("cursorActivity", clear);
}
function makeTooltip(x, y, content) {
var node = elt("div", cls + "tooltip", content);
node.style.left = x + "px";
node.style.top = y + "px";
document.body.appendChild(node);
return node;
}
function remove(node) {
var p = node && node.parentNode;
if (p) p.removeChild(node);
}
function fadeOut(tooltip) {
tooltip.style.opacity = "0";
setTimeout(function() { remove(tooltip); }, 1100);
}
function showError(ts, cm, msg) {
if (ts.options.showError)
ts.options.showError(cm, msg);
else
tempTooltip(cm, String(msg));
}
function closeArgHints(ts) {
if (ts.activeArgHints) { remove(ts.activeArgHints); ts.activeArgHints = null; }
}
function docValue(ts, doc) {
var val = doc.doc.getValue();
if (ts.options.fileFilter) val = ts.options.fileFilter(val, doc.name, doc.doc);
return val;
}
// Worker wrapper
function WorkerServer(ts) {
var worker = new Worker(ts.options.workerScript);
worker.postMessage({type: "init",
defs: ts.options.defs,
plugins: ts.options.plugins,
scripts: ts.options.workerDeps});
var msgId = 0, pending = {};
function send(data, c) {
if (c) {
data.id = ++msgId;
pending[msgId] = c;
}
worker.postMessage(data);
}
worker.onmessage = function(e) {
var data = e.data;
if (data.type == "getFile") {
getFile(ts, data.name, function(err, text) {
send({type: "getFile", err: String(err), text: text, id: data.id});
});
} else if (data.type == "debug") {
window.console.log(data.message);
} else if (data.id && pending[data.id]) {
pending[data.id](data.err, data.body);
delete pending[data.id];
}
};
worker.onerror = function(e) {
for (var id in pending) pending[id](e);
pending = {};
};
this.addFile = function(name, text) { send({type: "add", name: name, text: text}); };
this.delFile = function(name) { send({type: "del", name: name}); };
this.request = function(body, c) { send({type: "req", body: body}, c); };
}
});
@@ -0,0 +1,44 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// declare global: tern, server
var server;
this.onmessage = function(e) {
var data = e.data;
switch (data.type) {
case "init": return startServer(data.defs, data.plugins, data.scripts);
case "add": return server.addFile(data.name, data.text);
case "del": return server.delFile(data.name);
case "req": return server.request(data.body, function(err, reqData) {
postMessage({id: data.id, body: reqData, err: err && String(err)});
});
case "getFile":
var c = pending[data.id];
delete pending[data.id];
return c(data.err, data.text);
default: throw new Error("Unknown message type: " + data.type);
}
};
var nextId = 0, pending = {};
function getFile(file, c) {
postMessage({type: "getFile", name: file, id: ++nextId});
pending[nextId] = c;
}
function startServer(defs, plugins, scripts) {
if (scripts) importScripts.apply(null, scripts);
server = new tern.Server({
getFile: getFile,
async: true,
defs: defs,
plugins: plugins
});
}
var console = {
log: function(v) { postMessage({type: "debug", message: v}); }
};
@@ -0,0 +1,139 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var Pos = CodeMirror.Pos;
function findParagraph(cm, pos, options) {
var startRE = options.paragraphStart || cm.getHelper(pos, "paragraphStart");
for (var start = pos.line, first = cm.firstLine(); start > first; --start) {
var line = cm.getLine(start);
if (startRE && startRE.test(line)) break;
if (!/\S/.test(line)) { ++start; break; }
}
var endRE = options.paragraphEnd || cm.getHelper(pos, "paragraphEnd");
for (var end = pos.line + 1, last = cm.lastLine(); end <= last; ++end) {
var line = cm.getLine(end);
if (endRE && endRE.test(line)) { ++end; break; }
if (!/\S/.test(line)) break;
}
return {from: start, to: end};
}
function findBreakPoint(text, column, wrapOn, killTrailingSpace) {
for (var at = column; at > 0; --at)
if (wrapOn.test(text.slice(at - 1, at + 1))) break;
if (at == 0) at = column;
var endOfText = at;
if (killTrailingSpace)
while (text.charAt(endOfText - 1) == " ") --endOfText;
return {from: endOfText, to: at};
}
function wrapRange(cm, from, to, options) {
from = cm.clipPos(from); to = cm.clipPos(to);
var column = options.column || 80;
var wrapOn = options.wrapOn || /\s\S|-[^\.\d]/;
var killTrailing = options.killTrailingSpace !== false;
var changes = [], curLine = "", curNo = from.line;
var lines = cm.getRange(from, to, false);
if (!lines.length) return null;
var leadingSpace = lines[0].match(/^[ \t]*/)[0];
for (var i = 0; i < lines.length; ++i) {
var text = lines[i], oldLen = curLine.length, spaceInserted = 0;
if (curLine && text && !wrapOn.test(curLine.charAt(curLine.length - 1) + text.charAt(0))) {
curLine += " ";
spaceInserted = 1;
}
var spaceTrimmed = "";
if (i) {
spaceTrimmed = text.match(/^\s*/)[0];
text = text.slice(spaceTrimmed.length);
}
curLine += text;
if (i) {
var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed &&
findBreakPoint(curLine, column, wrapOn, killTrailing);
// If this isn't broken, or is broken at a different point, remove old break
if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) {
changes.push({text: [spaceInserted ? " " : ""],
from: Pos(curNo, oldLen),
to: Pos(curNo + 1, spaceTrimmed.length)});
} else {
curLine = leadingSpace + text;
++curNo;
}
}
while (curLine.length > column) {
var bp = findBreakPoint(curLine, column, wrapOn, killTrailing);
changes.push({text: ["", leadingSpace],
from: Pos(curNo, bp.from),
to: Pos(curNo, bp.to)});
curLine = leadingSpace + curLine.slice(bp.to);
++curNo;
}
}
if (changes.length) cm.operation(function() {
for (var i = 0; i < changes.length; ++i) {
var change = changes[i];
cm.replaceRange(change.text, change.from, change.to);
}
});
return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null;
}
CodeMirror.defineExtension("wrapParagraph", function(pos, options) {
options = options || {};
if (!pos) pos = this.getCursor();
var para = findParagraph(this, pos, options);
return wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options);
});
CodeMirror.commands.wrapLines = function(cm) {
cm.operation(function() {
var ranges = cm.listSelections(), at = cm.lastLine() + 1;
for (var i = ranges.length - 1; i >= 0; i--) {
var range = ranges[i], span;
if (range.empty()) {
var para = findParagraph(cm, range.head, {});
span = {from: Pos(para.from, 0), to: Pos(para.to - 1)};
} else {
span = {from: range.from(), to: range.to()};
}
if (span.to.line >= at) continue;
at = span.from.line;
wrapRange(cm, span.from, span.to, {});
}
});
};
CodeMirror.defineExtension("wrapRange", function(from, to, options) {
return wrapRange(this, from, to, options || {});
});
CodeMirror.defineExtension("wrapParagraphsInRange", function(from, to, options) {
options = options || {};
var cm = this, paras = [];
for (var line = from.line; line <= to.line;) {
var para = findParagraph(cm, Pos(line, 0), options);
paras.push(para);
line = para.to;
}
var madeChange = false;
if (paras.length) cm.operation(function() {
for (var i = paras.length - 1; i >= 0; --i)
madeChange = madeChange || wrapRange(cm, Pos(paras[i].from, 0), Pos(paras[i].to - 1), options);
});
return madeChange;
});
});
+1 -14
View File
@@ -1,16 +1,3 @@
#!/usr/bin/env node #!/usr/bin/env node
var lint = require("../test/lint/lint"), process.exit(require("../test/lint").ok ? 0 : 1);
path = require("path");
if (process.argv.length > 2) {
lint.checkDir(process.argv[2]);
} else {
process.chdir(path.resolve(__dirname, ".."));
lint.checkDir("lib");
lint.checkDir("mode");
lint.checkDir("addon");
lint.checkDir("keymap");
}
process.exit(lint.success() ? 0 : 1);
+49 -42
View File
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../lib/codemirror")); mod(require("../lib/codemirror"));
@@ -129,8 +132,8 @@
}; };
} }
function findEnd(cm, by, dir) { function findEnd(cm, pos, by, dir) {
var pos = cm.getCursor(), prefix = getPrefix(cm); var prefix = getPrefix(cm);
if (prefix < 0) { dir = -dir; prefix = -prefix; } if (prefix < 0) { dir = -dir; prefix = -prefix; }
for (var i = 0; i < prefix; ++i) { for (var i = 0; i < prefix; ++i) {
var newPos = by(cm, pos, dir); var newPos = by(cm, pos, dir);
@@ -142,14 +145,31 @@
function move(by, dir) { function move(by, dir) {
var f = function(cm) { var f = function(cm) {
cm.extendSelection(findEnd(cm, by, dir)); cm.extendSelection(findEnd(cm, cm.getCursor(), by, dir));
}; };
f.motion = true; f.motion = true;
return f; return f;
} }
function killTo(cm, by, dir) { function killTo(cm, by, dir) {
kill(cm, cm.getCursor(), findEnd(cm, by, dir), true); var selections = cm.listSelections(), cursor;
var i = selections.length;
while (i--) {
cursor = selections[i].head;
kill(cm, cursor, findEnd(cm, cursor, by, dir), true);
}
}
function killRegion(cm) {
if (cm.somethingSelected()) {
var selections = cm.listSelections(), selection;
var i = selections.length;
while (i--) {
selection = selections[i];
kill(cm, selection.anchor, selection.head);
}
return true;
}
} }
function addPrefix(cm, digit) { function addPrefix(cm, digit) {
@@ -253,7 +273,7 @@
// Actual keymap // Actual keymap
var keyMap = CodeMirror.keyMap.emacs = { var keyMap = CodeMirror.keyMap.emacs = CodeMirror.normalizeKeyMap({
"Ctrl-W": function(cm) {kill(cm, cm.getCursor("start"), cm.getCursor("end"));}, "Ctrl-W": function(cm) {kill(cm, cm.getCursor("start"), cm.getCursor("end"));},
"Ctrl-K": repeated(function(cm) { "Ctrl-K": repeated(function(cm) {
var start = cm.getCursor(), end = cm.clipPos(Pos(start.line)); var start = cm.getCursor(), end = cm.clipPos(Pos(start.line));
@@ -280,9 +300,9 @@
"Ctrl-F": move(byChar, 1), "Ctrl-B": move(byChar, -1), "Ctrl-F": move(byChar, 1), "Ctrl-B": move(byChar, -1),
"Right": move(byChar, 1), "Left": move(byChar, -1), "Right": move(byChar, 1), "Left": move(byChar, -1),
"Ctrl-D": function(cm) { killTo(cm, byChar, 1); }, "Ctrl-D": function(cm) { killTo(cm, byChar, 1); },
"Delete": function(cm) { killTo(cm, byChar, 1); }, "Delete": function(cm) { killRegion(cm) || killTo(cm, byChar, 1); },
"Ctrl-H": function(cm) { killTo(cm, byChar, -1); }, "Ctrl-H": function(cm) { killTo(cm, byChar, -1); },
"Backspace": function(cm) { killTo(cm, byChar, -1); }, "Backspace": function(cm) { killRegion(cm) || killTo(cm, byChar, -1); },
"Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1), "Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1),
"Alt-D": function(cm) { killTo(cm, byWord, 1); }, "Alt-D": function(cm) { killTo(cm, byWord, 1); },
@@ -306,7 +326,8 @@
"Ctrl-Alt-F": move(byExpr, 1), "Ctrl-Alt-B": move(byExpr, -1), "Ctrl-Alt-F": move(byExpr, 1), "Ctrl-Alt-B": move(byExpr, -1),
"Shift-Ctrl-Alt-2": function(cm) { "Shift-Ctrl-Alt-2": function(cm) {
cm.setSelection(findEnd(cm, byExpr, 1), cm.getCursor()); var cursor = cm.getCursor();
cm.setSelection(findEnd(cm, cursor, byExpr, 1), cursor);
}, },
"Ctrl-Alt-T": function(cm) { "Ctrl-Alt-T": function(cm) {
var leftStart = byExpr(cm, cm.getCursor(), -1), leftEnd = byExpr(cm, leftStart, 1); var leftStart = byExpr(cm, cm.getCursor(), -1), leftEnd = byExpr(cm, leftStart, 1);
@@ -324,13 +345,7 @@
}, },
"Ctrl-O": repeated(function(cm) { cm.replaceSelection("\n", "start"); }), "Ctrl-O": repeated(function(cm) { cm.replaceSelection("\n", "start"); }),
"Ctrl-T": repeated(function(cm) { "Ctrl-T": repeated(function(cm) {
var pos = cm.getCursor(); cm.execCommand("transposeChars");
if (pos.ch < cm.getLine(pos.line).length) pos = Pos(pos.line, pos.ch + 1);
var from = cm.findPosH(pos, -2, "char");
var range = cm.getRange(from, pos);
if (range.length != 2) return;
cm.setSelection(from, pos);
cm.replaceSelection(range.charAt(1) + range.charAt(0), null, "+transpose");
}), }),
"Alt-C": repeated(function(cm) { "Alt-C": repeated(function(cm) {
@@ -356,27 +371,7 @@
"Alt-/": "autocomplete", "Alt-/": "autocomplete",
"Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto", "Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto",
"Alt-G": function(cm) {cm.setOption("keyMap", "emacs-Alt-G");}, "Alt-G G": function(cm) {
"Ctrl-X": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-X");},
"Ctrl-Q": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-Q");},
"Ctrl-U": addPrefixMap
};
CodeMirror.keyMap["emacs-Ctrl-X"] = {
"Tab": function(cm) {
cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit"));
},
"Ctrl-X": function(cm) {
cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor"));
},
"Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": repeated("undo"), "K": "close",
"Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); },
auto: "emacs", nofallthrough: true, disableInput: true
};
CodeMirror.keyMap["emacs-Alt-G"] = {
"G": function(cm) {
var prefix = getPrefix(cm, true); var prefix = getPrefix(cm, true);
if (prefix != null && prefix > 0) return cm.setCursor(prefix - 1); if (prefix != null && prefix > 0) return cm.setCursor(prefix - 1);
@@ -386,13 +381,25 @@
cm.setCursor(num - 1); cm.setCursor(num - 1);
}); });
}, },
auto: "emacs", nofallthrough: true, disableInput: true
};
CodeMirror.keyMap["emacs-Ctrl-Q"] = { "Ctrl-X Tab": function(cm) {
"Tab": repeated("insertTab"), cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit"));
auto: "emacs", nofallthrough: true },
}; "Ctrl-X Ctrl-X": function(cm) {
cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor"));
},
"Ctrl-X Ctrl-S": "save",
"Ctrl-X Ctrl-W": "save",
"Ctrl-X S": "saveAll",
"Ctrl-X F": "open",
"Ctrl-X U": repeated("undo"),
"Ctrl-X K": "close",
"Ctrl-X Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); },
"Ctrl-X H": "selectAll",
"Ctrl-Q Tab": repeated("insertTab"),
"Ctrl-U": addPrefixMap
});
var prefixMap = {"Ctrl-G": clearPrefix}; var prefixMap = {"Ctrl-G": clearPrefix};
function regPrefix(d) { function regPrefix(d) {
+540
View File
@@ -0,0 +1,540 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// A rough approximation of Sublime Text's keybindings
// Depends on addon/search/searchcursor.js and optionally addon/dialog/dialogs.js
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../lib/codemirror"), require("../addon/search/searchcursor"), require("../addon/edit/matchbrackets"));
else if (typeof define == "function" && define.amd) // AMD
define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/edit/matchbrackets"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var map = CodeMirror.keyMap.sublime = {fallthrough: "default"};
var cmds = CodeMirror.commands;
var Pos = CodeMirror.Pos;
var mac = CodeMirror.keyMap["default"] == CodeMirror.keyMap.macDefault;
var ctrl = mac ? "Cmd-" : "Ctrl-";
// This is not exactly Sublime's algorithm. I couldn't make heads or tails of that.
function findPosSubword(doc, start, dir) {
if (dir < 0 && start.ch == 0) return doc.clipPos(Pos(start.line - 1));
var line = doc.getLine(start.line);
if (dir > 0 && start.ch >= line.length) return doc.clipPos(Pos(start.line + 1, 0));
var state = "start", type;
for (var pos = start.ch, e = dir < 0 ? 0 : line.length, i = 0; pos != e; pos += dir, i++) {
var next = line.charAt(dir < 0 ? pos - 1 : pos);
var cat = next != "_" && CodeMirror.isWordChar(next) ? "w" : "o";
if (cat == "w" && next.toUpperCase() == next) cat = "W";
if (state == "start") {
if (cat != "o") { state = "in"; type = cat; }
} else if (state == "in") {
if (type != cat) {
if (type == "w" && cat == "W" && dir < 0) pos--;
if (type == "W" && cat == "w" && dir > 0) { type = "w"; continue; }
break;
}
}
}
return Pos(start.line, pos);
}
function moveSubword(cm, dir) {
cm.extendSelectionsBy(function(range) {
if (cm.display.shift || cm.doc.extend || range.empty())
return findPosSubword(cm.doc, range.head, dir);
else
return dir < 0 ? range.from() : range.to();
});
}
cmds[map["Alt-Left"] = "goSubwordLeft"] = function(cm) { moveSubword(cm, -1); };
cmds[map["Alt-Right"] = "goSubwordRight"] = function(cm) { moveSubword(cm, 1); };
cmds[map[ctrl + "Up"] = "scrollLineUp"] = function(cm) {
var info = cm.getScrollInfo();
if (!cm.somethingSelected()) {
var visibleBottomLine = cm.lineAtHeight(info.top + info.clientHeight, "local");
if (cm.getCursor().line >= visibleBottomLine)
cm.execCommand("goLineUp");
}
cm.scrollTo(null, info.top - cm.defaultTextHeight());
};
cmds[map[ctrl + "Down"] = "scrollLineDown"] = function(cm) {
var info = cm.getScrollInfo();
if (!cm.somethingSelected()) {
var visibleTopLine = cm.lineAtHeight(info.top, "local")+1;
if (cm.getCursor().line <= visibleTopLine)
cm.execCommand("goLineDown");
}
cm.scrollTo(null, info.top + cm.defaultTextHeight());
};
cmds[map["Shift-" + ctrl + "L"] = "splitSelectionByLine"] = function(cm) {
var ranges = cm.listSelections(), lineRanges = [];
for (var i = 0; i < ranges.length; i++) {
var from = ranges[i].from(), to = ranges[i].to();
for (var line = from.line; line <= to.line; ++line)
if (!(to.line > from.line && line == to.line && to.ch == 0))
lineRanges.push({anchor: line == from.line ? from : Pos(line, 0),
head: line == to.line ? to : Pos(line)});
}
cm.setSelections(lineRanges, 0);
};
map["Shift-Tab"] = "indentLess";
cmds[map["Esc"] = "singleSelectionTop"] = function(cm) {
var range = cm.listSelections()[0];
cm.setSelection(range.anchor, range.head, {scroll: false});
};
cmds[map[ctrl + "L"] = "selectLine"] = function(cm) {
var ranges = cm.listSelections(), extended = [];
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i];
extended.push({anchor: Pos(range.from().line, 0),
head: Pos(range.to().line + 1, 0)});
}
cm.setSelections(extended);
};
map["Shift-" + ctrl + "K"] = "deleteLine";
function insertLine(cm, above) {
cm.operation(function() {
var len = cm.listSelections().length, newSelection = [], last = -1;
for (var i = 0; i < len; i++) {
var head = cm.listSelections()[i].head;
if (head.line <= last) continue;
var at = Pos(head.line + (above ? 0 : 1), 0);
cm.replaceRange("\n", at, null, "+insertLine");
cm.indentLine(at.line, null, true);
newSelection.push({head: at, anchor: at});
last = head.line + 1;
}
cm.setSelections(newSelection);
});
}
cmds[map[ctrl + "Enter"] = "insertLineAfter"] = function(cm) { insertLine(cm, false); };
cmds[map["Shift-" + ctrl + "Enter"] = "insertLineBefore"] = function(cm) { insertLine(cm, true); };
function wordAt(cm, pos) {
var start = pos.ch, end = start, line = cm.getLine(pos.line);
while (start && CodeMirror.isWordChar(line.charAt(start - 1))) --start;
while (end < line.length && CodeMirror.isWordChar(line.charAt(end))) ++end;
return {from: Pos(pos.line, start), to: Pos(pos.line, end), word: line.slice(start, end)};
}
cmds[map[ctrl + "D"] = "selectNextOccurrence"] = function(cm) {
var from = cm.getCursor("from"), to = cm.getCursor("to");
var fullWord = cm.state.sublimeFindFullWord == cm.doc.sel;
if (CodeMirror.cmpPos(from, to) == 0) {
var word = wordAt(cm, from);
if (!word.word) return;
cm.setSelection(word.from, word.to);
fullWord = true;
} else {
var text = cm.getRange(from, to);
var query = fullWord ? new RegExp("\\b" + text + "\\b") : text;
var cur = cm.getSearchCursor(query, to);
if (cur.findNext()) {
cm.addSelection(cur.from(), cur.to());
} else {
cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0));
if (cur.findNext())
cm.addSelection(cur.from(), cur.to());
}
}
if (fullWord)
cm.state.sublimeFindFullWord = cm.doc.sel;
};
var mirror = "(){}[]";
function selectBetweenBrackets(cm) {
var pos = cm.getCursor(), opening = cm.scanForBracket(pos, -1);
if (!opening) return;
for (;;) {
var closing = cm.scanForBracket(pos, 1);
if (!closing) return;
if (closing.ch == mirror.charAt(mirror.indexOf(opening.ch) + 1)) {
cm.setSelection(Pos(opening.pos.line, opening.pos.ch + 1), closing.pos, false);
return true;
}
pos = Pos(closing.pos.line, closing.pos.ch + 1);
}
}
cmds[map["Shift-" + ctrl + "Space"] = "selectScope"] = function(cm) {
selectBetweenBrackets(cm) || cm.execCommand("selectAll");
};
cmds[map["Shift-" + ctrl + "M"] = "selectBetweenBrackets"] = function(cm) {
if (!selectBetweenBrackets(cm)) return CodeMirror.Pass;
};
cmds[map[ctrl + "M"] = "goToBracket"] = function(cm) {
cm.extendSelectionsBy(function(range) {
var next = cm.scanForBracket(range.head, 1);
if (next && CodeMirror.cmpPos(next.pos, range.head) != 0) return next.pos;
var prev = cm.scanForBracket(range.head, -1);
return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head;
});
};
var swapLineCombo = mac ? "Cmd-Ctrl-" : "Shift-Ctrl-";
cmds[map[swapLineCombo + "Up"] = "swapLineUp"] = function(cm) {
var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = [];
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i], from = range.from().line - 1, to = range.to().line;
newSels.push({anchor: Pos(range.anchor.line - 1, range.anchor.ch),
head: Pos(range.head.line - 1, range.head.ch)});
if (range.to().ch == 0 && !range.empty()) --to;
if (from > at) linesToMove.push(from, to);
else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to;
at = to;
}
cm.operation(function() {
for (var i = 0; i < linesToMove.length; i += 2) {
var from = linesToMove[i], to = linesToMove[i + 1];
var line = cm.getLine(from);
cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine");
if (to > cm.lastLine())
cm.replaceRange("\n" + line, Pos(cm.lastLine()), null, "+swapLine");
else
cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine");
}
cm.setSelections(newSels);
cm.scrollIntoView();
});
};
cmds[map[swapLineCombo + "Down"] = "swapLineDown"] = function(cm) {
var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1;
for (var i = ranges.length - 1; i >= 0; i--) {
var range = ranges[i], from = range.to().line + 1, to = range.from().line;
if (range.to().ch == 0 && !range.empty()) from--;
if (from < at) linesToMove.push(from, to);
else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to;
at = to;
}
cm.operation(function() {
for (var i = linesToMove.length - 2; i >= 0; i -= 2) {
var from = linesToMove[i], to = linesToMove[i + 1];
var line = cm.getLine(from);
if (from == cm.lastLine())
cm.replaceRange("", Pos(from - 1), Pos(from), "+swapLine");
else
cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine");
cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine");
}
cm.scrollIntoView();
});
};
map[ctrl + "/"] = "toggleComment";
cmds[map[ctrl + "J"] = "joinLines"] = function(cm) {
var ranges = cm.listSelections(), joined = [];
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i], from = range.from();
var start = from.line, end = range.to().line;
while (i < ranges.length - 1 && ranges[i + 1].from().line == end)
end = ranges[++i].to().line;
joined.push({start: start, end: end, anchor: !range.empty() && from});
}
cm.operation(function() {
var offset = 0, ranges = [];
for (var i = 0; i < joined.length; i++) {
var obj = joined[i];
var anchor = obj.anchor && Pos(obj.anchor.line - offset, obj.anchor.ch), head;
for (var line = obj.start; line <= obj.end; line++) {
var actual = line - offset;
if (line == obj.end) head = Pos(actual, cm.getLine(actual).length + 1);
if (actual < cm.lastLine()) {
cm.replaceRange(" ", Pos(actual), Pos(actual + 1, /^\s*/.exec(cm.getLine(actual + 1))[0].length));
++offset;
}
}
ranges.push({anchor: anchor || head, head: head});
}
cm.setSelections(ranges, 0);
});
};
cmds[map["Shift-" + ctrl + "D"] = "duplicateLine"] = function(cm) {
cm.operation(function() {
var rangeCount = cm.listSelections().length;
for (var i = 0; i < rangeCount; i++) {
var range = cm.listSelections()[i];
if (range.empty())
cm.replaceRange(cm.getLine(range.head.line) + "\n", Pos(range.head.line, 0));
else
cm.replaceRange(cm.getRange(range.from(), range.to()), range.from());
}
cm.scrollIntoView();
});
};
map[ctrl + "T"] = "transposeChars";
function sortLines(cm, caseSensitive) {
var ranges = cm.listSelections(), toSort = [], selected;
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i];
if (range.empty()) continue;
var from = range.from().line, to = range.to().line;
while (i < ranges.length - 1 && ranges[i + 1].from().line == to)
to = range[++i].to().line;
toSort.push(from, to);
}
if (toSort.length) selected = true;
else toSort.push(cm.firstLine(), cm.lastLine());
cm.operation(function() {
var ranges = [];
for (var i = 0; i < toSort.length; i += 2) {
var from = toSort[i], to = toSort[i + 1];
var start = Pos(from, 0), end = Pos(to);
var lines = cm.getRange(start, end, false);
if (caseSensitive)
lines.sort();
else
lines.sort(function(a, b) {
var au = a.toUpperCase(), bu = b.toUpperCase();
if (au != bu) { a = au; b = bu; }
return a < b ? -1 : a == b ? 0 : 1;
});
cm.replaceRange(lines, start, end);
if (selected) ranges.push({anchor: start, head: end});
}
if (selected) cm.setSelections(ranges, 0);
});
}
cmds[map["F9"] = "sortLines"] = function(cm) { sortLines(cm, true); };
cmds[map[ctrl + "F9"] = "sortLinesInsensitive"] = function(cm) { sortLines(cm, false); };
cmds[map["F2"] = "nextBookmark"] = function(cm) {
var marks = cm.state.sublimeBookmarks;
if (marks) while (marks.length) {
var current = marks.shift();
var found = current.find();
if (found) {
marks.push(current);
return cm.setSelection(found.from, found.to);
}
}
};
cmds[map["Shift-F2"] = "prevBookmark"] = function(cm) {
var marks = cm.state.sublimeBookmarks;
if (marks) while (marks.length) {
marks.unshift(marks.pop());
var found = marks[marks.length - 1].find();
if (!found)
marks.pop();
else
return cm.setSelection(found.from, found.to);
}
};
cmds[map[ctrl + "F2"] = "toggleBookmark"] = function(cm) {
var ranges = cm.listSelections();
var marks = cm.state.sublimeBookmarks || (cm.state.sublimeBookmarks = []);
for (var i = 0; i < ranges.length; i++) {
var from = ranges[i].from(), to = ranges[i].to();
var found = cm.findMarks(from, to);
for (var j = 0; j < found.length; j++) {
if (found[j].sublimeBookmark) {
found[j].clear();
for (var k = 0; k < marks.length; k++)
if (marks[k] == found[j])
marks.splice(k--, 1);
break;
}
}
if (j == found.length)
marks.push(cm.markText(from, to, {sublimeBookmark: true, clearWhenEmpty: false}));
}
};
cmds[map["Shift-" + ctrl + "F2"] = "clearBookmarks"] = function(cm) {
var marks = cm.state.sublimeBookmarks;
if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear();
marks.length = 0;
};
cmds[map["Alt-F2"] = "selectBookmarks"] = function(cm) {
var marks = cm.state.sublimeBookmarks, ranges = [];
if (marks) for (var i = 0; i < marks.length; i++) {
var found = marks[i].find();
if (!found)
marks.splice(i--, 0);
else
ranges.push({anchor: found.from, head: found.to});
}
if (ranges.length)
cm.setSelections(ranges, 0);
};
map["Alt-Q"] = "wrapLines";
var cK = ctrl + "K ";
function modifyWordOrSelection(cm, mod) {
cm.operation(function() {
var ranges = cm.listSelections(), indices = [], replacements = [];
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i];
if (range.empty()) { indices.push(i); replacements.push(""); }
else replacements.push(mod(cm.getRange(range.from(), range.to())));
}
cm.replaceSelections(replacements, "around", "case");
for (var i = indices.length - 1, at; i >= 0; i--) {
var range = ranges[indices[i]];
if (at && CodeMirror.cmpPos(range.head, at) > 0) continue;
var word = wordAt(cm, range.head);
at = word.from;
cm.replaceRange(mod(word.word), word.from, word.to);
}
});
}
map[cK + ctrl + "Backspace"] = "delLineLeft";
cmds[map[cK + ctrl + "K"] = "delLineRight"] = function(cm) {
cm.operation(function() {
var ranges = cm.listSelections();
for (var i = ranges.length - 1; i >= 0; i--)
cm.replaceRange("", ranges[i].anchor, Pos(ranges[i].to().line), "+delete");
cm.scrollIntoView();
});
};
cmds[map[cK + ctrl + "U"] = "upcaseAtCursor"] = function(cm) {
modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); });
};
cmds[map[cK + ctrl + "L"] = "downcaseAtCursor"] = function(cm) {
modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); });
};
cmds[map[cK + ctrl + "Space"] = "setSublimeMark"] = function(cm) {
if (cm.state.sublimeMark) cm.state.sublimeMark.clear();
cm.state.sublimeMark = cm.setBookmark(cm.getCursor());
};
cmds[map[cK + ctrl + "A"] = "selectToSublimeMark"] = function(cm) {
var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
if (found) cm.setSelection(cm.getCursor(), found);
};
cmds[map[cK + ctrl + "W"] = "deleteToSublimeMark"] = function(cm) {
var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
if (found) {
var from = cm.getCursor(), to = found;
if (CodeMirror.cmpPos(from, to) > 0) { var tmp = to; to = from; from = tmp; }
cm.state.sublimeKilled = cm.getRange(from, to);
cm.replaceRange("", from, to);
}
};
cmds[map[cK + ctrl + "X"] = "swapWithSublimeMark"] = function(cm) {
var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
if (found) {
cm.state.sublimeMark.clear();
cm.state.sublimeMark = cm.setBookmark(cm.getCursor());
cm.setCursor(found);
}
};
cmds[map[cK + ctrl + "Y"] = "sublimeYank"] = function(cm) {
if (cm.state.sublimeKilled != null)
cm.replaceSelection(cm.state.sublimeKilled, null, "paste");
};
map[cK + ctrl + "G"] = "clearBookmarks";
cmds[map[cK + ctrl + "C"] = "showInCenter"] = function(cm) {
var pos = cm.cursorCoords(null, "local");
cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2);
};
cmds[map["Shift-Alt-Up"] = "selectLinesUpward"] = function(cm) {
cm.operation(function() {
var ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i];
if (range.head.line > cm.firstLine())
cm.addSelection(Pos(range.head.line - 1, range.head.ch));
}
});
};
cmds[map["Shift-Alt-Down"] = "selectLinesDownward"] = function(cm) {
cm.operation(function() {
var ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i];
if (range.head.line < cm.lastLine())
cm.addSelection(Pos(range.head.line + 1, range.head.ch));
}
});
};
function getTarget(cm) {
var from = cm.getCursor("from"), to = cm.getCursor("to");
if (CodeMirror.cmpPos(from, to) == 0) {
var word = wordAt(cm, from);
if (!word.word) return;
from = word.from;
to = word.to;
}
return {from: from, to: to, query: cm.getRange(from, to), word: word};
}
function findAndGoTo(cm, forward) {
var target = getTarget(cm);
if (!target) return;
var query = target.query;
var cur = cm.getSearchCursor(query, forward ? target.to : target.from);
if (forward ? cur.findNext() : cur.findPrevious()) {
cm.setSelection(cur.from(), cur.to());
} else {
cur = cm.getSearchCursor(query, forward ? Pos(cm.firstLine(), 0)
: cm.clipPos(Pos(cm.lastLine())));
if (forward ? cur.findNext() : cur.findPrevious())
cm.setSelection(cur.from(), cur.to());
else if (target.word)
cm.setSelection(target.from, target.to);
}
};
cmds[map[ctrl + "F3"] = "findUnder"] = function(cm) { findAndGoTo(cm, true); };
cmds[map["Shift-" + ctrl + "F3"] = "findUnderPrevious"] = function(cm) { findAndGoTo(cm,false); };
cmds[map["Alt-F3"] = "findAllUnder"] = function(cm) {
var target = getTarget(cm);
if (!target) return;
var cur = cm.getSearchCursor(target.query);
var matches = [];
var primaryIndex = -1;
while (cur.findNext()) {
matches.push({anchor: cur.from(), head: cur.to()});
if (cur.from().line <= target.from.line && cur.from().ch <= target.from.ch)
primaryIndex++;
}
cm.setSelections(matches, primaryIndex);
};
map["Shift-" + ctrl + "["] = "fold";
map["Shift-" + ctrl + "]"] = "unfold";
map[cK + ctrl + "0"] = map[cK + ctrl + "j"] = "unfoldAll";
map[ctrl + "I"] = "findIncremental";
map["Shift-" + ctrl + "I"] = "findIncrementalReverse";
map[ctrl + "H"] = "replace";
map["F3"] = "findNext";
map["Shift-F3"] = "findPrev";
CodeMirror.normalizeKeyMap(map);
});
File diff suppressed because it is too large Load Diff
+56 -17
View File
@@ -5,10 +5,6 @@
font-family: monospace; font-family: monospace;
height: 300px; height: 300px;
} }
.CodeMirror-scroll {
/* Set scrolling behaviour here */
overflow: auto;
}
/* PADDING */ /* PADDING */
@@ -40,6 +36,9 @@
box-sizing: content-box; box-sizing: content-box;
} }
.CodeMirror-guttermarker { color: black; }
.CodeMirror-guttermarker-subtle { color: #999; }
/* CURSOR */ /* CURSOR */
.CodeMirror div.CodeMirror-cursor { .CodeMirror div.CodeMirror-cursor {
@@ -49,15 +48,42 @@
.CodeMirror div.CodeMirror-secondarycursor { .CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver; border-left: 1px solid silver;
} }
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor { .CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
width: auto; width: auto;
border: 0; border: 0;
background: #7e7; background: #7e7;
} }
.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.cm-animate-fat-cursor {
width: auto;
border: 0;
-webkit-animation: blink 1.06s steps(1) infinite;
-moz-animation: blink 1.06s steps(1) infinite;
animation: blink 1.06s steps(1) infinite;
}
@-moz-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
@-webkit-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
@keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
/* Can style cursor different in overwrite (non-insert) mode */ /* Can style cursor different in overwrite (non-insert) mode */
div.CodeMirror-overwrite div.CodeMirror-cursor {} div.CodeMirror-overwrite div.CodeMirror-cursor {}
.cm-tab { display: inline-block; } .cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-ruler { .CodeMirror-ruler {
border-left: 1px solid #ccc; border-left: 1px solid #ccc;
@@ -70,11 +96,12 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
.cm-s-default .cm-atom {color: #219;} .cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;} .cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;} .cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable {color: black;} .cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;} .cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;} .cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-property {color: black;}
.cm-s-default .cm-operator {color: black;}
.cm-s-default .cm-comment {color: #a50;} .cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;} .cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;} .cm-s-default .cm-string-2 {color: #f50;}
@@ -94,12 +121,16 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
.cm-header, .cm-strong {font-weight: bold;} .cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;} .cm-em {font-style: italic;}
.cm-link {text-decoration: underline;} .cm-link {text-decoration: underline;}
.cm-strikethrough {text-decoration: line-through;}
.cm-s-default .cm-error {color: #f00;} .cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;} .cm-invalidchar {color: #f00;}
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;} .CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */ /* STOP */
@@ -116,6 +147,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
} }
.CodeMirror-scroll { .CodeMirror-scroll {
overflow: scroll !important; /* Things will break if this is overridden */
/* 30px is the magic margin used to hide the element's real scrollbars */ /* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */ /* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px; margin-bottom: -30px; margin-right: -30px;
@@ -160,7 +192,6 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-gutters { .CodeMirror-gutters {
position: absolute; left: 0; top: 0; position: absolute; left: 0; top: 0;
padding-bottom: 30px;
z-index: 3; z-index: 3;
} }
.CodeMirror-gutter { .CodeMirror-gutter {
@@ -168,13 +199,17 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
height: 100%; height: 100%;
-moz-box-sizing: content-box; -moz-box-sizing: content-box;
box-sizing: content-box; box-sizing: content-box;
padding-bottom: 30px;
margin-bottom: -32px;
display: inline-block; display: inline-block;
margin-bottom: -30px;
/* Hack to make IE7 behave */ /* Hack to make IE7 behave */
*zoom:1; *zoom:1;
*display:inline; *display:inline;
} }
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
height: 100%;
}
.CodeMirror-gutter-elt { .CodeMirror-gutter-elt {
position: absolute; position: absolute;
cursor: default; cursor: default;
@@ -183,6 +218,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-lines { .CodeMirror-lines {
cursor: text; cursor: text;
min-height: 1px; /* prevents collapsing before first draw */
} }
.CodeMirror pre { .CodeMirror pre {
/* Reset some styles that the rest of the page might have set */ /* Reset some styles that the rest of the page might have set */
@@ -220,10 +256,6 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-widget {} .CodeMirror-widget {}
.CodeMirror-wrap .CodeMirror-scroll {
overflow-x: hidden;
}
.CodeMirror-measure { .CodeMirror-measure {
position: absolute; position: absolute;
width: 100%; width: 100%;
@@ -242,7 +274,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
div.CodeMirror-cursors { div.CodeMirror-cursors {
visibility: hidden; visibility: hidden;
position: relative; position: relative;
z-index: 1; z-index: 3;
} }
.CodeMirror-focused div.CodeMirror-cursors { .CodeMirror-focused div.CodeMirror-cursors {
visibility: visible; visibility: visible;
@@ -250,6 +282,7 @@ div.CodeMirror-cursors {
.CodeMirror-selected { background: #d9d9d9; } .CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.cm-searching { .cm-searching {
background: #ffa; background: #ffa;
@@ -268,3 +301,9 @@ div.CodeMirror-cursors {
visibility: hidden; visibility: hidden;
} }
} }
/* See issue #2901 */
.cm-tab-wrap-hack:after { content: ''; }
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext { background: none; }
File diff suppressed because it is too large Load Diff
+151 -24
View File
@@ -1,3 +1,16 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("clike", function(config, parserConfig) { CodeMirror.defineMode("clike", function(config, parserConfig) {
var indentUnit = config.indentUnit, var indentUnit = config.indentUnit,
statementIndentUnit = parserConfig.statementIndentUnit || indentUnit, statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
@@ -7,7 +20,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
blockKeywords = parserConfig.blockKeywords || {}, blockKeywords = parserConfig.blockKeywords || {},
atoms = parserConfig.atoms || {}, atoms = parserConfig.atoms || {},
hooks = parserConfig.hooks || {}, hooks = parserConfig.hooks || {},
multiLineStrings = parserConfig.multiLineStrings; multiLineStrings = parserConfig.multiLineStrings,
indentStatements = parserConfig.indentStatements !== false;
var isOperatorChar = /[+\-*&%=<>!?|\/]/; var isOperatorChar = /[+\-*&%=<>!?|\/]/;
var curPunc; var curPunc;
@@ -44,7 +58,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
stream.eatWhile(isOperatorChar); stream.eatWhile(isOperatorChar);
return "operator"; return "operator";
} }
stream.eatWhile(/[\w\$_]/); stream.eatWhile(/[\w\$_\xa1-\uffff]/);
var cur = stream.current(); var cur = stream.current();
if (keywords.propertyIsEnumerable(cur)) { if (keywords.propertyIsEnumerable(cur)) {
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
@@ -138,7 +152,9 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
while (ctx.type == "statement") ctx = popContext(state); while (ctx.type == "statement") ctx = popContext(state);
} }
else if (curPunc == ctx.type) popContext(state); else if (curPunc == ctx.type) popContext(state);
else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement")) else if (indentStatements &&
(((ctx.type == "}" || ctx.type == "top") && curPunc != ';') ||
(ctx.type == "statement" && curPunc == "newstatement")))
pushContext(state, stream.column(), "statement"); pushContext(state, stream.column(), "statement");
state.startOfLine = false; state.startOfLine = false;
return style; return style;
@@ -163,7 +179,6 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
}; };
}); });
(function() {
function words(str) { function words(str) {
var obj = {}, words = str.split(" "); var obj = {}, words = str.split(" ");
for (var i = 0; i < words.length; ++i) obj[words[i]] = true; for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
@@ -191,6 +206,30 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
return "meta"; return "meta";
} }
function cpp11StringHook(stream, state) {
stream.backUp(1);
// Raw strings.
if (stream.match(/(R|u8R|uR|UR|LR)/)) {
var match = stream.match(/"([^\s\\()]{0,16})\(/);
if (!match) {
return false;
}
state.cpp11RawStringDelim = match[1];
state.tokenize = tokenRawString;
return tokenRawString(stream, state);
}
// Unicode strings/chars.
if (stream.match(/(u8|u|U|L)/)) {
if (stream.match(/["']/, /* eat */ false)) {
return "string";
}
return false;
}
// Ignore this hook.
stream.next();
return false;
}
// C#-style strings where "" escapes a quote. // C#-style strings where "" escapes a quote.
function tokenAtString(stream, state) { function tokenAtString(stream, state) {
var next; var next;
@@ -203,28 +242,67 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
return "string"; return "string";
} }
function mimes(ms, mode) { // C++11 raw string literal is <prefix>"<delim>( anything )<delim>", where
for (var i = 0; i < ms.length; ++i) CodeMirror.defineMIME(ms[i], mode); // <delim> can be a string up to 16 characters long.
function tokenRawString(stream, state) {
// Escape characters that have special regex meanings.
var delim = state.cpp11RawStringDelim.replace(/[^\w\s]/g, '\\$&');
var match = stream.match(new RegExp(".*?\\)" + delim + '"'));
if (match)
state.tokenize = null;
else
stream.skipToEnd();
return "string";
} }
mimes(["text/x-csrc", "text/x-c", "text/x-chdr"], { function def(mimes, mode) {
if (typeof mimes == "string") mimes = [mimes];
var words = [];
function add(obj) {
if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))
words.push(prop);
}
add(mode.keywords);
add(mode.builtin);
add(mode.atoms);
if (words.length) {
mode.helperType = mimes[0];
CodeMirror.registerHelper("hintWords", mimes[0], words);
}
for (var i = 0; i < mimes.length; ++i)
CodeMirror.defineMIME(mimes[i], mode);
}
def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
name: "clike", name: "clike",
keywords: words(cKeywords), keywords: words(cKeywords),
blockKeywords: words("case do else for if switch while struct"), blockKeywords: words("case do else for if switch while struct"),
atoms: words("null"), atoms: words("null"),
hooks: {"#": cppHook} hooks: {"#": cppHook},
modeProps: {fold: ["brace", "include"]}
}); });
mimes(["text/x-c++src", "text/x-c++hdr"], {
def(["text/x-c++src", "text/x-c++hdr"], {
name: "clike", name: "clike",
keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " + keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
"static_cast typeid catch operator template typename class friend private " + "static_cast typeid catch operator template typename class friend private " +
"this using const_cast inline public throw virtual delete mutable protected " + "this using const_cast inline public throw virtual delete mutable protected " +
"wchar_t"), "wchar_t alignas alignof constexpr decltype nullptr noexcept thread_local final " +
"static_assert override"),
blockKeywords: words("catch class do else finally for if struct switch try while"), blockKeywords: words("catch class do else finally for if struct switch try while"),
atoms: words("true false null"), atoms: words("true false null"),
hooks: {"#": cppHook} hooks: {
"#": cppHook,
"u": cpp11StringHook,
"U": cpp11StringHook,
"L": cpp11StringHook,
"R": cpp11StringHook
},
modeProps: {fold: ["brace", "include"]}
}); });
CodeMirror.defineMIME("text/x-java", {
def("text/x-java", {
name: "clike", name: "clike",
keywords: words("abstract assert boolean break byte case catch char class const continue default " + keywords: words("abstract assert boolean break byte case catch char class const continue default " +
"do double else enum extends final finally float for goto if implements import " + "do double else enum extends final finally float for goto if implements import " +
@@ -238,9 +316,11 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
stream.eatWhile(/[\w\$_]/); stream.eatWhile(/[\w\$_]/);
return "meta"; return "meta";
} }
} },
modeProps: {fold: ["brace", "import"]}
}); });
CodeMirror.defineMIME("text/x-csharp", {
def("text/x-csharp", {
name: "clike", name: "clike",
keywords: words("abstract as base break case catch checked class const continue" + keywords: words("abstract as base break case catch checked class const continue" +
" default delegate do else enum event explicit extern finally fixed for" + " default delegate do else enum event explicit extern finally fixed for" +
@@ -266,7 +346,20 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
} }
} }
}); });
CodeMirror.defineMIME("text/x-scala", {
function tokenTripleString(stream, state) {
var escaped = false;
while (!stream.eol()) {
if (!escaped && stream.match('"""')) {
state.tokenize = null;
break;
}
escaped = stream.next() != "\\" && !escaped;
}
return "string";
}
def("text/x-scala", {
name: "clike", name: "clike",
keywords: words( keywords: words(
@@ -291,25 +384,31 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " + "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " + "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void" "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
), ),
multiLineStrings: true,
blockKeywords: words("catch class do else finally for forSome if match switch try while"), blockKeywords: words("catch class do else finally for forSome if match switch try while"),
atoms: words("true false null"), atoms: words("true false null"),
indentStatements: false,
hooks: { hooks: {
"@": function(stream) { "@": function(stream) {
stream.eatWhile(/[\w\$_]/); stream.eatWhile(/[\w\$_]/);
return "meta"; return "meta";
},
'"': function(stream, state) {
if (!stream.match('""')) return false;
state.tokenize = tokenTripleString;
return state.tokenize(stream, state);
} }
} }
}); });
mimes(["x-shader/x-vertex", "x-shader/x-fragment"], {
def(["x-shader/x-vertex", "x-shader/x-fragment"], {
name: "clike", name: "clike",
keywords: words("float int bool void " + keywords: words("float int bool void " +
"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " + "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
"mat2 mat3 mat4 " + "mat2 mat3 mat4 " +
"sampler1D sampler2D sampler3D samplerCube " + "sampler1D sampler2D sampler3D samplerCube " +
"sampler1DShadow sampler2DShadow" + "sampler1DShadow sampler2DShadow " +
"const attribute uniform varying " + "const attribute uniform varying " +
"break continue discard return " + "break continue discard return " +
"for while do if else struct " + "for while do if else struct " +
@@ -317,7 +416,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
blockKeywords: words("for while do if else struct"), blockKeywords: words("for while do if else struct"),
builtin: words("radians degrees sin cos tan asin acos atan " + builtin: words("radians degrees sin cos tan asin acos atan " +
"pow exp log exp2 sqrt inversesqrt " + "pow exp log exp2 sqrt inversesqrt " +
"abs sign floor ceil fract mod min max clamp mix step smootstep " + "abs sign floor ceil fract mod min max clamp mix step smoothstep " +
"length distance dot cross normalize ftransform faceforward " + "length distance dot cross normalize ftransform faceforward " +
"reflect refract matrixCompMult " + "reflect refract matrixCompMult " +
"lessThan lessThanEqual greaterThan greaterThanEqual " + "lessThan lessThanEqual greaterThan greaterThanEqual " +
@@ -334,12 +433,12 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
"gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " + "gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
"gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " + "gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
"gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " + "gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
"gl_FogCoord " + "gl_FogCoord gl_PointCoord " +
"gl_Position gl_PointSize gl_ClipVertex " + "gl_Position gl_PointSize gl_ClipVertex " +
"gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " + "gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
"gl_TexCoord gl_FogFragCoord " + "gl_TexCoord gl_FogFragCoord " +
"gl_FragCoord gl_FrontFacing " + "gl_FragCoord gl_FrontFacing " +
"gl_FragColor gl_FragData gl_FragDepth " + "gl_FragData gl_FragDepth " +
"gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " + "gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
"gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " + "gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
"gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " + "gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
@@ -357,6 +456,34 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
"gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " + "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
"gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " + "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
"gl_MaxDrawBuffers"), "gl_MaxDrawBuffers"),
hooks: {"#": cppHook} hooks: {"#": cppHook},
modeProps: {fold: ["brace", "include"]}
}); });
}());
def("text/x-nesc", {
name: "clike",
keywords: words(cKeywords + "as atomic async call command component components configuration event generic " +
"implementation includes interface module new norace nx_struct nx_union post provides " +
"signal task uses abstract extends"),
blockKeywords: words("case do else for if switch while struct"),
atoms: words("null"),
hooks: {"#": cppHook},
modeProps: {fold: ["brace", "include"]}
});
def("text/x-objectivec", {
name: "clike",
keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " +
"inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
atoms: words("YES NO NULL NILL ON OFF"),
hooks: {
"@": function(stream) {
stream.eatWhile(/[\w\$]/);
return "keyword";
},
"#": cppHook
},
modeProps: {fold: "brace"}
});
});
+63 -7
View File
@@ -7,15 +7,17 @@
<link rel="stylesheet" href="../../lib/codemirror.css"> <link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script> <script src="../../lib/codemirror.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script> <script src="../../addon/edit/matchbrackets.js"></script>
<link rel="stylesheet" href="../../addon/hint/show-hint.css">
<script src="../../addon/hint/show-hint.js"></script>
<script src="clike.js"></script> <script src="clike.js"></script>
<style>.CodeMirror {border: 2px inset #dee;}</style> <style>.CodeMirror {border: 2px inset #dee;}</style>
<div id=nav> <div id=nav>
<a href="http://codemirror.net"><img id=logo src="../../doc/logo.png"></a> <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a> <li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/marijnh/codemirror">Code</a> <li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul> </ul>
<ul> <ul>
<li><a href="../index.html">Language modes</a> <li><a href="../index.html">Language modes</a>
@@ -105,6 +107,11 @@ enum Enum {
VAL1, VAL2, VAL3 VAL1, VAL2, VAL3
}; };
char32_t unicode_string = U"\U0010FFFF";
string raw_string = R"delim(anything
you
want)delim";
int Helper(const MyType& param) { int Helper(const MyType& param) {
return 0; return 0;
} }
@@ -132,6 +139,26 @@ void Class::Method2(MyType<T, V>* value) {
} }
</textarea></div> </textarea></div>
<h2>Objective-C example</h2>
<div><textarea id="objectivec-code">
/*
This is a longer comment
That spans two lines
*/
#import <Test/Test.h>
@implementation YourAppDelegate
// This is a one-line comment
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
char myString[] = "This is a C character array";
int test = 5;
return YES;
}
</textarea></div>
<h2>Java example</h2> <h2>Java example</h2>
<div><textarea id="java-code"> <div><textarea id="java-code">
@@ -162,15 +189,30 @@ public class Class<T, V> implements MyInterface {
member = value; member = value;
} }
} }
</textarea></div>
<h2>Scala example</h2>
<div><textarea id="scala-code">
object FilterTest extends App {
def filter(xs: List[Int], threshold: Int) = {
def process(ys: List[Int]): List[Int] =
if (ys.isEmpty) ys
else if (ys.head < threshold) ys.head :: process(ys.tail)
else process(ys.tail)
process(xs)
}
println(filter(List(1, 9, 2, 8, 3, 7, 4), 5))
}
</textarea></div> </textarea></div>
<script> <script>
var editor = CodeMirror.fromTextArea(document.getElementById("c-code"), { var cEditor = CodeMirror.fromTextArea(document.getElementById("c-code"), {
lineNumbers: true, lineNumbers: true,
matchBrackets: true, matchBrackets: true,
mode: "text/x-csrc" mode: "text/x-csrc"
}); });
var editor = CodeMirror.fromTextArea(document.getElementById("cpp-code"), { var cppEditor = CodeMirror.fromTextArea(document.getElementById("cpp-code"), {
lineNumbers: true, lineNumbers: true,
matchBrackets: true, matchBrackets: true,
mode: "text/x-c++src" mode: "text/x-c++src"
@@ -180,6 +222,18 @@ public class Class<T, V> implements MyInterface {
matchBrackets: true, matchBrackets: true,
mode: "text/x-java" mode: "text/x-java"
}); });
var objectivecEditor = CodeMirror.fromTextArea(document.getElementById("objectivec-code"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-objectivec"
});
var scalaEditor = CodeMirror.fromTextArea(document.getElementById("scala-code"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-scala"
});
var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
</script> </script>
<p>Simple mode that tries to handle C-like languages as well as it <p>Simple mode that tries to handle C-like languages as well as it
@@ -189,7 +243,9 @@ public class Class<T, V> implements MyInterface {
directives are recognized.</p> directives are recognized.</p>
<p><strong>MIME types defined:</strong> <code>text/x-csrc</code> <p><strong>MIME types defined:</strong> <code>text/x-csrc</code>
(C code), <code>text/x-c++src</code> (C++ (C), <code>text/x-c++src</code> (C++), <code>text/x-java</code>
code), <code>text/x-java</code> (Java (Java), <code>text/x-csharp</code> (C#),
code), <code>text/x-csharp</code> (C#).</p> <code>text/x-objectivec</code> (Objective-C),
<code>text/x-scala</code> (Scala), <code>text/x-vertex</code>
and <code>x-shader/x-fragment</code> (shader programs).</p>
</article> </article>
+2 -2
View File
@@ -10,12 +10,12 @@
<script src="../../addon/edit/matchbrackets.js"></script> <script src="../../addon/edit/matchbrackets.js"></script>
<script src="clike.js"></script> <script src="clike.js"></script>
<div id=nav> <div id=nav>
<a href="http://codemirror.net"><img id=logo src="../../doc/logo.png"></a> <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a> <li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/marijnh/codemirror">Code</a> <li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul> </ul>
<ul> <ul>
<li><a href="../index.html">Language modes</a> <li><a href="../index.html">Language modes</a>
@@ -1,11 +1,26 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
/** /**
* Author: Hans Engel * Author: Hans Engel
* Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun) * Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun)
*/ */
CodeMirror.defineMode("clojure", function () {
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("clojure", function (options) {
var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2", var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2",
ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword"; ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword", VAR = "variable";
var INDENT_WORD_SKIP = 2; var INDENT_WORD_SKIP = options.indentUnit || 2;
var NORMAL_INDENT_UNIT = options.indentUnit || 2;
function makeKeywords(str) { function makeKeywords(str) {
var obj = {}, words = str.split(" "); var obj = {}, words = str.split(" ");
@@ -44,7 +59,7 @@ CodeMirror.defineMode("clojure", function () {
sign: /[+-]/, sign: /[+-]/,
exponent: /e/i, exponent: /e/i,
keyword_char: /[^\s\(\[\;\)\]]/, keyword_char: /[^\s\(\[\;\)\]]/,
symbol: /[\w*+!\-\._?:\/]/ symbol: /[\w*+!\-\._?:<>\/\xa1-\uffff]/
}; };
function stateStack(indent, type, prev) { // represents a state stack object function stateStack(indent, type, prev) { // represents a state stack object
@@ -99,7 +114,7 @@ CodeMirror.defineMode("clojure", function () {
var first = stream.next(); var first = stream.next();
// Read special literals: backspace, newline, space, return. // Read special literals: backspace, newline, space, return.
// Just read all lowercase letters. // Just read all lowercase letters.
if (first.match(/[a-z]/) && stream.match(/[a-z]+/, true)) { if (first && first.match(/[a-z]/) && stream.match(/[a-z]+/, true)) {
return; return;
} }
// Read unicode character: \u1000 \uA0a1 // Read unicode character: \u1000 \uA0a1
@@ -179,8 +194,8 @@ CodeMirror.defineMode("clojure", function () {
stream.eatSpace(); stream.eatSpace();
if (stream.eol() || stream.peek() == ";") { if (stream.eol() || stream.peek() == ";") {
// nothing significant after // nothing significant after
// we restart indentation 1 space after // we restart indentation the user defined spaces after
pushStack(state, indentTemp + 1, ch); pushStack(state, indentTemp + NORMAL_INDENT_UNIT, ch);
} else { } else {
pushStack(state, indentTemp + stream.current().length, ch); // else we match pushStack(state, indentTemp + stream.current().length, ch); // else we match
} }
@@ -205,7 +220,9 @@ CodeMirror.defineMode("clojure", function () {
returnType = BUILTIN; returnType = BUILTIN;
} else if (atoms && atoms.propertyIsEnumerable(stream.current())) { } else if (atoms && atoms.propertyIsEnumerable(stream.current())) {
returnType = ATOM; returnType = ATOM;
} else returnType = null; } else {
returnType = VAR;
}
} }
} }
@@ -222,3 +239,5 @@ CodeMirror.defineMode("clojure", function () {
}); });
CodeMirror.defineMIME("text/x-clojure", "clojure"); CodeMirror.defineMIME("text/x-clojure", "clojure");
});
@@ -9,12 +9,12 @@
<script src="clojure.js"></script> <script src="clojure.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style> <style>.CodeMirror {background: #f8f8f8;}</style>
<div id=nav> <div id=nav>
<a href="http://codemirror.net"><img id=logo src="../../doc/logo.png"></a> <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a> <li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/marijnh/codemirror">Code</a> <li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul> </ul>
<ul> <ul>
<li><a href="../index.html">Language modes</a> <li><a href="../index.html">Language modes</a>
@@ -1,22 +0,0 @@
The MIT License
Copyright (c) 2011 Jeff Pickhardt
Modified from the Python CodeMirror mode, Copyright (c) 2010 Timothy Farrell
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.
@@ -1,348 +1,369 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
/** /**
* Link to the project's GitHub page: * Link to the project's GitHub page:
* https://github.com/pickhardt/coffeescript-codemirror-mode * https://github.com/pickhardt/coffeescript-codemirror-mode
*/ */
CodeMirror.defineMode('coffeescript', function(conf) { (function(mod) {
var ERRORCLASS = 'error'; if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
function wordRegexp(words) { CodeMirror.defineMode("coffeescript", function(conf, parserConf) {
return new RegExp("^((" + words.join(")|(") + "))\\b"); var ERRORCLASS = "error";
function wordRegexp(words) {
return new RegExp("^((" + words.join(")|(") + "))\\b");
}
var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/;
var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/;
var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/;
var properties = /^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*/;
var wordOperators = wordRegexp(["and", "or", "not",
"is", "isnt", "in",
"instanceof", "typeof"]);
var indentKeywords = ["for", "while", "loop", "if", "unless", "else",
"switch", "try", "catch", "finally", "class"];
var commonKeywords = ["break", "by", "continue", "debugger", "delete",
"do", "in", "of", "new", "return", "then",
"this", "@", "throw", "when", "until", "extends"];
var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
indentKeywords = wordRegexp(indentKeywords);
var stringPrefixes = /^('{3}|\"{3}|['\"])/;
var regexPrefixes = /^(\/{3}|\/)/;
var commonConstants = ["Infinity", "NaN", "undefined", "null", "true", "false", "on", "off", "yes", "no"];
var constants = wordRegexp(commonConstants);
// Tokenizers
function tokenBase(stream, state) {
// Handle scope changes
if (stream.sol()) {
if (state.scope.align === null) state.scope.align = false;
var scopeOffset = state.scope.offset;
if (stream.eatSpace()) {
var lineOffset = stream.indentation();
if (lineOffset > scopeOffset && state.scope.type == "coffee") {
return "indent";
} else if (lineOffset < scopeOffset) {
return "dedent";
}
return null;
} else {
if (scopeOffset > 0) {
dedent(stream, state);
}
}
}
if (stream.eatSpace()) {
return null;
} }
var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\?]"); var ch = stream.peek();
var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\},:`=;\\.]');
var doubleOperators = new RegExp("^((\->)|(\=>)|(\\+\\+)|(\\+\\=)|(\\-\\-)|(\\-\\=)|(\\*\\*)|(\\*\\=)|(\\/\\/)|(\\/\\=)|(==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//))");
var doubleDelimiters = new RegExp("^((\\.\\.)|(\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
var tripleDelimiters = new RegExp("^((\\.\\.\\.)|(//=)|(>>=)|(<<=)|(\\*\\*=))");
var identifiers = new RegExp("^[_A-Za-z$][_A-Za-z$0-9]*");
var properties = new RegExp("^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*");
var wordOperators = wordRegexp(['and', 'or', 'not', // Handle docco title comment (single line)
'is', 'isnt', 'in', if (stream.match("####")) {
'instanceof', 'typeof']); stream.skipToEnd();
var indentKeywords = ['for', 'while', 'loop', 'if', 'unless', 'else', return "comment";
'switch', 'try', 'catch', 'finally', 'class'];
var commonKeywords = ['break', 'by', 'continue', 'debugger', 'delete',
'do', 'in', 'of', 'new', 'return', 'then',
'this', 'throw', 'when', 'until'];
var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
indentKeywords = wordRegexp(indentKeywords);
var stringPrefixes = new RegExp("^('{3}|\"{3}|['\"])");
var regexPrefixes = new RegExp("^(/{3}|/)");
var commonConstants = ['Infinity', 'NaN', 'undefined', 'null', 'true', 'false', 'on', 'off', 'yes', 'no'];
var constants = wordRegexp(commonConstants);
// Tokenizers
function tokenBase(stream, state) {
// Handle scope changes
if (stream.sol()) {
var scopeOffset = state.scopes[0].offset;
if (stream.eatSpace()) {
var lineOffset = stream.indentation();
if (lineOffset > scopeOffset) {
return 'indent';
} else if (lineOffset < scopeOffset) {
return 'dedent';
}
return null;
} else {
if (scopeOffset > 0) {
dedent(stream, state);
}
}
}
if (stream.eatSpace()) {
return null;
}
var ch = stream.peek();
// Handle docco title comment (single line)
if (stream.match("####")) {
stream.skipToEnd();
return 'comment';
}
// Handle multi line comments
if (stream.match("###")) {
state.tokenize = longComment;
return state.tokenize(stream, state);
}
// Single line comment
if (ch === '#') {
stream.skipToEnd();
return 'comment';
}
// Handle number literals
if (stream.match(/^-?[0-9\.]/, false)) {
var floatLiteral = false;
// Floats
if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
floatLiteral = true;
}
if (stream.match(/^-?\d+\.\d*/)) {
floatLiteral = true;
}
if (stream.match(/^-?\.\d+/)) {
floatLiteral = true;
}
if (floatLiteral) {
// prevent from getting extra . on 1..
if (stream.peek() == "."){
stream.backUp(1);
}
return 'number';
}
// Integers
var intLiteral = false;
// Hex
if (stream.match(/^-?0x[0-9a-f]+/i)) {
intLiteral = true;
}
// Decimal
if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
intLiteral = true;
}
// Zero by itself with no other piece of number.
if (stream.match(/^-?0(?![\dx])/i)) {
intLiteral = true;
}
if (intLiteral) {
return 'number';
}
}
// Handle strings
if (stream.match(stringPrefixes)) {
state.tokenize = tokenFactory(stream.current(), 'string');
return state.tokenize(stream, state);
}
// Handle regex literals
if (stream.match(regexPrefixes)) {
if (stream.current() != '/' || stream.match(/^.*\//, false)) { // prevent highlight of division
state.tokenize = tokenFactory(stream.current(), 'string-2');
return state.tokenize(stream, state);
} else {
stream.backUp(1);
}
}
// Handle operators and delimiters
if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
return 'punctuation';
}
if (stream.match(doubleOperators)
|| stream.match(singleOperators)
|| stream.match(wordOperators)) {
return 'operator';
}
if (stream.match(singleDelimiters)) {
return 'punctuation';
}
if (stream.match(constants)) {
return 'atom';
}
if (stream.match(keywords)) {
return 'keyword';
}
if (stream.match(identifiers)) {
return 'variable';
}
if (stream.match(properties)) {
return 'property';
}
// Handle non-detected items
stream.next();
return ERRORCLASS;
} }
function tokenFactory(delimiter, outclass) { // Handle multi line comments
var singleline = delimiter.length == 1; if (stream.match("###")) {
return function(stream, state) { state.tokenize = longComment;
while (!stream.eol()) { return state.tokenize(stream, state);
stream.eatWhile(/[^'"\/\\]/); }
if (stream.eat('\\')) {
stream.next(); // Single line comment
if (singleline && stream.eol()) { if (ch === "#") {
return outclass; stream.skipToEnd();
} return "comment";
} else if (stream.match(delimiter)) { }
state.tokenize = tokenBase;
return outclass; // Handle number literals
} else { if (stream.match(/^-?[0-9\.]/, false)) {
stream.eat(/['"\/]/); var floatLiteral = false;
} // Floats
} if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
if (singleline) { floatLiteral = true;
if (conf.mode.singleLineStringErrors) { }
outclass = ERRORCLASS; if (stream.match(/^-?\d+\.\d*/)) {
} else { floatLiteral = true;
state.tokenize = tokenBase; }
} if (stream.match(/^-?\.\d+/)) {
} floatLiteral = true;
}
if (floatLiteral) {
// prevent from getting extra . on 1..
if (stream.peek() == "."){
stream.backUp(1);
}
return "number";
}
// Integers
var intLiteral = false;
// Hex
if (stream.match(/^-?0x[0-9a-f]+/i)) {
intLiteral = true;
}
// Decimal
if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
intLiteral = true;
}
// Zero by itself with no other piece of number.
if (stream.match(/^-?0(?![\dx])/i)) {
intLiteral = true;
}
if (intLiteral) {
return "number";
}
}
// Handle strings
if (stream.match(stringPrefixes)) {
state.tokenize = tokenFactory(stream.current(), false, "string");
return state.tokenize(stream, state);
}
// Handle regex literals
if (stream.match(regexPrefixes)) {
if (stream.current() != "/" || stream.match(/^.*\//, false)) { // prevent highlight of division
state.tokenize = tokenFactory(stream.current(), true, "string-2");
return state.tokenize(stream, state);
} else {
stream.backUp(1);
}
}
// Handle operators and delimiters
if (stream.match(operators) || stream.match(wordOperators)) {
return "operator";
}
if (stream.match(delimiters)) {
return "punctuation";
}
if (stream.match(constants)) {
return "atom";
}
if (stream.match(keywords)) {
return "keyword";
}
if (stream.match(identifiers)) {
return "variable";
}
if (stream.match(properties)) {
return "property";
}
// Handle non-detected items
stream.next();
return ERRORCLASS;
}
function tokenFactory(delimiter, singleline, outclass) {
return function(stream, state) {
while (!stream.eol()) {
stream.eatWhile(/[^'"\/\\]/);
if (stream.eat("\\")) {
stream.next();
if (singleline && stream.eol()) {
return outclass; return outclass;
}; }
} } else if (stream.match(delimiter)) {
state.tokenize = tokenBase;
function longComment(stream, state) { return outclass;
while (!stream.eol()) {
stream.eatWhile(/[^#]/);
if (stream.match("###")) {
state.tokenize = tokenBase;
break;
}
stream.eatWhile("#");
}
return "comment";
}
function indent(stream, state, type) {
type = type || 'coffee';
var indentUnit = 0;
if (type === 'coffee') {
for (var i = 0; i < state.scopes.length; i++) {
if (state.scopes[i].type === 'coffee') {
indentUnit = state.scopes[i].offset + conf.indentUnit;
break;
}
}
} else { } else {
indentUnit = stream.column() + stream.current().length; stream.eat(/['"\/]/);
} }
state.scopes.unshift({ }
offset: indentUnit, if (singleline) {
type: type if (parserConf.singleLineStringErrors) {
}); outclass = ERRORCLASS;
}
function dedent(stream, state) {
if (state.scopes.length == 1) return;
if (state.scopes[0].type === 'coffee') {
var _indent = stream.indentation();
var _indent_index = -1;
for (var i = 0; i < state.scopes.length; ++i) {
if (_indent === state.scopes[i].offset) {
_indent_index = i;
break;
}
}
if (_indent_index === -1) {
return true;
}
while (state.scopes[0].offset !== _indent) {
state.scopes.shift();
}
return false;
} else { } else {
state.scopes.shift(); state.tokenize = tokenBase;
return false;
} }
} }
return outclass;
function tokenLexer(stream, state) {
var style = state.tokenize(stream, state);
var current = stream.current();
// Handle '.' connected identifiers
if (current === '.') {
style = state.tokenize(stream, state);
current = stream.current();
if (/^\.[\w$]+$/.test(current)) {
return 'variable';
} else {
return ERRORCLASS;
}
}
// Handle scope changes.
if (current === 'return') {
state.dedent += 1;
}
if (((current === '->' || current === '=>') &&
!state.lambda &&
state.scopes[0].type == 'coffee' &&
stream.peek() === '')
|| style === 'indent') {
indent(stream, state);
}
var delimiter_index = '[({'.indexOf(current);
if (delimiter_index !== -1) {
indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));
}
if (indentKeywords.exec(current)){
indent(stream, state);
}
if (current == 'then'){
dedent(stream, state);
}
if (style === 'dedent') {
if (dedent(stream, state)) {
return ERRORCLASS;
}
}
delimiter_index = '])}'.indexOf(current);
if (delimiter_index !== -1) {
if (dedent(stream, state)) {
return ERRORCLASS;
}
}
if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'coffee') {
if (state.scopes.length > 1) state.scopes.shift();
state.dedent -= 1;
}
return style;
}
var external = {
startState: function(basecolumn) {
return {
tokenize: tokenBase,
scopes: [{offset:basecolumn || 0, type:'coffee'}],
lastToken: null,
lambda: false,
dedent: 0
};
},
token: function(stream, state) {
var style = tokenLexer(stream, state);
state.lastToken = {style:style, content: stream.current()};
if (stream.eol() && stream.lambda) {
state.lambda = false;
}
return style;
},
indent: function(state) {
if (state.tokenize != tokenBase) {
return 0;
}
return state.scopes[0].offset;
},
lineComment: "#",
fold: "indent"
}; };
return external; }
function longComment(stream, state) {
while (!stream.eol()) {
stream.eatWhile(/[^#]/);
if (stream.match("###")) {
state.tokenize = tokenBase;
break;
}
stream.eatWhile("#");
}
return "comment";
}
function indent(stream, state, type) {
type = type || "coffee";
var offset = 0, align = false, alignOffset = null;
for (var scope = state.scope; scope; scope = scope.prev) {
if (scope.type === "coffee" || scope.type == "}") {
offset = scope.offset + conf.indentUnit;
break;
}
}
if (type !== "coffee") {
align = null;
alignOffset = stream.column() + stream.current().length;
} else if (state.scope.align) {
state.scope.align = false;
}
state.scope = {
offset: offset,
type: type,
prev: state.scope,
align: align,
alignOffset: alignOffset
};
}
function dedent(stream, state) {
if (!state.scope.prev) return;
if (state.scope.type === "coffee") {
var _indent = stream.indentation();
var matched = false;
for (var scope = state.scope; scope; scope = scope.prev) {
if (_indent === scope.offset) {
matched = true;
break;
}
}
if (!matched) {
return true;
}
while (state.scope.prev && state.scope.offset !== _indent) {
state.scope = state.scope.prev;
}
return false;
} else {
state.scope = state.scope.prev;
return false;
}
}
function tokenLexer(stream, state) {
var style = state.tokenize(stream, state);
var current = stream.current();
// Handle "." connected identifiers
if (current === ".") {
style = state.tokenize(stream, state);
current = stream.current();
if (/^\.[\w$]+$/.test(current)) {
return "variable";
} else {
return ERRORCLASS;
}
}
// Handle scope changes.
if (current === "return") {
state.dedent = true;
}
if (((current === "->" || current === "=>") &&
!state.lambda &&
!stream.peek())
|| style === "indent") {
indent(stream, state);
}
var delimiter_index = "[({".indexOf(current);
if (delimiter_index !== -1) {
indent(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
}
if (indentKeywords.exec(current)){
indent(stream, state);
}
if (current == "then"){
dedent(stream, state);
}
if (style === "dedent") {
if (dedent(stream, state)) {
return ERRORCLASS;
}
}
delimiter_index = "])}".indexOf(current);
if (delimiter_index !== -1) {
while (state.scope.type == "coffee" && state.scope.prev)
state.scope = state.scope.prev;
if (state.scope.type == current)
state.scope = state.scope.prev;
}
if (state.dedent && stream.eol()) {
if (state.scope.type == "coffee" && state.scope.prev)
state.scope = state.scope.prev;
state.dedent = false;
}
return style;
}
var external = {
startState: function(basecolumn) {
return {
tokenize: tokenBase,
scope: {offset:basecolumn || 0, type:"coffee", prev: null, align: false},
lastToken: null,
lambda: false,
dedent: 0
};
},
token: function(stream, state) {
var fillAlign = state.scope.align === null && state.scope;
if (fillAlign && stream.sol()) fillAlign.align = false;
var style = tokenLexer(stream, state);
if (fillAlign && style && style != "comment") fillAlign.align = true;
state.lastToken = {style:style, content: stream.current()};
if (stream.eol() && stream.lambda) {
state.lambda = false;
}
return style;
},
indent: function(state, text) {
if (state.tokenize != tokenBase) return 0;
var scope = state.scope;
var closer = text && "])}".indexOf(text.charAt(0)) > -1;
if (closer) while (scope.type == "coffee" && scope.prev) scope = scope.prev;
var closes = closer && scope.type === text.charAt(0);
if (scope.align)
return scope.alignOffset - (closes ? 1 : 0);
else
return (closes ? scope.prev : scope).offset;
},
lineComment: "#",
fold: "indent"
};
return external;
}); });
CodeMirror.defineMIME('text/x-coffeescript', 'coffeescript'); CodeMirror.defineMIME("text/x-coffeescript", "coffeescript");
});
@@ -9,12 +9,12 @@
<script src="coffeescript.js"></script> <script src="coffeescript.js"></script>
<style>.CodeMirror {border-top: 1px solid silver; border-bottom: 1px solid silver;}</style> <style>.CodeMirror {border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>
<div id=nav> <div id=nav>
<a href="http://codemirror.net"><img id=logo src="../../doc/logo.png"></a> <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a> <li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/marijnh/codemirror">Code</a> <li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul> </ul>
<ul> <ul>
<li><a href="../index.html">Language modes</a> <li><a href="../index.html">Language modes</a>
@@ -735,6 +735,6 @@ wrapper::value = -> this._wrapped
<p><strong>MIME types defined:</strong> <code>text/x-coffeescript</code>.</p> <p><strong>MIME types defined:</strong> <code>text/x-coffeescript</code>.</p>
<p>The CoffeeScript mode was written by Jeff Pickhardt (<a href="LICENSE">license</a>).</p> <p>The CoffeeScript mode was written by Jeff Pickhardt.</p>
</article> </article>
+42 -26
View File
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
@@ -16,6 +19,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
mediaTypes = parserConfig.mediaTypes || {}, mediaTypes = parserConfig.mediaTypes || {},
mediaFeatures = parserConfig.mediaFeatures || {}, mediaFeatures = parserConfig.mediaFeatures || {},
propertyKeywords = parserConfig.propertyKeywords || {}, propertyKeywords = parserConfig.propertyKeywords || {},
nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
colorKeywords = parserConfig.colorKeywords || {}, colorKeywords = parserConfig.colorKeywords || {},
valueKeywords = parserConfig.valueKeywords || {}, valueKeywords = parserConfig.valueKeywords || {},
fontProperties = parserConfig.fontProperties || {}, fontProperties = parserConfig.fontProperties || {},
@@ -53,7 +57,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
if (/[\d.]/.test(stream.peek())) { if (/[\d.]/.test(stream.peek())) {
stream.eatWhile(/[\w.%]/); stream.eatWhile(/[\w.%]/);
return ret("number", "unit"); return ret("number", "unit");
} else if (stream.match(/^[^-]+-/)) { } else if (stream.match(/^\w+-/)) {
return ret("meta", "meta"); return ret("meta", "meta");
} }
} else if (/[,+>*\/]/.test(ch)) { } else if (/[,+>*\/]/.test(ch)) {
@@ -91,7 +95,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
function tokenParenthesized(stream, state) { function tokenParenthesized(stream, state) {
stream.next(); // Must be '(' stream.next(); // Must be '('
if (!stream.match(/\s*[\"\']/, false)) if (!stream.match(/\s*[\"\')]/, false))
state.tokenize = tokenString(")"); state.tokenize = tokenString(")");
else else
state.tokenize = null; state.tokenize = null;
@@ -163,18 +167,22 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
} else if (type == ":") { } else if (type == ":") {
return "pseudo"; return "pseudo";
} else if (allowNested && type == "(") { } else if (allowNested && type == "(") {
return pushContext(state, stream, "params"); return pushContext(state, stream, "parens");
} }
return state.context.type; return state.context.type;
}; };
states.block = function(type, stream, state) { states.block = function(type, stream, state) {
if (type == "word") { if (type == "word") {
if (propertyKeywords.hasOwnProperty(stream.current().toLowerCase())) { var word = stream.current().toLowerCase();
if (propertyKeywords.hasOwnProperty(word)) {
override = "property"; override = "property";
return "maybeprop"; return "maybeprop";
} else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
override = "string-2";
return "maybeprop";
} else if (allowNested) { } else if (allowNested) {
override = stream.match(/^\s*:/, false) ? "property" : "tag"; override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
return "block"; return "block";
} else { } else {
override += " error"; override += " error";
@@ -220,6 +228,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
states.parens = function(type, stream, state) { states.parens = function(type, stream, state) {
if (type == "{" || type == "}") return popAndPass(type, stream, state); if (type == "{" || type == "}") return popAndPass(type, stream, state);
if (type == ")") return popContext(state); if (type == ")") return popContext(state);
if (type == "(") return pushContext(state, stream, "parens");
if (type == "word") wordAsValue(stream);
return "parens"; return "parens";
}; };
@@ -295,13 +305,6 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
return "interpolation"; return "interpolation";
}; };
states.params = function(type, stream, state) {
if (type == ")") return popContext(state);
if (type == "{" || type == "}") return popAndPass(type, stream, state);
if (type == "word") wordAsValue(stream);
return "params";
};
return { return {
startState: function(base) { startState: function(base) {
return {tokenize: null, return {tokenize: null,
@@ -324,10 +327,10 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
indent: function(state, textAfter) { indent: function(state, textAfter) {
var cx = state.context, ch = textAfter && textAfter.charAt(0); var cx = state.context, ch = textAfter && textAfter.charAt(0);
var indent = cx.indent; var indent = cx.indent;
if (cx.type == "prop" && ch == "}") cx = cx.prev; if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
if (cx.prev && if (cx.prev &&
(ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") || (ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") ||
ch == ")" && (cx.type == "parens" || cx.type == "params" || cx.type == "media_parens") || ch == ")" && (cx.type == "parens" || cx.type == "media_parens") ||
ch == "{" && (cx.type == "at" || cx.type == "media"))) { ch == "{" && (cx.type == "at" || cx.type == "media"))) {
indent = cx.indent - indentUnit; indent = cx.indent - indentUnit;
cx = cx.prev; cx = cx.prev;
@@ -417,7 +420,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"marker-offset", "marks", "marquee-direction", "marquee-loop", "marker-offset", "marks", "marquee-direction", "marquee-loop",
"marquee-play-count", "marquee-speed", "marquee-style", "max-height", "marquee-play-count", "marquee-speed", "marquee-style", "max-height",
"max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index", "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
"nav-left", "nav-right", "nav-up", "opacity", "order", "orphans", "outline", "nav-left", "nav-right", "nav-up", "object-fit", "object-position",
"opacity", "order", "orphans", "outline",
"outline-color", "outline-offset", "outline-style", "outline-width", "outline-color", "outline-offset", "outline-style", "outline-width",
"overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y", "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
"padding", "padding-bottom", "padding-left", "padding-right", "padding-top", "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
@@ -428,8 +432,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"region-break-before", "region-break-inside", "region-fragment", "region-break-before", "region-break-inside", "region-fragment",
"rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness", "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
"right", "rotation", "rotation-point", "ruby-align", "ruby-overhang", "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
"ruby-position", "ruby-span", "shape-inside", "shape-outside", "size", "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
"speak", "speak-as", "speak-header", "shape-outside", "size", "speak", "speak-as", "speak-header",
"speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set", "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
"tab-size", "table-layout", "target", "target-name", "target-new", "tab-size", "table-layout", "target", "target-name", "target-new",
"target-position", "text-align", "text-align-last", "text-decoration", "target-position", "text-align", "text-align-last", "text-decoration",
@@ -444,19 +448,27 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"vertical-align", "visibility", "voice-balance", "voice-duration", "vertical-align", "visibility", "voice-balance", "voice-duration",
"voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress", "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
"voice-volume", "volume", "white-space", "widows", "width", "word-break", "voice-volume", "volume", "white-space", "widows", "width", "word-break",
"word-spacing", "word-wrap", "z-index", "zoom", "word-spacing", "word-wrap", "z-index",
// SVG-specific // SVG-specific
"clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color", "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
"flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events", "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
"color-interpolation", "color-interpolation-filters", "color-profile", "color-interpolation", "color-interpolation-filters",
"color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering", "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
"marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke", "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
"stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
"stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering", "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
"baseline-shift", "dominant-baseline", "glyph-orientation-horizontal", "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
"glyph-orientation-vertical", "kerning", "text-anchor", "writing-mode" "glyph-orientation-vertical", "text-anchor", "writing-mode"
], propertyKeywords = keySet(propertyKeywords_); ], propertyKeywords = keySet(propertyKeywords_);
var nonStandardPropertyKeywords_ = [
"scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
"scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
"scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",
"searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
"searchfield-results-decoration", "zoom"
], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
var colorKeywords_ = [ var colorKeywords_ = [
"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
@@ -479,8 +491,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered", "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
"orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred", "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
"papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
"purple", "red", "rosybrown", "royalblue", "saddlebrown", "salmon", "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
"sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue", "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
"slateblue", "slategray", "snow", "springgreen", "steelblue", "tan", "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white", "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
"whitesmoke", "yellow", "yellowgreen" "whitesmoke", "yellow", "yellowgreen"
@@ -513,14 +525,14 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"ethiopic-halehame-sid-et", "ethiopic-halehame-so-et", "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et",
"ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed", "ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed",
"extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes", "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "footnotes",
"forwards", "from", "geometricPrecision", "georgian", "graytext", "groove", "forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew", "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
"help", "hidden", "hide", "higher", "highlight", "highlighttext", "help", "hidden", "hide", "higher", "highlight", "highlighttext",
"hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore", "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis", "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
"inline-block", "inline-table", "inset", "inside", "intrinsic", "invert", "inline-block", "inline-flex", "inline-table", "inset", "inside", "intrinsic", "invert",
"italic", "justify", "kannada", "katakana", "katakana-iroha", "keep-all", "khmer", "italic", "justify", "kannada", "katakana", "katakana-iroha", "keep-all", "khmer",
"landscape", "lao", "large", "larger", "left", "level", "lighter", "landscape", "lao", "large", "larger", "left", "level", "lighter",
"line-through", "linear", "lines", "list-item", "listbox", "listitem", "line-through", "linear", "lines", "list-item", "listbox", "listitem",
@@ -576,7 +588,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"font-stretch", "font-weight", "font-style" "font-stretch", "font-weight", "font-style"
], fontProperties = keySet(fontProperties_); ], fontProperties = keySet(fontProperties_);
var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_).concat(colorKeywords_).concat(valueKeywords_); var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_)
.concat(nonStandardPropertyKeywords_).concat(colorKeywords_).concat(valueKeywords_);
CodeMirror.registerHelper("hintWords", "css", allWords); CodeMirror.registerHelper("hintWords", "css", allWords);
function tokenCComment(stream, state) { function tokenCComment(stream, state) {
@@ -605,6 +618,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
mediaTypes: mediaTypes, mediaTypes: mediaTypes,
mediaFeatures: mediaFeatures, mediaFeatures: mediaFeatures,
propertyKeywords: propertyKeywords, propertyKeywords: propertyKeywords,
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
colorKeywords: colorKeywords, colorKeywords: colorKeywords,
valueKeywords: valueKeywords, valueKeywords: valueKeywords,
fontProperties: fontProperties, fontProperties: fontProperties,
@@ -627,6 +641,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
mediaTypes: mediaTypes, mediaTypes: mediaTypes,
mediaFeatures: mediaFeatures, mediaFeatures: mediaFeatures,
propertyKeywords: propertyKeywords, propertyKeywords: propertyKeywords,
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
colorKeywords: colorKeywords, colorKeywords: colorKeywords,
valueKeywords: valueKeywords, valueKeywords: valueKeywords,
fontProperties: fontProperties, fontProperties: fontProperties,
@@ -644,7 +659,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
} }
}, },
":": function(stream) { ":": function(stream) {
if (stream.match(/\s*{/)) if (stream.match(/\s*\{/))
return [null, "{"]; return [null, "{"];
return false; return false;
}, },
@@ -667,6 +682,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
mediaTypes: mediaTypes, mediaTypes: mediaTypes,
mediaFeatures: mediaFeatures, mediaFeatures: mediaFeatures,
propertyKeywords: propertyKeywords, propertyKeywords: propertyKeywords,
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
colorKeywords: colorKeywords, colorKeywords: colorKeywords,
valueKeywords: valueKeywords, valueKeywords: valueKeywords,
fontProperties: fontProperties, fontProperties: fontProperties,
@@ -0,0 +1,75 @@
<!doctype html>
<title>CodeMirror: CSS mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">
<link rel="stylesheet" href="../../lib/codemirror.css">
<link rel="stylesheet" href="../../addon/hint/show-hint.css">
<script src="../../lib/codemirror.js"></script>
<script src="css.js"></script>
<script src="../../addon/hint/show-hint.js"></script>
<script src="../../addon/hint/css-hint.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style>
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<ul>
<li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul>
<ul>
<li><a href="../index.html">Language modes</a>
<li><a class=active href="#">CSS</a>
</ul>
</div>
<article>
<h2>CSS mode</h2>
<form><textarea id="code" name="code">
/* Some example CSS */
@import url("something.css");
body {
margin: 0;
padding: 3em 6em;
font-family: tahoma, arial, sans-serif;
color: #000;
}
#navigation a {
font-weight: bold;
text-decoration: none !important;
}
h1 {
font-size: 2.5em;
}
h2 {
font-size: 1.7em;
}
h1:before, h2:before {
content: "::";
}
code {
font-family: courier, monospace;
font-size: 80%;
color: #418A8A;
}
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
extraKeys: {"Ctrl-Space": "autocomplete"},
});
</script>
<p><strong>MIME types defined:</strong> <code>text/css</code>, <code>text/x-scss</code> (<a href="scss.html">demo</a>), <code>text/x-less</code> (<a href="less.html">demo</a>).</p>
<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#css_*">normal</a>, <a href="../../test/index.html#verbose,css_*">verbose</a>.</p>
</article>
+152
View File
@@ -0,0 +1,152 @@
<!doctype html>
<title>CodeMirror: LESS mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="css.js"></script>
<style>.CodeMirror {border: 1px solid #ddd; line-height: 1.2;}</style>
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<ul>
<li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul>
<ul>
<li><a href="../index.html">Language modes</a>
<li><a class=active href="#">LESS</a>
</ul>
</div>
<article>
<h2>LESS mode</h2>
<form><textarea id="code" name="code">@media screen and (device-aspect-ratio: 16/9) { … }
@media screen and (device-aspect-ratio: 1280/720) { … }
@media screen and (device-aspect-ratio: 2560/1440) { … }
html:lang(fr-be)
tr:nth-child(2n+1) /* represents every odd row of an HTML table */
img:nth-of-type(2n+1) { float: right; }
img:nth-of-type(2n) { float: left; }
body > h2:not(:first-of-type):not(:last-of-type)
html|*:not(:link):not(:visited)
*|*:not(:hover)
p::first-line { text-transform: uppercase }
@namespace foo url(http://www.example.com);
foo|h1 { color: blue } /* first rule */
span[hello="Ocean"][goodbye="Land"]
E[foo]{
padding:65px;
}
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button {
-webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5
}
button::-moz-focus-inner,
input::-moz-focus-inner { // Inner padding and border oddities in FF3/4
padding: 0;
border: 0;
}
.btn {
// reset here as of 2.0.3 due to Recess property order
border-color: #ccc;
border-color: rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);
}
fieldset span button, fieldset span input[type="file"] {
font-size:12px;
font-family:Arial, Helvetica, sans-serif;
}
.rounded-corners (@radius: 5px) {
border-radius: @radius;
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
}
@import url("something.css");
@light-blue: hsl(190, 50%, 65%);
#menu {
position: absolute;
width: 100%;
z-index: 3;
clear: both;
display: block;
background-color: @blue;
height: 42px;
border-top: 2px solid lighten(@alpha-blue, 20%);
border-bottom: 2px solid darken(@alpha-blue, 25%);
.box-shadow(0, 1px, 8px, 0.6);
-moz-box-shadow: 0 0 0 #000; // Because firefox sucks.
&.docked {
background-color: hsla(210, 60%, 40%, 0.4);
}
&:hover {
background-color: @blue;
}
#dropdown {
margin: 0 0 0 117px;
padding: 0;
padding-top: 5px;
display: none;
width: 190px;
border-top: 2px solid @medium;
color: @highlight;
border: 2px solid darken(@medium, 25%);
border-left-color: darken(@medium, 15%);
border-right-color: darken(@medium, 15%);
border-top-width: 0;
background-color: darken(@medium, 10%);
ul {
padding: 0px;
}
li {
font-size: 14px;
display: block;
text-align: left;
padding: 0;
border: 0;
a {
display: block;
padding: 0px 15px;
text-decoration: none;
color: white;
&:hover {
background-color: darken(@medium, 15%);
text-decoration: none;
}
}
}
.border-radius(5px, bottom);
.box-shadow(0, 6px, 8px, 0.5);
}
}
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers : true,
matchBrackets : true,
mode: "text/x-less"
});
</script>
<p>The LESS mode is a sub-mode of the <a href="index.html">CSS mode</a> (defined in <code>css.js</code>.</p>
<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#less_*">normal</a>, <a href="../../test/index.html#verbose,less_*">verbose</a>.</p>
</article>
@@ -0,0 +1,51 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function() {
"use strict";
var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-less");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "less"); }
MT("variable",
"[variable-2 @base]: [atom #f04615];",
"[qualifier .class] {",
" [property width]: [variable percentage]([number 0.5]); [comment // returns `50%`]",
" [property color]: [variable saturate]([variable-2 @base], [number 5%]);",
"}");
MT("amp",
"[qualifier .child], [qualifier .sibling] {",
" [qualifier .parent] [atom &] {",
" [property color]: [keyword black];",
" }",
" [atom &] + [atom &] {",
" [property color]: [keyword red];",
" }",
"}");
MT("mixin",
"[qualifier .mixin] ([variable dark]; [variable-2 @color]) {",
" [property color]: [variable darken]([variable-2 @color], [number 10%]);",
"}",
"[qualifier .mixin] ([variable light]; [variable-2 @color]) {",
" [property color]: [variable lighten]([variable-2 @color], [number 10%]);",
"}",
"[qualifier .mixin] ([variable-2 @_]; [variable-2 @color]) {",
" [property display]: [atom block];",
"}",
"[variable-2 @switch]: [variable light];",
"[qualifier .class] {",
" [qualifier .mixin]([variable-2 @switch]; [atom #888]);",
"}");
MT("nest",
"[qualifier .one] {",
" [def @media] ([property width]: [number 400px]) {",
" [property font-size]: [number 1.2em];",
" [def @media] [attribute print] [keyword and] [property color] {",
" [property color]: [keyword blue];",
" }",
" }",
"}");
})();
+2 -2
View File
@@ -9,12 +9,12 @@
<script src="css.js"></script> <script src="css.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style> <style>.CodeMirror {background: #f8f8f8;}</style>
<div id=nav> <div id=nav>
<a href="http://codemirror.net"><img id=logo src="../../doc/logo.png"></a> <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a> <li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/marijnh/codemirror">Code</a> <li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul> </ul>
<ul> <ul>
<li><a href="../index.html">Language modes</a> <li><a href="../index.html">Language modes</a>
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function() { (function() {
var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss"); var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); } function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); }
+16
View File
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function() { (function() {
var mode = CodeMirror.getMode({indentUnit: 2}, "css"); var mode = CodeMirror.getMode({indentUnit: 2}, "css");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
@@ -116,4 +119,17 @@
" [property src]: [atom url]([string http://blah]),", " [property src]: [atom url]([string http://blah]),",
" [atom url]([string http://foo]);", " [atom url]([string http://foo]);",
"}"); "}");
MT("empty_url",
"[def @import] [tag url]() [tag screen];");
MT("parens",
"[qualifier .foo] {",
" [property background-image]: [variable fade]([atom #000], [number 20%]);",
" [property border-image]: [variable linear-gradient](",
" [atom to] [atom bottom],",
" [variable fade]([atom #000], [number 20%]) [number 0%],",
" [variable fade]([atom #000], [number 20%]) [number 100%]",
" );",
"}");
})(); })();
+16 -10
View File
@@ -1,5 +1,15 @@
(function() { // CodeMirror, copyright (c) by Marijn Haverbeke and others
"use strict"; // Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
// full haml mode. This handled embeded ruby and html fragments too // full haml mode. This handled embeded ruby and html fragments too
CodeMirror.defineMode("haml", function(config) { CodeMirror.defineMode("haml", function(config) {
@@ -65,7 +75,7 @@
// donot handle --> as valid ruby, make it HTML close comment instead // donot handle --> as valid ruby, make it HTML close comment instead
if (state.startOfLine && !stream.match("-->", false) && (ch == "=" || ch == "-" )) { if (state.startOfLine && !stream.match("-->", false) && (ch == "=" || ch == "-" )) {
state.tokenize = ruby; state.tokenize = ruby;
return null; return state.tokenize(stream, state);
} }
if (state.previousToken.style == "hamlTag" || if (state.previousToken.style == "hamlTag" ||
@@ -73,10 +83,10 @@
state.previousToken.style == "hamlAttribute") { state.previousToken.style == "hamlAttribute") {
if (ch == "(") { if (ch == "(") {
state.tokenize = rubyInQuote(")"); state.tokenize = rubyInQuote(")");
return null; return state.tokenize(stream, state);
} else if (ch == "{") { } else if (ch == "{") {
state.tokenize = rubyInQuote("}"); state.tokenize = rubyInQuote("}");
return null; return state.tokenize(stream, state);
} }
} }
@@ -141,13 +151,9 @@
style = null; style = null;
} }
return style; return style;
},
indent: function(state) {
return state.indented;
} }
}; };
}, "htmlmixed", "ruby"); }, "htmlmixed", "ruby");
CodeMirror.defineMIME("text/x-haml", "haml"); CodeMirror.defineMIME("text/x-haml", "haml");
})(); });
+2 -2
View File
@@ -13,12 +13,12 @@
<script src="haml.js"></script> <script src="haml.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style> <style>.CodeMirror {background: #f8f8f8;}</style>
<div id=nav> <div id=nav>
<a href="http://codemirror.net"><img id=logo src="../../doc/logo.png"></a> <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a> <li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/marijnh/codemirror">Code</a> <li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul> </ul>
<ul> <ul>
<li><a href="../index.html">Language modes</a> <li><a href="../index.html">Language modes</a>
+7 -4
View File
@@ -1,5 +1,8 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function() { (function() {
var mode = CodeMirror.getMode({tabSize: 4}, "haml"); var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "haml");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
// Requires at least one media query // Requires at least one media query
@@ -28,7 +31,7 @@
"[tag %a]([variable title][operator =][string \"test\"]){[atom :title] [operator =>] [string \"test\"]}"); "[tag %a]([variable title][operator =][string \"test\"]){[atom :title] [operator =>] [string \"test\"]}");
MT("htmlCode", MT("htmlCode",
"[tag <h1>]Title[tag </h1>]"); "[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket </][tag h1][tag&bracket >]");
MT("rubyBlock", MT("rubyBlock",
"[operator =][variable-2 @item]"); "[operator =][variable-2 @item]");
@@ -50,9 +53,9 @@
" [comment -# this is a comment]", " [comment -# this is a comment]",
" [comment and this is a comment too]", " [comment and this is a comment too]",
" Date/Time", " Date/Time",
" [operator -] [variable now] [operator =] [tag DateTime][operator .][variable now]", " [operator -] [variable now] [operator =] [tag DateTime][operator .][property now]",
" [tag %strong=] [variable now]", " [tag %strong=] [variable now]",
" [operator -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][variable parse]([string \"December 31, 2006\"])", " [operator -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \"December 31, 2006\"])",
" [operator =][string \"Happy\"]", " [operator =][string \"Happy\"]",
" [operator =][string \"Belated\"]", " [operator =][string \"Belated\"]",
" [operator =][string \"Birthday\"]"); " [operator =][string \"Birthday\"]");
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed")); mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"));
@@ -0,0 +1,58 @@
<!doctype html>
<title>CodeMirror: Html Embedded Scripts mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../xml/xml.js"></script>
<script src="../javascript/javascript.js"></script>
<script src="../css/css.js"></script>
<script src="../htmlmixed/htmlmixed.js"></script>
<script src="htmlembedded.js"></script>
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<ul>
<li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul>
<ul>
<li><a href="../index.html">Language modes</a>
<li><a class=active href="#">Html Embedded Scripts</a>
</ul>
</div>
<article>
<h2>Html Embedded Scripts mode</h2>
<form><textarea id="code" name="code">
<%
function hello(who) {
return "Hello " + who;
}
%>
This is an example of EJS (embedded javascript)
<p>The program says <%= hello("world") %>.</p>
<script>
alert("And here is some normal JS code"); // also colored
</script>
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
mode: "application/x-ejs",
indentUnit: 4,
indentWithTabs: true
});
</script>
<p>Mode for html embedded scripts like JSP and ASP.NET. Depends on HtmlMixed which in turn depends on
JavaScript, CSS and XML.<br />Other dependancies include those of the scriping language chosen.</p>
<p><strong>MIME types defined:</strong> <code>application/x-aspx</code> (ASP.NET),
<code>application/x-ejs</code> (Embedded Javascript), <code>application/x-jsp</code> (JavaServer Pages)</p>
</article>
@@ -1,3 +1,6 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css")); mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
@@ -27,6 +30,7 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
function html(stream, state) { function html(stream, state) {
var tagName = state.htmlState.tagName; var tagName = state.htmlState.tagName;
if (tagName) tagName = tagName.toLowerCase();
var style = htmlMode.token(stream, state.htmlState); var style = htmlMode.token(stream, state.htmlState);
if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") { if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
// Script block: mode to change to depends on type attribute // Script block: mode to change to depends on type attribute
@@ -65,7 +69,7 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
if (stream.match(/^<\/\s*script\s*>/i, false)) { if (stream.match(/^<\/\s*script\s*>/i, false)) {
state.token = html; state.token = html;
state.localState = state.localMode = null; state.localState = state.localMode = null;
return html(stream, state); return null;
} }
return maybeBackup(stream, /<\/\s*script\s*>/, return maybeBackup(stream, /<\/\s*script\s*>/,
state.localMode.token(stream, state.localState)); state.localMode.token(stream, state.localState));
@@ -74,7 +78,7 @@ CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
if (stream.match(/^<\/\s*style\s*>/i, false)) { if (stream.match(/^<\/\s*style\s*>/i, false)) {
state.token = html; state.token = html;
state.localState = state.localMode = null; state.localState = state.localMode = null;
return html(stream, state); return null;
} }
return maybeBackup(stream, /<\/\s*style\s*>/, return maybeBackup(stream, /<\/\s*style\s*>/,
cssMode.token(stream, state.localState)); cssMode.token(stream, state.localState));
@@ -0,0 +1,89 @@
<!doctype html>
<title>CodeMirror: HTML mixed mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../addon/selection/selection-pointer.js"></script>
<script src="../xml/xml.js"></script>
<script src="../javascript/javascript.js"></script>
<script src="../css/css.js"></script>
<script src="../vbscript/vbscript.js"></script>
<script src="htmlmixed.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<ul>
<li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul>
<ul>
<li><a href="../index.html">Language modes</a>
<li><a class=active href="#">HTML mixed</a>
</ul>
</div>
<article>
<h2>HTML mixed mode</h2>
<form><textarea id="code" name="code">
<html style="color: green">
<!-- this is a comment -->
<head>
<title>Mixed HTML Example</title>
<style type="text/css">
h1 {font-family: comic sans; color: #f0f;}
div {background: yellow !important;}
body {
max-width: 50em;
margin: 1em 2em 1em 5em;
}
</style>
</head>
<body>
<h1>Mixed HTML Example</h1>
<script>
function jsFunc(arg1, arg2) {
if (arg1 && arg2) document.body.innerHTML = "achoo";
}
</script>
</body>
</html>
</textarea></form>
<script>
// Define an extended mixed-mode that understands vbscript and
// leaves mustache/handlebars embedded templates in html mode
var mixedMode = {
name: "htmlmixed",
scriptTypes: [{matches: /\/x-handlebars-template|\/x-mustache/i,
mode: null},
{matches: /(text|application)\/(x-)?vb(a|script)/i,
mode: "vbscript"}]
};
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: mixedMode,
selectionPointer: true
});
</script>
<p>The HTML mixed mode depends on the XML, JavaScript, and CSS modes.</p>
<p>It takes an optional mode configuration
option, <code>scriptTypes</code>, which can be used to add custom
behavior for specific <code>&lt;script type="..."></code> tags. If
given, it should hold an array of <code>{matches, mode}</code>
objects, where <code>matches</code> is a string or regexp that
matches the script type, and <code>mode</code> is
either <code>null</code>, for script types that should stay in
HTML mode, or a <a href="../../doc/manual.html#option_mode">mode
spec</a> corresponding to the mode that should be used for the
script.</p>
<p><strong>MIME types defined:</strong> <code>text/html</code>
(redefined, only takes effect if you load this parser after the
XML parser).</p>
</article>
+15
View File
@@ -1,3 +1,16 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("http", function() { CodeMirror.defineMode("http", function() {
function failFirstLine(stream, state) { function failFirstLine(stream, state) {
stream.skipToEnd(); stream.skipToEnd();
@@ -96,3 +109,5 @@ CodeMirror.defineMode("http", function() {
}); });
CodeMirror.defineMIME("message/http", "http"); CodeMirror.defineMIME("message/http", "http");
});
+2 -2
View File
@@ -9,12 +9,12 @@
<script src="http.js"></script> <script src="http.js"></script>
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="http://codemirror.net"><img id=logo src="../../doc/logo.png"></a> <a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a> <li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/marijnh/codemirror">Code</a> <li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul> </ul>
<ul> <ul>
<li><a href="../index.html">Language modes</a> <li><a href="../index.html">Language modes</a>
+132
View File
@@ -0,0 +1,132 @@
<!doctype html>
<title>CodeMirror: Language Modes</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
<ul>
<li><a href="../index.html">Home</a>
<li><a href="../doc/manual.html">Manual</a>
<li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul>
<ul>
<li><a class=active href="#">Language modes</a>
</ul>
</div>
<article>
<h2>Language modes</h2>
<p>This is a list of every mode in the distribution. Each mode lives
in a subdirectory of the <code>mode/</code> directory, and typically
defines a single JavaScript file that implements the mode. Loading
such file will make the language available to CodeMirror, through
the <a href="../doc/manual.html#option_mode"><code>mode</code></a>
option.</p>
<div style="-webkit-columns: 100px 2; -moz-columns: 100px 2; columns: 100px 2;">
<ul style="margin-top: 0">
<li><a href="apl/index.html">APL</a></li>
<li><a href="asterisk/index.html">Asterisk dialplan</a></li>
<li><a href="clike/index.html">C, C++, C#</a></li>
<li><a href="clojure/index.html">Clojure</a></li>
<li><a href="cobol/index.html">COBOL</a></li>
<li><a href="coffeescript/index.html">CoffeeScript</a></li>
<li><a href="commonlisp/index.html">Common Lisp</a></li>
<li><a href="css/index.html">CSS</a></li>
<li><a href="cypher/index.html">Cypher</a></li>
<li><a href="python/index.html">Cython</a></li>
<li><a href="d/index.html">D</a></li>
<li><a href="dart/index.html">Dart</a></li>
<li><a href="django/index.html">Django</a> (templating language)</li>
<li><a href="dockerfile/index.html">Dockerfile</a></li>
<li><a href="diff/index.html">diff</a></li>
<li><a href="dtd/index.html">DTD</a></li>
<li><a href="dylan/index.html">Dylan</a></li>
<li><a href="ebnf/index.html">EBNF</a></li>
<li><a href="ecl/index.html">ECL</a></li>
<li><a href="eiffel/index.html">Eiffel</a></li>
<li><a href="erlang/index.html">Erlang</a></li>
<li><a href="fortran/index.html">Fortran</a></li>
<li><a href="mllike/index.html">F#</a></li>
<li><a href="gas/index.html">Gas</a> (AT&amp;T-style assembly)</li>
<li><a href="gherkin/index.html">Gherkin</a></li>
<li><a href="go/index.html">Go</a></li>
<li><a href="groovy/index.html">Groovy</a></li>
<li><a href="haml/index.html">HAML</a></li>
<li><a href="haskell/index.html">Haskell</a></li>
<li><a href="haxe/index.html">Haxe</a></li>
<li><a href="htmlembedded/index.html">HTML embedded scripts</a></li>
<li><a href="htmlmixed/index.html">HTML mixed-mode</a></li>
<li><a href="http/index.html">HTTP</a></li>
<li><a href="idl/index.html">IDL</a></li>
<li><a href="clike/index.html">Java</a></li>
<li><a href="jade/index.html">Jade</a></li>
<li><a href="javascript/index.html">JavaScript</a></li>
<li><a href="jinja2/index.html">Jinja2</a></li>
<li><a href="julia/index.html">Julia</a></li>
<li><a href="kotlin/index.html">Kotlin</a></li>
<li><a href="css/less.html">LESS</a></li>
<li><a href="livescript/index.html">LiveScript</a></li>
<li><a href="lua/index.html">Lua</a></li>
<li><a href="markdown/index.html">Markdown</a> (<a href="gfm/index.html">GitHub-flavour</a>)</li>
<li><a href="mirc/index.html">mIRC</a></li>
<li><a href="modelica/index.html">Modelica</a></li>
<li><a href="nginx/index.html">Nginx</a></li>
<li><a href="ntriples/index.html">NTriples</a></li>
<li><a href="clike/index.html">Objective C</a></li>
<li><a href="mllike/index.html">OCaml</a></li>
<li><a href="octave/index.html">Octave</a> (MATLAB)</li>
<li><a href="pascal/index.html">Pascal</a></li>
<li><a href="pegjs/index.html">PEG.js</a></li>
<li><a href="perl/index.html">Perl</a></li>
<li><a href="php/index.html">PHP</a></li>
<li><a href="pig/index.html">Pig Latin</a></li>
<li><a href="properties/index.html">Properties files</a></li>
<li><a href="puppet/index.html">Puppet</a></li>
<li><a href="python/index.html">Python</a></li>
<li><a href="q/index.html">Q</a></li>
<li><a href="r/index.html">R</a></li>
<li><a href="rpm/index.html">RPM</a></li>
<li><a href="rst/index.html">reStructuredText</a></li>
<li><a href="ruby/index.html">Ruby</a></li>
<li><a href="rust/index.html">Rust</a></li>
<li><a href="sass/index.html">Sass</a></li>
<li><a href="spreadsheet/index.html">Spreadsheet</a></li>
<li><a href="clike/scala.html">Scala</a></li>
<li><a href="scheme/index.html">Scheme</a></li>
<li><a href="css/scss.html">SCSS</a></li>
<li><a href="shell/index.html">Shell</a></li>
<li><a href="sieve/index.html">Sieve</a></li>
<li><a href="slim/index.html">Slim</a></li>
<li><a href="smalltalk/index.html">Smalltalk</a></li>
<li><a href="smarty/index.html">Smarty</a></li>
<li><a href="smartymixed/index.html">Smarty/HTML mixed</a></li>
<li><a href="solr/index.html">Solr</a></li>
<li><a href="soy/index.html">Soy</a></li>
<li><a href="sql/index.html">SQL</a> (several dialects)</li>
<li><a href="sparql/index.html">SPARQL</a></li>
<li><a href="stex/index.html">sTeX, LaTeX</a></li>
<li><a href="tcl/index.html">Tcl</a></li>
<li><a href="textile/index.html">Textile</a></li>
<li><a href="tiddlywiki/index.html">Tiddlywiki</a></li>
<li><a href="tiki/index.html">Tiki wiki</a></li>
<li><a href="toml/index.html">TOML</a></li>
<li><a href="tornado/index.html">Tornado</a> (templating language)</li>
<li><a href="turtle/index.html">Turtle</a></li>
<li><a href="vb/index.html">VB.NET</a></li>
<li><a href="vbscript/index.html">VBScript</a></li>
<li><a href="velocity/index.html">Velocity</a></li>
<li><a href="verilog/index.html">Verilog/SystemVerilog</a></li>
<li><a href="xml/index.html">XML/HTML</a></li>
<li><a href="xquery/index.html">XQuery</a></li>
<li><a href="yaml/index.html">YAML</a></li>
<li><a href="z80/index.html">Z80</a></li>
</ul>
</div>
</article>

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