mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Updated the CodeMirror to the latest stable version (5.14.2).
It has now the 'sql/x-pgsql' mode, which will make the queries more familiar, and lot more improved addons.
This commit is contained in:
parent
471cd72bb9
commit
a5aa6d159a
@ -8,7 +8,7 @@ Bootstrap 3.3.4 MIT http://getbootstrap.com/
|
|||||||
jQuery 1.11.1 MIT http://jquery.com/
|
jQuery 1.11.1 MIT http://jquery.com/
|
||||||
Modernizr 2.6.2 MIT/BSD http://modernizr.com/
|
Modernizr 2.6.2 MIT/BSD http://modernizr.com/
|
||||||
AlertifyJS 1.1.0 MIT http://alertifyjs.com/
|
AlertifyJS 1.1.0 MIT http://alertifyjs.com/
|
||||||
CodeMirror 4.12 MIT http://codemirror.net/
|
CodeMirror 5.14.2 MIT http://codemirror.net/
|
||||||
aciTree 4.5.0-rc.7 MIT/GPL http://acoderinsights.ro/en/aciTree-tree-view-with-jQuery
|
aciTree 4.5.0-rc.7 MIT/GPL http://acoderinsights.ro/en/aciTree-tree-view-with-jQuery
|
||||||
contextMenu 2.1.0 MIT https://github.com/swisnl/jQuery-contextMenu
|
contextMenu 2.1.0 MIT https://github.com/swisnl/jQuery-contextMenu
|
||||||
wcDocker 0f5690318c MIT/GPL https://github.com/WebCabin/wcDocker
|
wcDocker 0f5690318c MIT/GPL https://github.com/WebCabin/wcDocker
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
define('pgadmin.browser',
|
define('pgadmin.browser',
|
||||||
['require', 'jquery', 'underscore', 'underscore.string', 'bootstrap',
|
['require', 'jquery', 'underscore', 'underscore.string', 'bootstrap',
|
||||||
'pgadmin', 'alertify', 'codemirror', 'codemirror/mode/sql', 'wcdocker',
|
'pgadmin', 'alertify', 'codemirror', 'codemirror/mode/sql/sql', 'wcdocker',
|
||||||
'jquery.contextmenu', 'jquery.aciplugin', 'jquery.acitree',
|
'jquery.contextmenu', 'jquery.aciplugin', 'jquery.acitree',
|
||||||
'pgadmin.alertifyjs', 'pgadmin.browser.messages',
|
'pgadmin.alertifyjs', 'pgadmin.browser.messages',
|
||||||
'pgadmin.browser.menu', 'pgadmin.browser.panel',
|
'pgadmin.browser.menu', 'pgadmin.browser.panel',
|
||||||
@ -318,7 +318,7 @@ function(require, $, _, S, Bootstrap, pgAdmin, alertify, CodeMirror) {
|
|||||||
obj.editor = CodeMirror.fromTextArea(
|
obj.editor = CodeMirror.fromTextArea(
|
||||||
document.getElementById("sql-textarea"), {
|
document.getElementById("sql-textarea"), {
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
mode: "text/x-sql",
|
mode: "text/x-pgsql",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
/* Set height, width, borders, and global font properties here */
|
/* Set height, width, borders, and global font properties here */
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PADDING */
|
/* PADDING */
|
||||||
@ -32,8 +33,7 @@
|
|||||||
min-width: 20px;
|
min-width: 20px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
color: #999;
|
color: #999;
|
||||||
-moz-box-sizing: content-box;
|
white-space: nowrap;
|
||||||
box-sizing: content-box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror-guttermarker { color: black; }
|
.CodeMirror-guttermarker { color: black; }
|
||||||
@ -41,19 +41,21 @@
|
|||||||
|
|
||||||
/* CURSOR */
|
/* CURSOR */
|
||||||
|
|
||||||
.CodeMirror div.CodeMirror-cursor {
|
.CodeMirror-cursor {
|
||||||
border-left: 1px solid black;
|
border-left: 1px solid black;
|
||||||
|
border-right: none;
|
||||||
|
width: 0;
|
||||||
}
|
}
|
||||||
/* Shown when moving in bi-directional text */
|
/* Shown when moving in bi-directional text */
|
||||||
.CodeMirror div.CodeMirror-secondarycursor {
|
.CodeMirror div.CodeMirror-secondarycursor {
|
||||||
border-left: 1px solid silver;
|
border-left: 1px solid silver;
|
||||||
}
|
}
|
||||||
.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
|
.cm-fat-cursor .CodeMirror-cursor {
|
||||||
width: auto;
|
width: auto;
|
||||||
border: 0;
|
border: 0;
|
||||||
background: #7e7;
|
background: #7e7;
|
||||||
}
|
}
|
||||||
.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
|
.cm-fat-cursor div.CodeMirror-cursors {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,25 +65,26 @@
|
|||||||
-webkit-animation: blink 1.06s steps(1) infinite;
|
-webkit-animation: blink 1.06s steps(1) infinite;
|
||||||
-moz-animation: blink 1.06s steps(1) infinite;
|
-moz-animation: blink 1.06s steps(1) infinite;
|
||||||
animation: blink 1.06s steps(1) infinite;
|
animation: blink 1.06s steps(1) infinite;
|
||||||
|
background-color: #7e7;
|
||||||
}
|
}
|
||||||
@-moz-keyframes blink {
|
@-moz-keyframes blink {
|
||||||
0% { background: #7e7; }
|
0% {}
|
||||||
50% { background: none; }
|
50% { background-color: transparent; }
|
||||||
100% { background: #7e7; }
|
100% {}
|
||||||
}
|
}
|
||||||
@-webkit-keyframes blink {
|
@-webkit-keyframes blink {
|
||||||
0% { background: #7e7; }
|
0% {}
|
||||||
50% { background: none; }
|
50% { background-color: transparent; }
|
||||||
100% { background: #7e7; }
|
100% {}
|
||||||
}
|
}
|
||||||
@keyframes blink {
|
@keyframes blink {
|
||||||
0% { background: #7e7; }
|
0% {}
|
||||||
50% { background: none; }
|
50% { background-color: transparent; }
|
||||||
100% { background: #7e7; }
|
100% {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can style cursor different in overwrite (non-insert) mode */
|
/* Can style cursor different in overwrite (non-insert) mode */
|
||||||
div.CodeMirror-overwrite div.CodeMirror-cursor {}
|
.CodeMirror-overwrite .CodeMirror-cursor {}
|
||||||
|
|
||||||
.cm-tab { display: inline-block; text-decoration: inherit; }
|
.cm-tab { display: inline-block; text-decoration: inherit; }
|
||||||
|
|
||||||
@ -92,6 +95,15 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
|
|||||||
|
|
||||||
/* DEFAULT THEME */
|
/* DEFAULT THEME */
|
||||||
|
|
||||||
|
.cm-s-default .cm-header {color: blue;}
|
||||||
|
.cm-s-default .cm-quote {color: #090;}
|
||||||
|
.cm-negative {color: #d44;}
|
||||||
|
.cm-positive {color: #292;}
|
||||||
|
.cm-header, .cm-strong {font-weight: bold;}
|
||||||
|
.cm-em {font-style: italic;}
|
||||||
|
.cm-link {text-decoration: underline;}
|
||||||
|
.cm-strikethrough {text-decoration: line-through;}
|
||||||
|
|
||||||
.cm-s-default .cm-keyword {color: #708;}
|
.cm-s-default .cm-keyword {color: #708;}
|
||||||
.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;}
|
||||||
@ -111,21 +123,14 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
|
|||||||
.cm-s-default .cm-bracket {color: #997;}
|
.cm-s-default .cm-bracket {color: #997;}
|
||||||
.cm-s-default .cm-tag {color: #170;}
|
.cm-s-default .cm-tag {color: #170;}
|
||||||
.cm-s-default .cm-attribute {color: #00c;}
|
.cm-s-default .cm-attribute {color: #00c;}
|
||||||
.cm-s-default .cm-header {color: blue;}
|
|
||||||
.cm-s-default .cm-quote {color: #090;}
|
|
||||||
.cm-s-default .cm-hr {color: #999;}
|
.cm-s-default .cm-hr {color: #999;}
|
||||||
.cm-s-default .cm-link {color: #00c;}
|
.cm-s-default .cm-link {color: #00c;}
|
||||||
|
|
||||||
.cm-negative {color: #d44;}
|
|
||||||
.cm-positive {color: #292;}
|
|
||||||
.cm-header, .cm-strong {font-weight: bold;}
|
|
||||||
.cm-em {font-style: italic;}
|
|
||||||
.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;}
|
||||||
|
|
||||||
|
.CodeMirror-composing { border-bottom: 2px solid; }
|
||||||
|
|
||||||
/* Default styles for common addons */
|
/* Default styles for common addons */
|
||||||
|
|
||||||
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
||||||
@ -139,11 +144,9 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
|||||||
the editor. You probably shouldn't touch them. */
|
the editor. You probably shouldn't touch them. */
|
||||||
|
|
||||||
.CodeMirror {
|
.CodeMirror {
|
||||||
line-height: 1;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: white;
|
background: white;
|
||||||
color: black;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror-scroll {
|
.CodeMirror-scroll {
|
||||||
@ -155,18 +158,14 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
outline: none; /* Prevent dragging from highlighting the element */
|
outline: none; /* Prevent dragging from highlighting the element */
|
||||||
position: relative;
|
position: relative;
|
||||||
-moz-box-sizing: content-box;
|
|
||||||
box-sizing: content-box;
|
|
||||||
}
|
}
|
||||||
.CodeMirror-sizer {
|
.CodeMirror-sizer {
|
||||||
position: relative;
|
position: relative;
|
||||||
border-right: 30px solid transparent;
|
border-right: 30px solid transparent;
|
||||||
-moz-box-sizing: content-box;
|
|
||||||
box-sizing: content-box;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||||
before actuall scrolling happens, thus preventing shaking and
|
before actual scrolling happens, thus preventing shaking and
|
||||||
flickering artifacts. */
|
flickering artifacts. */
|
||||||
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -192,14 +191,14 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
|||||||
|
|
||||||
.CodeMirror-gutters {
|
.CodeMirror-gutters {
|
||||||
position: absolute; left: 0; top: 0;
|
position: absolute; left: 0; top: 0;
|
||||||
|
min-height: 100%;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
.CodeMirror-gutter {
|
.CodeMirror-gutter {
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
-moz-box-sizing: content-box;
|
|
||||||
box-sizing: content-box;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
margin-bottom: -30px;
|
margin-bottom: -30px;
|
||||||
/* Hack to make IE7 behave */
|
/* Hack to make IE7 behave */
|
||||||
*zoom:1;
|
*zoom:1;
|
||||||
@ -208,13 +207,24 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
|||||||
.CodeMirror-gutter-wrapper {
|
.CodeMirror-gutter-wrapper {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
height: 100%;
|
background: none !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-background {
|
||||||
|
position: absolute;
|
||||||
|
top: 0; bottom: 0;
|
||||||
|
z-index: 4;
|
||||||
}
|
}
|
||||||
.CodeMirror-gutter-elt {
|
.CodeMirror-gutter-elt {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
}
|
}
|
||||||
|
.CodeMirror-gutter-wrapper {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
.CodeMirror-lines {
|
.CodeMirror-lines {
|
||||||
cursor: text;
|
cursor: text;
|
||||||
@ -235,6 +245,9 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
|||||||
z-index: 2;
|
z-index: 2;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
-webkit-font-variant-ligatures: none;
|
||||||
|
font-variant-ligatures: none;
|
||||||
}
|
}
|
||||||
.CodeMirror-wrap pre {
|
.CodeMirror-wrap pre {
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
@ -256,6 +269,20 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
|||||||
|
|
||||||
.CodeMirror-widget {}
|
.CodeMirror-widget {}
|
||||||
|
|
||||||
|
.CodeMirror-code {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force content-box sizing for the elements where we expect it */
|
||||||
|
.CodeMirror-scroll,
|
||||||
|
.CodeMirror-sizer,
|
||||||
|
.CodeMirror-gutter,
|
||||||
|
.CodeMirror-gutters,
|
||||||
|
.CodeMirror-linenumber {
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
.CodeMirror-measure {
|
.CodeMirror-measure {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -263,19 +290,19 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
.CodeMirror-measure pre { position: static; }
|
|
||||||
|
|
||||||
.CodeMirror div.CodeMirror-cursor {
|
.CodeMirror-cursor { position: absolute; }
|
||||||
position: absolute;
|
.CodeMirror-measure pre { position: static; }
|
||||||
border-right: none;
|
|
||||||
width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.CodeMirror-cursors {
|
div.CodeMirror-cursors {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
|
div.CodeMirror-dragcursors {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
.CodeMirror-focused div.CodeMirror-cursors {
|
.CodeMirror-focused div.CodeMirror-cursors {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
@ -283,6 +310,8 @@ 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; }
|
.CodeMirror-crosshair { cursor: crosshair; }
|
||||||
|
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
|
||||||
|
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
|
||||||
|
|
||||||
.cm-searching {
|
.cm-searching {
|
||||||
background: #ffa;
|
background: #ffa;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
if (typeof define === 'function' && define.amd) {
|
if (typeof define === 'function' && define.amd) {
|
||||||
define([
|
define([
|
||||||
'underscore', 'underscore.string', 'jquery', 'backbone', 'backform',
|
'underscore', 'underscore.string', 'jquery', 'backbone', 'backform',
|
||||||
'backgrid', 'codemirror', 'pgadmin.backgrid', 'codemirror/mode/sql',
|
'backgrid', 'codemirror', 'pgadmin.backgrid', 'codemirror/mode/sql/sql',
|
||||||
'select2'
|
'select2'
|
||||||
],
|
],
|
||||||
function(_, S, $, Backbone, Backform, Backgrid, CodeMirror) {
|
function(_, S, $, Backbone, Backform, Backgrid, CodeMirror) {
|
||||||
@ -1376,7 +1376,7 @@
|
|||||||
var sqlTab = CodeMirror.fromTextArea(
|
var sqlTab = CodeMirror.fromTextArea(
|
||||||
(this.$el.find("textarea")[0]), {
|
(this.$el.find("textarea")[0]), {
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
mode: "text/x-sql",
|
mode: "text/x-pgsql",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
});
|
});
|
||||||
this.sqlTab = sqlTab;
|
this.sqlTab = sqlTab;
|
||||||
|
@ -21,26 +21,40 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
CodeMirror.commands.toggleComment = function(cm) {
|
CodeMirror.commands.toggleComment = function(cm) {
|
||||||
var minLine = Infinity, ranges = cm.listSelections(), mode = null;
|
cm.toggleComment();
|
||||||
|
};
|
||||||
|
|
||||||
|
CodeMirror.defineExtension("toggleComment", function(options) {
|
||||||
|
if (!options) options = noOptions;
|
||||||
|
var cm = this;
|
||||||
|
var minLine = Infinity, ranges = this.listSelections(), mode = null;
|
||||||
for (var i = ranges.length - 1; i >= 0; i--) {
|
for (var i = ranges.length - 1; i >= 0; i--) {
|
||||||
var from = ranges[i].from(), to = ranges[i].to();
|
var from = ranges[i].from(), to = ranges[i].to();
|
||||||
if (from.line >= minLine) continue;
|
if (from.line >= minLine) continue;
|
||||||
if (to.line >= minLine) to = Pos(minLine, 0);
|
if (to.line >= minLine) to = Pos(minLine, 0);
|
||||||
minLine = from.line;
|
minLine = from.line;
|
||||||
if (mode == null) {
|
if (mode == null) {
|
||||||
if (cm.uncomment(from, to)) mode = "un";
|
if (cm.uncomment(from, to, options)) mode = "un";
|
||||||
else { cm.lineComment(from, to); mode = "line"; }
|
else { cm.lineComment(from, to, options); mode = "line"; }
|
||||||
} else if (mode == "un") {
|
} else if (mode == "un") {
|
||||||
cm.uncomment(from, to);
|
cm.uncomment(from, to, options);
|
||||||
} else {
|
} else {
|
||||||
cm.lineComment(from, to);
|
cm.lineComment(from, to, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
|
// Rough heuristic to try and detect lines that are part of multi-line string
|
||||||
|
function probablyInsideString(cm, pos, line) {
|
||||||
|
return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"`]/.test(line)
|
||||||
|
}
|
||||||
|
|
||||||
CodeMirror.defineExtension("lineComment", function(from, to, options) {
|
CodeMirror.defineExtension("lineComment", 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 firstLine = self.getLine(from.line);
|
||||||
|
if (firstLine == null || probablyInsideString(self, from, firstLine)) return;
|
||||||
|
|
||||||
var commentString = options.lineComment || mode.lineComment;
|
var commentString = options.lineComment || mode.lineComment;
|
||||||
if (!commentString) {
|
if (!commentString) {
|
||||||
if (options.blockCommentStart || mode.blockCommentStart) {
|
if (options.blockCommentStart || mode.blockCommentStart) {
|
||||||
@ -49,15 +63,21 @@
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var firstLine = self.getLine(from.line);
|
|
||||||
if (firstLine == null) return;
|
|
||||||
var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1);
|
var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1);
|
||||||
var pad = options.padding == null ? " " : options.padding;
|
var pad = options.padding == null ? " " : options.padding;
|
||||||
var blankLines = options.commentBlankLines || from.line == to.line;
|
var blankLines = options.commentBlankLines || from.line == to.line;
|
||||||
|
|
||||||
self.operation(function() {
|
self.operation(function() {
|
||||||
if (options.indent) {
|
if (options.indent) {
|
||||||
var baseString = firstLine.slice(0, firstNonWS(firstLine));
|
var baseString = null;
|
||||||
|
for (var i = from.line; i < end; ++i) {
|
||||||
|
var line = self.getLine(i);
|
||||||
|
var whitespace = line.slice(0, firstNonWS(line));
|
||||||
|
if (baseString == null || baseString.length > whitespace.length) {
|
||||||
|
baseString = whitespace;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (var i = from.line; i < end; ++i) {
|
for (var i = from.line; i < end; ++i) {
|
||||||
var line = self.getLine(i), cut = baseString.length;
|
var line = self.getLine(i), cut = baseString.length;
|
||||||
if (!blankLines && !nonWS.test(line)) continue;
|
if (!blankLines && !nonWS.test(line)) continue;
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
.CodeMirror-dialog {
|
.CodeMirror-dialog {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0; right: 0;
|
left: 0; right: 0;
|
||||||
background: white;
|
background: inherit;
|
||||||
z-index: 15;
|
z-index: 15;
|
||||||
padding: .1em .8em;
|
padding: .1em .8em;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: #333;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror-dialog-top {
|
.CodeMirror-dialog-top {
|
||||||
|
@ -56,9 +56,13 @@
|
|||||||
|
|
||||||
var inp = dialog.getElementsByTagName("input")[0], button;
|
var inp = dialog.getElementsByTagName("input")[0], button;
|
||||||
if (inp) {
|
if (inp) {
|
||||||
|
inp.focus();
|
||||||
|
|
||||||
if (options.value) {
|
if (options.value) {
|
||||||
inp.value = options.value;
|
inp.value = options.value;
|
||||||
inp.select();
|
if (options.selectValueOnOpen !== false) {
|
||||||
|
inp.select();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.onInput)
|
if (options.onInput)
|
||||||
@ -77,8 +81,6 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
|
if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
|
||||||
|
|
||||||
inp.focus();
|
|
||||||
} 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();
|
||||||
|
47
web/pgadmin/static/js/codemirror/addon/display/autorefresh.js
vendored
Normal file
47
web/pgadmin/static/js/codemirror/addon/display/autorefresh.js
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// 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("autoRefresh", false, function(cm, val) {
|
||||||
|
if (cm.state.autoRefresh) {
|
||||||
|
stopListening(cm, cm.state.autoRefresh)
|
||||||
|
cm.state.autoRefresh = null
|
||||||
|
}
|
||||||
|
if (val && cm.display.wrapper.offsetHeight == 0)
|
||||||
|
startListening(cm, cm.state.autoRefresh = {delay: val.delay || 250})
|
||||||
|
})
|
||||||
|
|
||||||
|
function startListening(cm, state) {
|
||||||
|
function check() {
|
||||||
|
if (cm.display.wrapper.offsetHeight) {
|
||||||
|
stopListening(cm, state)
|
||||||
|
if (cm.display.lastWrapHeight != cm.display.wrapper.clientHeight)
|
||||||
|
cm.refresh()
|
||||||
|
} else {
|
||||||
|
state.timeout = setTimeout(check, state.delay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.timeout = setTimeout(check, state.delay)
|
||||||
|
state.hurry = function() {
|
||||||
|
clearTimeout(state.timeout)
|
||||||
|
state.timeout = setTimeout(check, 50)
|
||||||
|
}
|
||||||
|
CodeMirror.on(window, "mouseup", state.hurry)
|
||||||
|
CodeMirror.on(window, "keyup", state.hurry)
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopListening(_cm, state) {
|
||||||
|
clearTimeout(state.timeout)
|
||||||
|
CodeMirror.off(window, "mouseup", state.hurry)
|
||||||
|
CodeMirror.off(window, "keyup", state.hurry)
|
||||||
|
}
|
||||||
|
});
|
@ -10,13 +10,31 @@
|
|||||||
mod(CodeMirror);
|
mod(CodeMirror);
|
||||||
})(function(CodeMirror) {
|
})(function(CodeMirror) {
|
||||||
CodeMirror.defineExtension("addPanel", function(node, options) {
|
CodeMirror.defineExtension("addPanel", function(node, options) {
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
if (!this.state.panels) initPanels(this);
|
if (!this.state.panels) initPanels(this);
|
||||||
|
|
||||||
var info = this.state.panels;
|
var info = this.state.panels;
|
||||||
if (options && options.position == "bottom")
|
var wrapper = info.wrapper;
|
||||||
info.wrapper.appendChild(node);
|
var cmWrapper = this.getWrapperElement();
|
||||||
else
|
|
||||||
info.wrapper.insertBefore(node, info.wrapper.firstChild);
|
if (options.after instanceof Panel && !options.after.cleared) {
|
||||||
|
wrapper.insertBefore(node, options.before.node.nextSibling);
|
||||||
|
} else if (options.before instanceof Panel && !options.before.cleared) {
|
||||||
|
wrapper.insertBefore(node, options.before.node);
|
||||||
|
} else if (options.replace instanceof Panel && !options.replace.cleared) {
|
||||||
|
wrapper.insertBefore(node, options.replace.node);
|
||||||
|
options.replace.clear();
|
||||||
|
} else if (options.position == "bottom") {
|
||||||
|
wrapper.appendChild(node);
|
||||||
|
} else if (options.position == "before-bottom") {
|
||||||
|
wrapper.insertBefore(node, cmWrapper.nextSibling);
|
||||||
|
} else if (options.position == "after-top") {
|
||||||
|
wrapper.insertBefore(node, cmWrapper);
|
||||||
|
} else {
|
||||||
|
wrapper.insertBefore(node, wrapper.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
var height = (options && options.height) || node.offsetHeight;
|
var height = (options && options.height) || node.offsetHeight;
|
||||||
this._setSize(null, info.heightLeft -= height);
|
this._setSize(null, info.heightLeft -= height);
|
||||||
info.panels++;
|
info.panels++;
|
||||||
|
@ -14,10 +14,12 @@
|
|||||||
if (val && !prev) {
|
if (val && !prev) {
|
||||||
cm.on("blur", onBlur);
|
cm.on("blur", onBlur);
|
||||||
cm.on("change", onChange);
|
cm.on("change", onChange);
|
||||||
|
cm.on("swapDoc", onChange);
|
||||||
onChange(cm);
|
onChange(cm);
|
||||||
} else if (!val && prev) {
|
} else if (!val && prev) {
|
||||||
cm.off("blur", onBlur);
|
cm.off("blur", onBlur);
|
||||||
cm.off("change", onChange);
|
cm.off("change", onChange);
|
||||||
|
cm.off("swapDoc", onChange);
|
||||||
clearPlaceholder(cm);
|
clearPlaceholder(cm);
|
||||||
var wrapper = cm.getWrapperElement();
|
var wrapper = cm.getWrapperElement();
|
||||||
wrapper.className = wrapper.className.replace(" CodeMirror-empty", "");
|
wrapper.className = wrapper.className.replace(" CodeMirror-empty", "");
|
||||||
@ -37,7 +39,9 @@
|
|||||||
var elt = cm.state.placeholder = document.createElement("pre");
|
var elt = cm.state.placeholder = document.createElement("pre");
|
||||||
elt.style.cssText = "height: 0; overflow: visible";
|
elt.style.cssText = "height: 0; overflow: visible";
|
||||||
elt.className = "CodeMirror-placeholder";
|
elt.className = "CodeMirror-placeholder";
|
||||||
elt.appendChild(document.createTextNode(cm.getOption("placeholder")));
|
var placeHolder = cm.getOption("placeholder")
|
||||||
|
if (typeof placeHolder == "string") placeHolder = document.createTextNode(placeHolder)
|
||||||
|
elt.appendChild(placeHolder)
|
||||||
cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
|
cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
for (var i = 0; i < val.length; i++) {
|
for (var i = 0; i < val.length; i++) {
|
||||||
var elt = document.createElement("div");
|
var elt = document.createElement("div");
|
||||||
elt.className = "CodeMirror-ruler";
|
elt.className = "CodeMirror-ruler";
|
||||||
var col, cls = null, conf = val[i];
|
var col, conf = val[i];
|
||||||
if (typeof conf == "number") {
|
if (typeof conf == "number") {
|
||||||
col = conf;
|
col = conf;
|
||||||
} else {
|
} else {
|
||||||
@ -47,7 +47,6 @@
|
|||||||
if (conf.color) elt.style.borderColor = conf.color;
|
if (conf.color) elt.style.borderColor = conf.color;
|
||||||
if (conf.lineStyle) elt.style.borderLeftStyle = conf.lineStyle;
|
if (conf.lineStyle) elt.style.borderLeftStyle = conf.lineStyle;
|
||||||
if (conf.width) elt.style.borderLeftWidth = conf.width;
|
if (conf.width) elt.style.borderLeftWidth = conf.width;
|
||||||
cls = val[i].className;
|
|
||||||
}
|
}
|
||||||
elt.style.left = (left + col * cw) + "px";
|
elt.style.left = (left + col * cw) + "px";
|
||||||
elt.style.top = "-50px";
|
elt.style.top = "-50px";
|
||||||
|
@ -9,27 +9,168 @@
|
|||||||
else // Plain browser env
|
else // Plain browser env
|
||||||
mod(CodeMirror);
|
mod(CodeMirror);
|
||||||
})(function(CodeMirror) {
|
})(function(CodeMirror) {
|
||||||
var DEFAULT_BRACKETS = "()[]{}''\"\"";
|
var defaults = {
|
||||||
var DEFAULT_EXPLODE_ON_ENTER = "[]{}";
|
pairs: "()[]{}''\"\"",
|
||||||
var SPACE_CHAR_REGEX = /\s/;
|
triples: "",
|
||||||
|
explode: "[]{}"
|
||||||
|
};
|
||||||
|
|
||||||
var Pos = CodeMirror.Pos;
|
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 && old != CodeMirror.Init) {
|
||||||
cm.removeKeyMap("autoCloseBrackets");
|
cm.removeKeyMap(keyMap);
|
||||||
if (!val) return;
|
cm.state.closeBrackets = null;
|
||||||
var pairs = DEFAULT_BRACKETS, explode = DEFAULT_EXPLODE_ON_ENTER;
|
}
|
||||||
if (typeof val == "string") pairs = val;
|
if (val) {
|
||||||
else if (typeof val == "object") {
|
cm.state.closeBrackets = val;
|
||||||
if (val.pairs != null) pairs = val.pairs;
|
cm.addKeyMap(keyMap);
|
||||||
if (val.explode != null) explode = val.explode;
|
|
||||||
}
|
}
|
||||||
var map = buildKeymap(pairs);
|
|
||||||
if (explode) map.Enter = buildExplodeHandler(explode);
|
|
||||||
cm.addKeyMap(map);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getOption(conf, name) {
|
||||||
|
if (name == "pairs" && typeof conf == "string") return conf;
|
||||||
|
if (typeof conf == "object" && conf[name] != null) return conf[name];
|
||||||
|
return defaults[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
var bind = defaults.pairs + "`";
|
||||||
|
var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
|
||||||
|
for (var i = 0; i < bind.length; i++)
|
||||||
|
keyMap["'" + bind.charAt(i) + "'"] = handler(bind.charAt(i));
|
||||||
|
|
||||||
|
function handler(ch) {
|
||||||
|
return function(cm) { return handleChar(cm, ch); };
|
||||||
|
}
|
||||||
|
|
||||||
|
function getConfig(cm) {
|
||||||
|
var deflt = cm.state.closeBrackets;
|
||||||
|
if (!deflt) return null;
|
||||||
|
var mode = cm.getModeAt(cm.getCursor());
|
||||||
|
return mode.closeBrackets || deflt;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBackspace(cm) {
|
||||||
|
var conf = getConfig(cm);
|
||||||
|
if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||||
|
|
||||||
|
var pairs = getOption(conf, "pairs");
|
||||||
|
var ranges = cm.listSelections();
|
||||||
|
for (var i = 0; i < ranges.length; i++) {
|
||||||
|
if (!ranges[i].empty()) return CodeMirror.Pass;
|
||||||
|
var around = charsAround(cm, ranges[i].head);
|
||||||
|
if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
|
||||||
|
}
|
||||||
|
for (var i = ranges.length - 1; i >= 0; i--) {
|
||||||
|
var cur = ranges[i].head;
|
||||||
|
cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1), "+delete");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleEnter(cm) {
|
||||||
|
var conf = getConfig(cm);
|
||||||
|
var explode = conf && getOption(conf, "explode");
|
||||||
|
if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||||
|
|
||||||
|
var ranges = cm.listSelections();
|
||||||
|
for (var i = 0; i < ranges.length; i++) {
|
||||||
|
if (!ranges[i].empty()) return CodeMirror.Pass;
|
||||||
|
var around = charsAround(cm, ranges[i].head);
|
||||||
|
if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
|
||||||
|
}
|
||||||
|
cm.operation(function() {
|
||||||
|
cm.replaceSelection("\n\n", null);
|
||||||
|
cm.execCommand("goCharLeft");
|
||||||
|
ranges = cm.listSelections();
|
||||||
|
for (var i = 0; i < ranges.length; i++) {
|
||||||
|
var line = ranges[i].head.line;
|
||||||
|
cm.indentLine(line, null, true);
|
||||||
|
cm.indentLine(line + 1, null, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function contractSelection(sel) {
|
||||||
|
var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
|
||||||
|
return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)),
|
||||||
|
head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))};
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleChar(cm, ch) {
|
||||||
|
var conf = getConfig(cm);
|
||||||
|
if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||||
|
|
||||||
|
var pairs = getOption(conf, "pairs");
|
||||||
|
var pos = pairs.indexOf(ch);
|
||||||
|
if (pos == -1) return CodeMirror.Pass;
|
||||||
|
var triples = getOption(conf, "triples");
|
||||||
|
|
||||||
|
var identical = pairs.charAt(pos + 1) == ch;
|
||||||
|
var ranges = cm.listSelections();
|
||||||
|
var opening = pos % 2 == 0;
|
||||||
|
|
||||||
|
var type, next;
|
||||||
|
for (var i = 0; i < ranges.length; i++) {
|
||||||
|
var range = ranges[i], cur = range.head, curType;
|
||||||
|
var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
|
||||||
|
if (opening && !range.empty()) {
|
||||||
|
curType = "surround";
|
||||||
|
} else if ((identical || !opening) && next == ch) {
|
||||||
|
if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch)
|
||||||
|
curType = "skipThree";
|
||||||
|
else
|
||||||
|
curType = "skip";
|
||||||
|
} else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
|
||||||
|
cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch &&
|
||||||
|
(cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != ch)) {
|
||||||
|
curType = "addFour";
|
||||||
|
} else if (identical) {
|
||||||
|
if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, ch)) curType = "both";
|
||||||
|
else return CodeMirror.Pass;
|
||||||
|
} else if (opening && (cm.getLine(cur.line).length == cur.ch ||
|
||||||
|
isClosingBracket(next, pairs) ||
|
||||||
|
/\s/.test(next))) {
|
||||||
|
curType = "both";
|
||||||
|
} else {
|
||||||
|
return CodeMirror.Pass;
|
||||||
|
}
|
||||||
|
if (!type) type = curType;
|
||||||
|
else if (type != curType) return CodeMirror.Pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
|
||||||
|
var right = pos % 2 ? ch : pairs.charAt(pos + 1);
|
||||||
|
cm.operation(function() {
|
||||||
|
if (type == "skip") {
|
||||||
|
cm.execCommand("goCharRight");
|
||||||
|
} else if (type == "skipThree") {
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
cm.execCommand("goCharRight");
|
||||||
|
} else if (type == "surround") {
|
||||||
|
var sels = cm.getSelections();
|
||||||
|
for (var i = 0; i < sels.length; i++)
|
||||||
|
sels[i] = left + sels[i] + right;
|
||||||
|
cm.replaceSelections(sels, "around");
|
||||||
|
sels = cm.listSelections().slice();
|
||||||
|
for (var i = 0; i < sels.length; i++)
|
||||||
|
sels[i] = contractSelection(sels[i]);
|
||||||
|
cm.setSelections(sels);
|
||||||
|
} else if (type == "both") {
|
||||||
|
cm.replaceSelection(left + right, null);
|
||||||
|
cm.triggerElectric(left + right);
|
||||||
|
cm.execCommand("goCharLeft");
|
||||||
|
} else if (type == "addFour") {
|
||||||
|
cm.replaceSelection(left + left + left + left, "before");
|
||||||
|
cm.execCommand("goCharRight");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function isClosingBracket(ch, pairs) {
|
||||||
|
var pos = pairs.lastIndexOf(ch);
|
||||||
|
return pos > -1 && pos % 2 == 1;
|
||||||
|
}
|
||||||
|
|
||||||
function charsAround(cm, pos) {
|
function charsAround(cm, pos) {
|
||||||
var str = cm.getRange(Pos(pos.line, pos.ch - 1),
|
var str = cm.getRange(Pos(pos.line, pos.ch - 1),
|
||||||
Pos(pos.line, pos.ch + 1));
|
Pos(pos.line, pos.ch + 1));
|
||||||
@ -51,109 +192,4 @@
|
|||||||
stream.start = stream.pos;
|
stream.start = stream.pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildKeymap(pairs) {
|
|
||||||
var map = {
|
|
||||||
name : "autoCloseBrackets",
|
|
||||||
Backspace: function(cm) {
|
|
||||||
if (cm.getOption("disableInput")) return CodeMirror.Pass;
|
|
||||||
var ranges = cm.listSelections();
|
|
||||||
for (var i = 0; i < ranges.length; i++) {
|
|
||||||
if (!ranges[i].empty()) return CodeMirror.Pass;
|
|
||||||
var around = charsAround(cm, ranges[i].head);
|
|
||||||
if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
|
|
||||||
}
|
|
||||||
for (var i = ranges.length - 1; i >= 0; i--) {
|
|
||||||
var cur = ranges[i].head;
|
|
||||||
cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var closingBrackets = "";
|
|
||||||
for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
|
|
||||||
closingBrackets += right;
|
|
||||||
map["'" + left + "'"] = function(cm) {
|
|
||||||
if (cm.getOption("disableInput")) return CodeMirror.Pass;
|
|
||||||
var ranges = cm.listSelections(), type, next;
|
|
||||||
for (var i = 0; i < ranges.length; i++) {
|
|
||||||
var range = ranges[i], cur = range.head, curType;
|
|
||||||
var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
|
|
||||||
if (!range.empty()) {
|
|
||||||
curType = "surround";
|
|
||||||
} else if (left == right && next == right) {
|
|
||||||
if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left)
|
|
||||||
curType = "skipThree";
|
|
||||||
else
|
|
||||||
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";
|
|
||||||
} else {
|
|
||||||
return CodeMirror.Pass;
|
|
||||||
}
|
|
||||||
if (!type) type = curType;
|
|
||||||
else if (type != curType) return CodeMirror.Pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
cm.operation(function() {
|
|
||||||
if (type == "skip") {
|
|
||||||
cm.execCommand("goCharRight");
|
|
||||||
} else if (type == "skipThree") {
|
|
||||||
for (var i = 0; i < 3; i++)
|
|
||||||
cm.execCommand("goCharRight");
|
|
||||||
} else if (type == "surround") {
|
|
||||||
var sels = cm.getSelections();
|
|
||||||
for (var i = 0; i < sels.length; i++)
|
|
||||||
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) {
|
|
||||||
var ranges = cm.listSelections();
|
|
||||||
for (var i = 0; i < ranges.length; i++) {
|
|
||||||
var range = ranges[i];
|
|
||||||
if (!range.empty() ||
|
|
||||||
cm.getRange(range.head, Pos(range.head.line, range.head.ch + 1)) != right)
|
|
||||||
return CodeMirror.Pass;
|
|
||||||
}
|
|
||||||
cm.execCommand("goCharRight");
|
|
||||||
};
|
|
||||||
})(pairs.charAt(i), pairs.charAt(i + 1));
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildExplodeHandler(pairs) {
|
|
||||||
return function(cm) {
|
|
||||||
if (cm.getOption("disableInput")) return CodeMirror.Pass;
|
|
||||||
var ranges = cm.listSelections();
|
|
||||||
for (var i = 0; i < ranges.length; i++) {
|
|
||||||
if (!ranges[i].empty()) return CodeMirror.Pass;
|
|
||||||
var around = charsAround(cm, ranges[i].head);
|
|
||||||
if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
|
|
||||||
}
|
|
||||||
cm.operation(function() {
|
|
||||||
cm.replaceSelection("\n\n", null);
|
|
||||||
cm.execCommand("goCharLeft");
|
|
||||||
ranges = cm.listSelections();
|
|
||||||
for (var i = 0; i < ranges.length; i++) {
|
|
||||||
var line = ranges[i].head.line;
|
|
||||||
cm.indentLine(line, null, true);
|
|
||||||
cm.indentLine(line + 1, null, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
@ -108,19 +108,22 @@
|
|||||||
// when completing in JS/CSS snippet in htmlmixed mode. Does not
|
// when completing in JS/CSS snippet in htmlmixed mode. Does not
|
||||||
// work for other XML embedded languages (there is no general
|
// work for other XML embedded languages (there is no general
|
||||||
// way to go from a mixed mode to its current XML state).
|
// way to go from a mixed mode to its current XML state).
|
||||||
|
var replacement;
|
||||||
if (inner.mode.name != "xml") {
|
if (inner.mode.name != "xml") {
|
||||||
if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript")
|
if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript")
|
||||||
replacements[i] = head + "script>";
|
replacement = head + "script";
|
||||||
else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css")
|
else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css")
|
||||||
replacements[i] = head + "style>";
|
replacement = head + "style";
|
||||||
else
|
else
|
||||||
return CodeMirror.Pass;
|
return CodeMirror.Pass;
|
||||||
} else {
|
} else {
|
||||||
if (!state.context || !state.context.tagName ||
|
if (!state.context || !state.context.tagName ||
|
||||||
closingTagExists(cm, state.context.tagName, pos, state))
|
closingTagExists(cm, state.context.tagName, pos, state))
|
||||||
return CodeMirror.Pass;
|
return CodeMirror.Pass;
|
||||||
replacements[i] = head + state.context.tagName + ">";
|
replacement = head + state.context.tagName;
|
||||||
}
|
}
|
||||||
|
if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">";
|
||||||
|
replacements[i] = replacement;
|
||||||
}
|
}
|
||||||
cm.replaceSelections(replacements);
|
cm.replaceSelections(replacements);
|
||||||
ranges = cm.listSelections();
|
ranges = cm.listSelections();
|
||||||
@ -131,7 +134,7 @@
|
|||||||
|
|
||||||
function autoCloseSlash(cm) {
|
function autoCloseSlash(cm) {
|
||||||
if (cm.getOption("disableInput")) return CodeMirror.Pass;
|
if (cm.getOption("disableInput")) return CodeMirror.Pass;
|
||||||
autoCloseCurrent(cm, true);
|
return autoCloseCurrent(cm, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeMirror.commands.closeTag = function(cm) { return autoCloseCurrent(cm); };
|
CodeMirror.commands.closeTag = function(cm) { return autoCloseCurrent(cm); };
|
||||||
|
@ -11,36 +11,36 @@
|
|||||||
})(function(CodeMirror) {
|
})(function(CodeMirror) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var listRE = /^(\s*)(>[> ]*|[*+-]\s|(\d+)\.)(\s*)/,
|
var listRE = /^(\s*)(>[> ]*|[*+-]\s|(\d+)([.)]))(\s*)/,
|
||||||
emptyListRE = /^(\s*)(>[> ]*|[*+-]|(\d+)\.)(\s*)$/,
|
emptyListRE = /^(\s*)(>[> ]*|[*+-]|(\d+)[.)])(\s*)$/,
|
||||||
unorderedListRE = /[*+-]\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;
|
||||||
var eolState = cm.getStateAfter(pos.line);
|
var eolState = cm.getStateAfter(pos.line);
|
||||||
var inList = eolState.list !== false;
|
var inList = eolState.list !== false;
|
||||||
var inQuote = eolState.quote !== false;
|
var inQuote = eolState.quote !== 0;
|
||||||
|
|
||||||
if (!ranges[i].empty() || (!inList && !inQuote) || !(match = cm.getLine(pos.line).match(listRE))) {
|
var line = cm.getLine(pos.line), match = listRE.exec(line);
|
||||||
|
if (!ranges[i].empty() || (!inList && !inQuote) || !match) {
|
||||||
cm.execCommand("newlineAndIndent");
|
cm.execCommand("newlineAndIndent");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cm.getLine(pos.line).match(emptyListRE)) {
|
if (emptyListRE.test(line)) {
|
||||||
cm.replaceRange("", {
|
cm.replaceRange("", {
|
||||||
line: pos.line, ch: 0
|
line: pos.line, ch: 0
|
||||||
}, {
|
}, {
|
||||||
line: pos.line, ch: pos.ch + 1
|
line: pos.line, ch: pos.ch + 1
|
||||||
});
|
});
|
||||||
replacements[i] = "\n";
|
replacements[i] = "\n";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
var indent = match[1], after = match[4];
|
var indent = match[1], after = match[5];
|
||||||
var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0
|
var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0
|
||||||
? match[2]
|
? match[2]
|
||||||
: (parseInt(match[3], 10) + 1) + ".";
|
: (parseInt(match[3], 10) + 1) + match[4];
|
||||||
|
|
||||||
replacements[i] = "\n" + indent + bullet + after;
|
replacements[i] = "\n" + indent + bullet + after;
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@
|
|||||||
if (marks.length) {
|
if (marks.length) {
|
||||||
// Kludge to work around the IE bug from issue #1193, where text
|
// Kludge to work around the IE bug from issue #1193, where text
|
||||||
// input stops going to the textare whever this fires.
|
// input stops going to the textare whever this fires.
|
||||||
if (ie_lt8 && cm.state.focused) cm.display.input.focus();
|
if (ie_lt8 && cm.state.focused) cm.focus();
|
||||||
|
|
||||||
var clear = function() {
|
var clear = function() {
|
||||||
cm.operation(function() {
|
cm.operation(function() {
|
||||||
|
@ -28,7 +28,9 @@ CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (pass == 1 && found < start.ch) return;
|
if (pass == 1 && found < start.ch) return;
|
||||||
if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1)))) {
|
if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1))) &&
|
||||||
|
(lineText.slice(found - endToken.length, found) == endToken ||
|
||||||
|
!/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found))))) {
|
||||||
startCh = found + startToken.length;
|
startCh = found + startToken.length;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
cm.off("viewportChange", onViewportChange);
|
cm.off("viewportChange", onViewportChange);
|
||||||
cm.off("fold", onFold);
|
cm.off("fold", onFold);
|
||||||
cm.off("unfold", onFold);
|
cm.off("unfold", onFold);
|
||||||
cm.off("swapDoc", updateInViewport);
|
cm.off("swapDoc", onChange);
|
||||||
}
|
}
|
||||||
if (val) {
|
if (val) {
|
||||||
cm.state.foldGutter = new State(parseOptions(val));
|
cm.state.foldGutter = new State(parseOptions(val));
|
||||||
@ -30,7 +30,7 @@
|
|||||||
cm.on("viewportChange", onViewportChange);
|
cm.on("viewportChange", onViewportChange);
|
||||||
cm.on("fold", onFold);
|
cm.on("fold", onFold);
|
||||||
cm.on("unfold", onFold);
|
cm.on("unfold", onFold);
|
||||||
cm.on("swapDoc", updateInViewport);
|
cm.on("swapDoc", onChange);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -52,7 +52,7 @@
|
|||||||
function isFolded(cm, line) {
|
function isFolded(cm, line) {
|
||||||
var marks = cm.findMarksAt(Pos(line));
|
var marks = cm.findMarksAt(Pos(line));
|
||||||
for (var i = 0; i < marks.length; ++i)
|
for (var i = 0; i < marks.length; ++i)
|
||||||
if (marks[i].__isFold && marks[i].find().from.line == line) return true;
|
if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
function marker(spec) {
|
function marker(spec) {
|
||||||
@ -94,20 +94,28 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onGutterClick(cm, line, gutter) {
|
function onGutterClick(cm, line, gutter) {
|
||||||
var opts = cm.state.foldGutter.options;
|
var state = cm.state.foldGutter;
|
||||||
|
if (!state) return;
|
||||||
|
var opts = state.options;
|
||||||
if (gutter != opts.gutter) return;
|
if (gutter != opts.gutter) return;
|
||||||
cm.foldCode(Pos(line, 0), opts.rangeFinder);
|
var folded = isFolded(cm, line);
|
||||||
|
if (folded) folded.clear();
|
||||||
|
else cm.foldCode(Pos(line, 0), opts.rangeFinder);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onChange(cm) {
|
function onChange(cm) {
|
||||||
var state = cm.state.foldGutter, opts = cm.state.foldGutter.options;
|
var state = cm.state.foldGutter;
|
||||||
|
if (!state) return;
|
||||||
|
var opts = state.options;
|
||||||
state.from = state.to = 0;
|
state.from = state.to = 0;
|
||||||
clearTimeout(state.changeUpdate);
|
clearTimeout(state.changeUpdate);
|
||||||
state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600);
|
state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onViewportChange(cm) {
|
function onViewportChange(cm) {
|
||||||
var state = cm.state.foldGutter, opts = cm.state.foldGutter.options;
|
var state = cm.state.foldGutter;
|
||||||
|
if (!state) return;
|
||||||
|
var opts = state.options;
|
||||||
clearTimeout(state.changeUpdate);
|
clearTimeout(state.changeUpdate);
|
||||||
state.changeUpdate = setTimeout(function() {
|
state.changeUpdate = setTimeout(function() {
|
||||||
var vp = cm.getViewport();
|
var vp = cm.getViewport();
|
||||||
@ -129,7 +137,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onFold(cm, from) {
|
function onFold(cm, from) {
|
||||||
var state = cm.state.foldGutter, line = from.line;
|
var state = cm.state.foldGutter;
|
||||||
|
if (!state) return;
|
||||||
|
var line = from.line;
|
||||||
if (line >= state.from && line < state.to)
|
if (line >= state.from && line < state.to)
|
||||||
updateFoldInfo(cm, line, line + 1);
|
updateFoldInfo(cm, line, line + 1);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
while (start && word.test(curLine.charAt(start - 1))) --start;
|
while (start && word.test(curLine.charAt(start - 1))) --start;
|
||||||
var curWord = start != end && curLine.slice(start, end);
|
var curWord = start != end && curLine.slice(start, end);
|
||||||
|
|
||||||
var list = [], seen = {};
|
var list = options && options.list || [], seen = {};
|
||||||
var re = new RegExp(word.source, "g");
|
var re = new RegExp(word.source, "g");
|
||||||
for (var dir = -1; dir <= 1; dir += 2) {
|
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;
|
var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
|
||||||
|
@ -20,6 +20,10 @@
|
|||||||
var inner = CodeMirror.innerMode(cm.getMode(), token.state);
|
var inner = CodeMirror.innerMode(cm.getMode(), token.state);
|
||||||
if (inner.mode.name != "css") return;
|
if (inner.mode.name != "css") return;
|
||||||
|
|
||||||
|
if (token.type == "keyword" && "!important".indexOf(token.string) == 0)
|
||||||
|
return {list: ["!important"], from: CodeMirror.Pos(cur.line, token.start),
|
||||||
|
to: CodeMirror.Pos(cur.line, token.end)};
|
||||||
|
|
||||||
var start = token.start, end = cur.ch, word = token.string.slice(0, end - start);
|
var start = token.start, end = cur.ch, word = token.string.slice(0, end - start);
|
||||||
if (/[^\w$_-]/.test(word)) {
|
if (/[^\w$_-]/.test(word)) {
|
||||||
word = ""; start = end = cur.ch;
|
word = ""; start = end = cur.ch;
|
||||||
|
@ -25,34 +25,54 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
CodeMirror.defineExtension("showHint", function(options) {
|
CodeMirror.defineExtension("showHint", function(options) {
|
||||||
// We want a single cursor position.
|
options = parseOptions(this, this.getCursor("start"), options);
|
||||||
if (this.listSelections().length > 1 || this.somethingSelected()) return;
|
var selections = this.listSelections()
|
||||||
|
if (selections.length > 1) return;
|
||||||
|
// By default, don't allow completion when something is selected.
|
||||||
|
// A hint function can have a `supportsSelection` property to
|
||||||
|
// indicate that it can handle selections.
|
||||||
|
if (this.somethingSelected()) {
|
||||||
|
if (!options.hint.supportsSelection) return;
|
||||||
|
// Don't try with cross-line selections
|
||||||
|
for (var i = 0; i < selections.length; i++)
|
||||||
|
if (selections[i].head.line != selections[i].anchor.line) return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.state.completionActive) this.state.completionActive.close();
|
if (this.state.completionActive) this.state.completionActive.close();
|
||||||
var completion = this.state.completionActive = new Completion(this, options);
|
var completion = this.state.completionActive = new Completion(this, options);
|
||||||
var getHints = completion.options.hint;
|
if (!completion.options.hint) return;
|
||||||
if (!getHints) return;
|
|
||||||
|
|
||||||
CodeMirror.signal(this, "startCompletion", this);
|
CodeMirror.signal(this, "startCompletion", this);
|
||||||
if (getHints.async)
|
completion.update(true);
|
||||||
getHints(this, function(hints) { completion.showHints(hints); }, completion.options);
|
|
||||||
else
|
|
||||||
return completion.showHints(getHints(this, completion.options));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function Completion(cm, options) {
|
function Completion(cm, options) {
|
||||||
this.cm = cm;
|
this.cm = cm;
|
||||||
this.options = this.buildOptions(options);
|
this.options = options;
|
||||||
this.widget = this.onClose = null;
|
this.widget = null;
|
||||||
|
this.debounce = 0;
|
||||||
|
this.tick = 0;
|
||||||
|
this.startPos = this.cm.getCursor("start");
|
||||||
|
this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
|
||||||
|
return setTimeout(fn, 1000/60);
|
||||||
|
};
|
||||||
|
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
|
||||||
|
|
||||||
Completion.prototype = {
|
Completion.prototype = {
|
||||||
close: function() {
|
close: function() {
|
||||||
if (!this.active()) return;
|
if (!this.active()) return;
|
||||||
this.cm.state.completionActive = null;
|
this.cm.state.completionActive = null;
|
||||||
|
this.tick = null;
|
||||||
|
this.cm.off("cursorActivity", this.activityFunc);
|
||||||
|
|
||||||
|
if (this.widget && this.data) CodeMirror.signal(this.data, "close");
|
||||||
if (this.widget) this.widget.close();
|
if (this.widget) this.widget.close();
|
||||||
if (this.onClose) this.onClose();
|
|
||||||
CodeMirror.signal(this.cm, "endCompletion", this.cm);
|
CodeMirror.signal(this.cm, "endCompletion", this.cm);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -69,88 +89,69 @@
|
|||||||
this.close();
|
this.close();
|
||||||
},
|
},
|
||||||
|
|
||||||
showHints: function(data) {
|
cursorActivity: function() {
|
||||||
if (!data || !data.list.length || !this.active()) return this.close();
|
if (this.debounce) {
|
||||||
|
cancelAnimationFrame(this.debounce);
|
||||||
|
this.debounce = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.options.completeSingle && data.list.length == 1)
|
var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
|
||||||
this.pick(data, 0);
|
if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
|
||||||
else
|
pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
|
||||||
this.showWidget(data);
|
(pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
|
||||||
|
this.close();
|
||||||
|
} else {
|
||||||
|
var self = this;
|
||||||
|
this.debounce = requestAnimationFrame(function() {self.update();});
|
||||||
|
if (this.widget) this.widget.disable();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
showWidget: function(data) {
|
update: function(first) {
|
||||||
this.widget = new Widget(this, data);
|
if (this.tick == null) return
|
||||||
CodeMirror.signal(data, "shown");
|
var self = this, myTick = ++this.tick
|
||||||
|
fetchHints(this.options.hint, this.cm, this.options, function(data) {
|
||||||
|
if (self.tick == myTick) self.finishUpdate(data, first)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
var debounce = 0, completion = this, finished;
|
finishUpdate: function(data, first) {
|
||||||
var closeOn = this.options.closeCharacters;
|
if (this.data) CodeMirror.signal(this.data, "update");
|
||||||
var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length;
|
|
||||||
|
|
||||||
var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
|
var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
|
||||||
return setTimeout(fn, 1000/60);
|
if (this.widget) this.widget.close();
|
||||||
};
|
|
||||||
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
|
|
||||||
|
|
||||||
function done() {
|
if (data && this.data && isNewCompletion(this.data, data)) return;
|
||||||
if (finished) return;
|
this.data = data;
|
||||||
finished = true;
|
|
||||||
completion.close();
|
|
||||||
completion.cm.off("cursorActivity", activity);
|
|
||||||
if (data) CodeMirror.signal(data, "close");
|
|
||||||
}
|
|
||||||
|
|
||||||
function update() {
|
if (data && data.list.length) {
|
||||||
if (finished) return;
|
if (picked && data.list.length == 1) {
|
||||||
CodeMirror.signal(data, "update");
|
this.pick(data, 0);
|
||||||
var getHints = completion.options.hint;
|
|
||||||
if (getHints.async)
|
|
||||||
getHints(completion.cm, finishUpdate, completion.options);
|
|
||||||
else
|
|
||||||
finishUpdate(getHints(completion.cm, completion.options));
|
|
||||||
}
|
|
||||||
function finishUpdate(data_) {
|
|
||||||
data = data_;
|
|
||||||
if (finished) return;
|
|
||||||
if (!data || !data.list.length) return done();
|
|
||||||
if (completion.widget) completion.widget.close();
|
|
||||||
completion.widget = new Widget(completion, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearDebounce() {
|
|
||||||
if (debounce) {
|
|
||||||
cancelAnimationFrame(debounce);
|
|
||||||
debounce = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function activity() {
|
|
||||||
clearDebounce();
|
|
||||||
var pos = completion.cm.getCursor(), line = completion.cm.getLine(pos.line);
|
|
||||||
if (pos.line != startPos.line || line.length - pos.ch != startLen - startPos.ch ||
|
|
||||||
pos.ch < startPos.ch || completion.cm.somethingSelected() ||
|
|
||||||
(pos.ch && closeOn.test(line.charAt(pos.ch - 1)))) {
|
|
||||||
completion.close();
|
|
||||||
} else {
|
} else {
|
||||||
debounce = requestAnimationFrame(update);
|
this.widget = new Widget(this, data);
|
||||||
if (completion.widget) completion.widget.close();
|
CodeMirror.signal(data, "shown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.cm.on("cursorActivity", activity);
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function isNewCompletion(old, nw) {
|
||||||
|
var moved = CodeMirror.cmpPos(nw.from, old.from)
|
||||||
|
return moved > 0 && old.to.ch - old.from.ch != nw.to.ch - nw.from.ch
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseOptions(cm, pos, options) {
|
||||||
|
var editor = 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];
|
||||||
|
if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
function getText(completion) {
|
function getText(completion) {
|
||||||
if (typeof completion == "string") return completion;
|
if (typeof completion == "string") return completion;
|
||||||
else return completion.text;
|
else return completion.text;
|
||||||
@ -201,6 +202,7 @@
|
|||||||
function Widget(completion, data) {
|
function Widget(completion, data) {
|
||||||
this.completion = completion;
|
this.completion = completion;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
this.picked = false;
|
||||||
var widget = this, cm = completion.cm;
|
var widget = this, cm = completion.cm;
|
||||||
|
|
||||||
var hints = this.hints = document.createElement("ul");
|
var hints = this.hints = document.createElement("ul");
|
||||||
@ -315,6 +317,13 @@
|
|||||||
cm.off("scroll", this.onScroll);
|
cm.off("scroll", this.onScroll);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
disable: function() {
|
||||||
|
this.completion.cm.removeKeyMap(this.keyMap);
|
||||||
|
var widget = this;
|
||||||
|
this.keyMap = {Enter: function() { widget.picked = true; }};
|
||||||
|
this.completion.cm.addKeyMap(this.keyMap);
|
||||||
|
},
|
||||||
|
|
||||||
pick: function() {
|
pick: function() {
|
||||||
this.completion.pick(this.data, this.selectedHint);
|
this.completion.pick(this.data, this.selectedHint);
|
||||||
},
|
},
|
||||||
@ -341,34 +350,70 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CodeMirror.registerHelper("hint", "auto", function(cm, options) {
|
function applicableHelpers(cm, helpers) {
|
||||||
var helpers = cm.getHelpers(cm.getCursor(), "hint"), words;
|
if (!cm.somethingSelected()) return helpers
|
||||||
if (helpers.length) {
|
var result = []
|
||||||
for (var i = 0; i < helpers.length; i++) {
|
for (var i = 0; i < helpers.length; i++)
|
||||||
var cur = helpers[i](cm, options);
|
if (helpers[i].supportsSelection) result.push(helpers[i])
|
||||||
if (cur && cur.list.length) return cur;
|
return result
|
||||||
}
|
}
|
||||||
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
|
|
||||||
if (words) return CodeMirror.hint.fromList(cm, {words: words});
|
function fetchHints(hint, cm, options, callback) {
|
||||||
} else if (CodeMirror.hint.anyword) {
|
if (hint.async) {
|
||||||
return CodeMirror.hint.anyword(cm, options);
|
hint(cm, callback, options)
|
||||||
|
} else {
|
||||||
|
var result = hint(cm, options)
|
||||||
|
if (result && result.then) result.then(callback)
|
||||||
|
else callback(result)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveAutoHints(cm, pos) {
|
||||||
|
var helpers = cm.getHelpers(pos, "hint"), words
|
||||||
|
if (helpers.length) {
|
||||||
|
var resolved = function(cm, callback, options) {
|
||||||
|
var app = applicableHelpers(cm, helpers);
|
||||||
|
function run(i) {
|
||||||
|
if (i == app.length) return callback(null)
|
||||||
|
fetchHints(app[i], cm, options, function(result) {
|
||||||
|
if (result && result.list.length > 0) callback(result)
|
||||||
|
else run(i + 1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
run(0)
|
||||||
|
}
|
||||||
|
resolved.async = true
|
||||||
|
resolved.supportsSelection = true
|
||||||
|
return resolved
|
||||||
|
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
|
||||||
|
return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
|
||||||
|
} else if (CodeMirror.hint.anyword) {
|
||||||
|
return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
|
||||||
|
} else {
|
||||||
|
return function() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeMirror.registerHelper("hint", "auto", {
|
||||||
|
resolve: resolveAutoHints
|
||||||
});
|
});
|
||||||
|
|
||||||
CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
|
CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
|
||||||
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
|
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
|
||||||
|
var to = CodeMirror.Pos(cur.line, token.end);
|
||||||
|
if (token.string && /\w/.test(token.string[token.string.length - 1])) {
|
||||||
|
var term = token.string, from = CodeMirror.Pos(cur.line, token.start);
|
||||||
|
} else {
|
||||||
|
var term = "", from = to;
|
||||||
|
}
|
||||||
var found = [];
|
var found = [];
|
||||||
for (var i = 0; i < options.words.length; i++) {
|
for (var i = 0; i < options.words.length; i++) {
|
||||||
var word = options.words[i];
|
var word = options.words[i];
|
||||||
if (word.slice(0, token.string.length) == token.string)
|
if (word.slice(0, term.length) == term)
|
||||||
found.push(word);
|
found.push(word);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found.length) return {
|
if (found.length) return {list: found, from: from, to: to};
|
||||||
list: found,
|
|
||||||
from: CodeMirror.Pos(cur.line, token.start),
|
|
||||||
to: CodeMirror.Pos(cur.line, token.end)
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
CodeMirror.commands.autocomplete = CodeMirror.showHint;
|
CodeMirror.commands.autocomplete = CodeMirror.showHint;
|
||||||
@ -379,7 +424,7 @@
|
|||||||
alignWithWord: true,
|
alignWithWord: true,
|
||||||
closeCharacters: /[\s()\[\]{};:>,]/,
|
closeCharacters: /[\s()\[\]{};:>,]/,
|
||||||
closeOnUnfocus: true,
|
closeOnUnfocus: true,
|
||||||
completeOnSingleClick: false,
|
completeOnSingleClick: true,
|
||||||
container: null,
|
container: null,
|
||||||
customKeys: null,
|
customKeys: null,
|
||||||
extraKeys: null
|
extraKeys: null
|
||||||
|
@ -20,77 +20,153 @@
|
|||||||
};
|
};
|
||||||
var Pos = CodeMirror.Pos;
|
var Pos = CodeMirror.Pos;
|
||||||
|
|
||||||
|
function isArray(val) { return Object.prototype.toString.call(val) == "[object Array]" }
|
||||||
|
|
||||||
function getKeywords(editor) {
|
function getKeywords(editor) {
|
||||||
var mode = editor.doc.modeOption;
|
var mode = editor.doc.modeOption;
|
||||||
if (mode === "sql") mode = "text/x-sql";
|
if (mode === "sql") mode = "text/x-sql";
|
||||||
return CodeMirror.resolveMode(mode).keywords;
|
return CodeMirror.resolveMode(mode).keywords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getText(item) {
|
||||||
|
return typeof item == "string" ? item : item.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapTable(name, value) {
|
||||||
|
if (isArray(value)) value = {columns: value}
|
||||||
|
if (!value.text) value.text = name
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseTables(input) {
|
||||||
|
var result = {}
|
||||||
|
if (isArray(input)) {
|
||||||
|
for (var i = input.length - 1; i >= 0; i--) {
|
||||||
|
var item = input[i]
|
||||||
|
result[getText(item).toUpperCase()] = wrapTable(getText(item), item)
|
||||||
|
}
|
||||||
|
} else if (input) {
|
||||||
|
for (var name in input)
|
||||||
|
result[name.toUpperCase()] = wrapTable(name, input[name])
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTable(name) {
|
||||||
|
return tables[name.toUpperCase()]
|
||||||
|
}
|
||||||
|
|
||||||
|
function shallowClone(object) {
|
||||||
|
var result = {};
|
||||||
|
for (var key in object) if (object.hasOwnProperty(key))
|
||||||
|
result[key] = object[key];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function match(string, word) {
|
function match(string, word) {
|
||||||
var len = string.length;
|
var len = string.length;
|
||||||
var sub = word.substr(0, len);
|
var sub = getText(word).substr(0, len);
|
||||||
return string.toUpperCase() === sub.toUpperCase();
|
return string.toUpperCase() === sub.toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function addMatches(result, search, wordlist, formatter) {
|
function addMatches(result, search, wordlist, formatter) {
|
||||||
for (var word in wordlist) {
|
if (isArray(wordlist)) {
|
||||||
if (!wordlist.hasOwnProperty(word)) continue;
|
for (var i = 0; i < wordlist.length; i++)
|
||||||
if (Array.isArray(wordlist)) {
|
if (match(search, wordlist[i])) result.push(formatter(wordlist[i]))
|
||||||
word = wordlist[word];
|
} else {
|
||||||
}
|
for (var word in wordlist) if (wordlist.hasOwnProperty(word)) {
|
||||||
if (match(search, word)) {
|
var val = wordlist[word]
|
||||||
result.push(formatter(word));
|
if (!val || val === true)
|
||||||
|
val = word
|
||||||
|
else
|
||||||
|
val = val.displayText ? {text: val.text, displayText: val.displayText} : val.text
|
||||||
|
if (match(search, val)) result.push(formatter(val))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function nameCompletion(cur, token, result, editor) {
|
function cleanName(name) {
|
||||||
var useBacktick = (token.string.charAt(0) == "`");
|
// Get rid name from backticks(`) and preceding dot(.)
|
||||||
var string = token.string.substr(1);
|
if (name.charAt(0) == ".") {
|
||||||
var prevToken = editor.getTokenAt(Pos(cur.line, token.start));
|
name = name.substr(1);
|
||||||
if (token.string.charAt(0) == "." || prevToken.string == "."){
|
}
|
||||||
//Suggest colunm names
|
return name.replace(/`/g, "");
|
||||||
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) {
|
function insertBackticks(name) {
|
||||||
addMatches(result, string, columns, function(w) {return "`" + w + "`";});
|
var nameParts = getText(name).split(".");
|
||||||
}
|
for (var i = 0; i < nameParts.length; i++)
|
||||||
else if(useBacktickTable) {
|
nameParts[i] = "`" + nameParts[i] + "`";
|
||||||
addMatches(result, string, columns, function(w) {return ".`" + w + "`";});
|
var escaped = nameParts.join(".");
|
||||||
}
|
if (typeof name == "string") return escaped;
|
||||||
else {
|
name = shallowClone(name);
|
||||||
addMatches(result, string, columns, function(w) {return "." + w;});
|
name.text = escaped;
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function nameCompletion(cur, token, result, editor) {
|
||||||
|
// Try to complete table, column names and return start position of completion
|
||||||
|
var useBacktick = false;
|
||||||
|
var nameParts = [];
|
||||||
|
var start = token.start;
|
||||||
|
var cont = true;
|
||||||
|
while (cont) {
|
||||||
|
cont = (token.string.charAt(0) == ".");
|
||||||
|
useBacktick = useBacktick || (token.string.charAt(0) == "`");
|
||||||
|
|
||||||
|
start = token.start;
|
||||||
|
nameParts.unshift(cleanName(token.string));
|
||||||
|
|
||||||
|
token = editor.getTokenAt(Pos(cur.line, token.start));
|
||||||
|
if (token.string == ".") {
|
||||||
|
cont = true;
|
||||||
|
token = editor.getTokenAt(Pos(cur.line, token.start));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
//Suggest table names or colums in defaultTable
|
// Try to complete table names
|
||||||
while (token.start && string.charAt(0) == ".") {
|
var string = nameParts.join(".");
|
||||||
token = editor.getTokenAt(Pos(cur.line, token.start - 1));
|
addMatches(result, string, tables, function(w) {
|
||||||
string = token.string + string;
|
return useBacktick ? insertBackticks(w) : w;
|
||||||
}
|
});
|
||||||
if (useBacktick) {
|
|
||||||
addMatches(result, string, tables, function(w) {return "`" + w + "`";});
|
// Try to complete columns from defaultTable
|
||||||
addMatches(result, string, defaultTable, function(w) {return "`" + w + "`";});
|
addMatches(result, string, defaultTable, function(w) {
|
||||||
}
|
return useBacktick ? insertBackticks(w) : w;
|
||||||
else {
|
});
|
||||||
addMatches(result, string, tables, function(w) {return w;});
|
|
||||||
addMatches(result, string, defaultTable, function(w) {return w;});
|
// Try to complete columns
|
||||||
}
|
string = nameParts.pop();
|
||||||
|
var table = nameParts.join(".");
|
||||||
|
|
||||||
|
var alias = false;
|
||||||
|
var aliasTable = table;
|
||||||
|
// Check if table is available. If not, find table by Alias
|
||||||
|
if (!getTable(table)) {
|
||||||
|
var oldTable = table;
|
||||||
|
table = findTableByAlias(table, editor);
|
||||||
|
if (table !== oldTable) alias = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var columns = getTable(table);
|
||||||
|
if (columns && columns.columns)
|
||||||
|
columns = columns.columns;
|
||||||
|
|
||||||
|
if (columns) {
|
||||||
|
addMatches(result, string, columns, function(w) {
|
||||||
|
var tableInsert = table;
|
||||||
|
if (alias == true) tableInsert = aliasTable;
|
||||||
|
if (typeof w == "string") {
|
||||||
|
w = tableInsert + "." + w;
|
||||||
|
} else {
|
||||||
|
w = shallowClone(w);
|
||||||
|
w.text = tableInsert + "." + w.text;
|
||||||
|
}
|
||||||
|
return useBacktick ? insertBackticks(w) : w;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
function eachWord(lineText, f) {
|
function eachWord(lineText, f) {
|
||||||
@ -135,7 +211,7 @@
|
|||||||
//find valid range
|
//find valid range
|
||||||
var prevItem = 0;
|
var prevItem = 0;
|
||||||
var current = convertCurToNumber(editor.getCursor());
|
var current = convertCurToNumber(editor.getCursor());
|
||||||
for (var i=0; i< separator.length; i++) {
|
for (var i = 0; i < separator.length; i++) {
|
||||||
var _v = convertCurToNumber(separator[i]);
|
var _v = convertCurToNumber(separator[i]);
|
||||||
if (current > prevItem && current <= _v) {
|
if (current > prevItem && current <= _v) {
|
||||||
validRange = { start: convertNumberToCur(prevItem), end: convertNumberToCur(_v) };
|
validRange = { start: convertNumberToCur(prevItem), end: convertNumberToCur(_v) };
|
||||||
@ -150,12 +226,10 @@
|
|||||||
var lineText = query[i];
|
var lineText = query[i];
|
||||||
eachWord(lineText, function(word) {
|
eachWord(lineText, function(word) {
|
||||||
var wordUpperCase = word.toUpperCase();
|
var wordUpperCase = word.toUpperCase();
|
||||||
if (wordUpperCase === aliasUpperCase && tables.hasOwnProperty(previousWord)) {
|
if (wordUpperCase === aliasUpperCase && getTable(previousWord))
|
||||||
table = previousWord;
|
table = previousWord;
|
||||||
}
|
if (wordUpperCase !== CONS.ALIAS_KEYWORD)
|
||||||
if (wordUpperCase !== CONS.ALIAS_KEYWORD) {
|
|
||||||
previousWord = word;
|
previousWord = word;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
if (table) break;
|
if (table) break;
|
||||||
}
|
}
|
||||||
@ -163,11 +237,20 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
CodeMirror.registerHelper("hint", "sql", function(editor, options) {
|
CodeMirror.registerHelper("hint", "sql", function(editor, options) {
|
||||||
tables = (options && options.tables) || {};
|
tables = parseTables(options && options.tables)
|
||||||
var defaultTableName = options && options.defaultTable;
|
var defaultTableName = options && options.defaultTable;
|
||||||
defaultTable = (defaultTableName && tables[defaultTableName] || []);
|
var disableKeywords = options && options.disableKeywords;
|
||||||
|
defaultTable = defaultTableName && getTable(defaultTableName);
|
||||||
keywords = keywords || getKeywords(editor);
|
keywords = keywords || getKeywords(editor);
|
||||||
|
|
||||||
|
if (defaultTableName && !defaultTable)
|
||||||
|
defaultTable = findTableByAlias(defaultTableName, editor);
|
||||||
|
|
||||||
|
defaultTable = defaultTable || [];
|
||||||
|
|
||||||
|
if (defaultTable.columns)
|
||||||
|
defaultTable = defaultTable.columns;
|
||||||
|
|
||||||
var cur = editor.getCursor();
|
var cur = editor.getCursor();
|
||||||
var result = [];
|
var result = [];
|
||||||
var token = editor.getTokenAt(cur), start, end, search;
|
var token = editor.getTokenAt(cur), start, end, search;
|
||||||
@ -185,11 +268,12 @@
|
|||||||
search = "";
|
search = "";
|
||||||
}
|
}
|
||||||
if (search.charAt(0) == "." || search.charAt(0) == "`") {
|
if (search.charAt(0) == "." || search.charAt(0) == "`") {
|
||||||
nameCompletion(cur, token, result, editor);
|
start = nameCompletion(cur, token, result, editor);
|
||||||
} else {
|
} else {
|
||||||
addMatches(result, search, tables, function(w) {return w;});
|
addMatches(result, search, tables, function(w) {return w;});
|
||||||
addMatches(result, search, defaultTable, function(w) {return w;});
|
addMatches(result, search, defaultTable, function(w) {return w;});
|
||||||
addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
|
if (!disableKeywords)
|
||||||
|
addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
|
return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
|
||||||
|
46
web/pgadmin/static/js/codemirror/addon/lint/html-lint.js
vendored
Normal file
46
web/pgadmin/static/js/codemirror/addon/lint/html-lint.js
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
// Depends on htmlhint.js from http://htmlhint.com/js/htmlhint.js
|
||||||
|
|
||||||
|
// declare global: HTMLHint
|
||||||
|
|
||||||
|
(function(mod) {
|
||||||
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
|
mod(require("../../lib/codemirror"), require("htmlhint"));
|
||||||
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
|
define(["../../lib/codemirror", "htmlhint"], mod);
|
||||||
|
else // Plain browser env
|
||||||
|
mod(CodeMirror);
|
||||||
|
})(function(CodeMirror) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var defaultRules = {
|
||||||
|
"tagname-lowercase": true,
|
||||||
|
"attr-lowercase": true,
|
||||||
|
"attr-value-double-quotes": true,
|
||||||
|
"doctype-first": false,
|
||||||
|
"tag-pair": true,
|
||||||
|
"spec-char-escape": true,
|
||||||
|
"id-unique": true,
|
||||||
|
"src-not-empty": true,
|
||||||
|
"attr-no-duplication": true
|
||||||
|
};
|
||||||
|
|
||||||
|
CodeMirror.registerHelper("lint", "html", function(text, options) {
|
||||||
|
var found = [];
|
||||||
|
if (!window.HTMLHint) return found;
|
||||||
|
var messages = HTMLHint.verify(text, options && options.rules || defaultRules);
|
||||||
|
for (var i = 0; i < messages.length; i++) {
|
||||||
|
var 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;
|
||||||
|
});
|
||||||
|
});
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
function validator(text, options) {
|
function validator(text, options) {
|
||||||
if (!window.JSHINT) return [];
|
if (!window.JSHINT) return [];
|
||||||
JSHINT(text, options);
|
JSHINT(text, options, options.globals);
|
||||||
var errors = JSHINT.data().errors, result = [];
|
var errors = JSHINT.data().errors, result = [];
|
||||||
if (errors) parseErrors(errors, result);
|
if (errors) parseErrors(errors, result);
|
||||||
return result;
|
return result;
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
}
|
}
|
||||||
var poll = setInterval(function() {
|
var poll = setInterval(function() {
|
||||||
if (tooltip) for (var n = node;; n = n.parentNode) {
|
if (tooltip) for (var n = node;; n = n.parentNode) {
|
||||||
|
if (n && n.nodeType == 11) n = n.host;
|
||||||
if (n == document.body) return;
|
if (n == document.body) return;
|
||||||
if (!n) { hide(); break; }
|
if (!n) { hide(); break; }
|
||||||
}
|
}
|
||||||
@ -60,13 +61,12 @@
|
|||||||
this.timeout = null;
|
this.timeout = null;
|
||||||
this.hasGutter = hasGutter;
|
this.hasGutter = hasGutter;
|
||||||
this.onMouseOver = function(e) { onMouseOver(cm, e); };
|
this.onMouseOver = function(e) { onMouseOver(cm, e); };
|
||||||
|
this.waitingFor = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseOptions(cm, options) {
|
function parseOptions(_cm, options) {
|
||||||
if (options instanceof Function) return {getAnnotations: options};
|
if (options instanceof Function) return {getAnnotations: options};
|
||||||
if (!options || options === true) options = {};
|
if (!options || options === true) options = {};
|
||||||
if (!options.getAnnotations) options.getAnnotations = cm.getHelper(CodeMirror.Pos(0, 0), "lint");
|
|
||||||
if (!options.getAnnotations) throw new Error("Required option 'getAnnotations' missing (lint addon)");
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,13 +116,32 @@
|
|||||||
return tip;
|
return tip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function lintAsync(cm, getAnnotations, passOptions) {
|
||||||
|
var state = cm.state.lint
|
||||||
|
var id = ++state.waitingFor
|
||||||
|
function abort() {
|
||||||
|
id = -1
|
||||||
|
cm.off("change", abort)
|
||||||
|
}
|
||||||
|
cm.on("change", abort)
|
||||||
|
getAnnotations(cm.getValue(), function(annotations, arg2) {
|
||||||
|
cm.off("change", abort)
|
||||||
|
if (state.waitingFor != id) return
|
||||||
|
if (arg2 && annotations instanceof CodeMirror) annotations = arg2
|
||||||
|
updateLinting(cm, annotations)
|
||||||
|
}, passOptions, cm);
|
||||||
|
}
|
||||||
|
|
||||||
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
|
var passOptions = options.options || options; // Support deprecated passing of `options` property in options
|
||||||
if (options.async)
|
var getAnnotations = options.getAnnotations || cm.getHelper(CodeMirror.Pos(0, 0), "lint");
|
||||||
options.getAnnotations(cm.getValue(), updateLinting, passOptions, cm);
|
if (!getAnnotations) return;
|
||||||
else
|
if (options.async || getAnnotations.async) {
|
||||||
updateLinting(cm, options.getAnnotations(cm.getValue(), passOptions, cm));
|
lintAsync(cm, getAnnotations, passOptions)
|
||||||
|
} else {
|
||||||
|
updateLinting(cm, getAnnotations(cm.getValue(), passOptions, cm));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateLinting(cm, annotationsNotSorted) {
|
function updateLinting(cm, annotationsNotSorted) {
|
||||||
@ -162,13 +181,19 @@
|
|||||||
|
|
||||||
function onChange(cm) {
|
function onChange(cm) {
|
||||||
var state = cm.state.lint;
|
var state = cm.state.lint;
|
||||||
|
if (!state) return;
|
||||||
clearTimeout(state.timeout);
|
clearTimeout(state.timeout);
|
||||||
state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
|
state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
function popupSpanTooltip(ann, e) {
|
function popupTooltips(annotations, e) {
|
||||||
var target = e.target || e.srcElement;
|
var target = e.target || e.srcElement;
|
||||||
showTooltipFor(e, annotationTooltip(ann), target);
|
var tooltip = document.createDocumentFragment();
|
||||||
|
for (var i = 0; i < annotations.length; i++) {
|
||||||
|
var ann = annotations[i];
|
||||||
|
tooltip.appendChild(annotationTooltip(ann));
|
||||||
|
}
|
||||||
|
showTooltipFor(e, tooltip, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMouseOver(cm, e) {
|
function onMouseOver(cm, e) {
|
||||||
@ -176,17 +201,22 @@
|
|||||||
if (!/\bCodeMirror-lint-mark-/.test(target.className)) return;
|
if (!/\bCodeMirror-lint-mark-/.test(target.className)) return;
|
||||||
var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2;
|
var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2;
|
||||||
var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client"));
|
var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client"));
|
||||||
|
|
||||||
|
var annotations = [];
|
||||||
for (var i = 0; i < spans.length; ++i) {
|
for (var i = 0; i < spans.length; ++i) {
|
||||||
var ann = spans[i].__annotation;
|
var ann = spans[i].__annotation;
|
||||||
if (ann) return popupSpanTooltip(ann, e);
|
if (ann) annotations.push(ann);
|
||||||
}
|
}
|
||||||
|
if (annotations.length) popupTooltips(annotations, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeMirror.defineOption("lint", false, function(cm, val, old) {
|
CodeMirror.defineOption("lint", false, function(cm, val, old) {
|
||||||
if (old && old != CodeMirror.Init) {
|
if (old && old != CodeMirror.Init) {
|
||||||
clearMarks(cm);
|
clearMarks(cm);
|
||||||
cm.off("change", onChange);
|
if (cm.state.lint.options.lintOnChange !== false)
|
||||||
|
cm.off("change", onChange);
|
||||||
CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.lint.onMouseOver);
|
CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.lint.onMouseOver);
|
||||||
|
clearTimeout(cm.state.lint.timeout);
|
||||||
delete cm.state.lint;
|
delete cm.state.lint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,11 +224,16 @@
|
|||||||
var gutters = cm.getOption("gutters"), hasLintGutter = false;
|
var gutters = cm.getOption("gutters"), hasLintGutter = false;
|
||||||
for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true;
|
for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true;
|
||||||
var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter);
|
var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter);
|
||||||
cm.on("change", onChange);
|
if (state.options.lintOnChange !== false)
|
||||||
|
cm.on("change", onChange);
|
||||||
if (state.options.tooltips != false)
|
if (state.options.tooltips != false)
|
||||||
CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
|
CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
|
||||||
|
|
||||||
startLinting(cm);
|
startLinting(cm);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
CodeMirror.defineExtension("performLint", function() {
|
||||||
|
if (this.state.lint) startLinting(this);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #44c;
|
color: #44c;
|
||||||
|
z-index: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror-merge-copy-reverse {
|
.CodeMirror-merge-copy-reverse {
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
(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("diff_match_patch"));
|
mod(require("../../lib/codemirror")); // Note non-packaged dependency diff_match_patch
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
define(["../../lib/codemirror", "diff_match_patch"], mod);
|
define(["../../lib/codemirror", "diff_match_patch"], mod);
|
||||||
else // Plain browser env
|
else // Plain browser env
|
||||||
mod(CodeMirror, diff_match_patch);
|
mod(CodeMirror);
|
||||||
})(function(CodeMirror, diff_match_patch) {
|
})(function(CodeMirror) {
|
||||||
"use strict";
|
"use strict";
|
||||||
var Pos = CodeMirror.Pos;
|
var Pos = CodeMirror.Pos;
|
||||||
var svgNS = "http://www.w3.org/2000/svg";
|
var svgNS = "http://www.w3.org/2000/svg";
|
||||||
@ -31,18 +31,19 @@
|
|||||||
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.edit.state.diffViews || (this.edit.state.diffViews = [])).push(this);
|
||||||
this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));
|
this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));
|
||||||
|
this.orig.state.diffViews = [this];
|
||||||
|
|
||||||
this.diff = getDiff(asString(orig), asString(options.value));
|
this.diff = getDiff(asString(orig), asString(options.value));
|
||||||
this.diffOutOfDate = false;
|
this.chunks = getChunks(this.diff);
|
||||||
|
this.diffOutOfDate = this.dealigned = false;
|
||||||
|
|
||||||
this.showDifferences = options.showDifferences !== false;
|
this.showDifferences = options.showDifferences !== false;
|
||||||
this.forceUpdate = registerUpdate(this);
|
this.forceUpdate = registerUpdate(this);
|
||||||
@ -61,16 +62,20 @@
|
|||||||
function ensureDiff(dv) {
|
function ensureDiff(dv) {
|
||||||
if (dv.diffOutOfDate) {
|
if (dv.diffOutOfDate) {
|
||||||
dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());
|
dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());
|
||||||
|
dv.chunks = getChunks(dv.diff);
|
||||||
dv.diffOutOfDate = false;
|
dv.diffOutOfDate = false;
|
||||||
CodeMirror.signal(dv.edit, "updateDiff", dv.diff);
|
CodeMirror.signal(dv.edit, "updateDiff", dv.diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var updating = false;
|
||||||
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: []};
|
||||||
var debounceChange;
|
var debounceChange, updatingFast = false;
|
||||||
function update(mode) {
|
function update(mode) {
|
||||||
|
updating = true;
|
||||||
|
updatingFast = false;
|
||||||
if (mode == "full") {
|
if (mode == "full") {
|
||||||
if (dv.svg) clear(dv.svg);
|
if (dv.svg) clear(dv.svg);
|
||||||
if (dv.copyButtons) clear(dv.copyButtons);
|
if (dv.copyButtons) clear(dv.copyButtons);
|
||||||
@ -84,26 +89,38 @@
|
|||||||
updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
|
updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
|
||||||
}
|
}
|
||||||
makeConnections(dv);
|
makeConnections(dv);
|
||||||
|
|
||||||
|
if (dv.mv.options.connect == "align")
|
||||||
|
alignChunks(dv);
|
||||||
|
updating = false;
|
||||||
}
|
}
|
||||||
function set(slow) {
|
function setDealign(fast) {
|
||||||
|
if (updating) return;
|
||||||
|
dv.dealigned = true;
|
||||||
|
set(fast);
|
||||||
|
}
|
||||||
|
function set(fast) {
|
||||||
|
if (updating || updatingFast) return;
|
||||||
clearTimeout(debounceChange);
|
clearTimeout(debounceChange);
|
||||||
debounceChange = setTimeout(update, slow == true ? 250 : 100);
|
if (fast === true) updatingFast = true;
|
||||||
|
debounceChange = setTimeout(update, fast === true ? 20 : 250);
|
||||||
}
|
}
|
||||||
function change() {
|
function change(_cm, change) {
|
||||||
if (!dv.diffOutOfDate) {
|
if (!dv.diffOutOfDate) {
|
||||||
dv.diffOutOfDate = true;
|
dv.diffOutOfDate = true;
|
||||||
edit.from = edit.to = orig.from = orig.to = 0;
|
edit.from = edit.to = orig.from = orig.to = 0;
|
||||||
}
|
}
|
||||||
set(true);
|
// Update faster when a line was added/removed
|
||||||
|
setDealign(change.text.length - 1 != change.to.line - change.from.line);
|
||||||
}
|
}
|
||||||
dv.edit.on("change", change);
|
dv.edit.on("change", change);
|
||||||
dv.orig.on("change", change);
|
dv.orig.on("change", change);
|
||||||
dv.edit.on("markerAdded", set);
|
dv.edit.on("markerAdded", setDealign);
|
||||||
dv.edit.on("markerCleared", set);
|
dv.edit.on("markerCleared", setDealign);
|
||||||
dv.orig.on("markerAdded", set);
|
dv.orig.on("markerAdded", setDealign);
|
||||||
dv.orig.on("markerCleared", set);
|
dv.orig.on("markerCleared", setDealign);
|
||||||
dv.edit.on("viewportChange", set);
|
dv.edit.on("viewportChange", function() { set(false); });
|
||||||
dv.orig.on("viewportChange", set);
|
dv.orig.on("viewportChange", function() { set(false); });
|
||||||
update();
|
update();
|
||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
@ -134,7 +151,7 @@
|
|||||||
} else {
|
} else {
|
||||||
var halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;
|
var halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;
|
||||||
var mid = editor.lineAtHeight(midY, "local");
|
var mid = editor.lineAtHeight(midY, "local");
|
||||||
var around = chunkBoundariesAround(dv.diff, mid, type == DIFF_INSERT);
|
var around = chunkBoundariesAround(dv.chunks, mid, type == DIFF_INSERT);
|
||||||
var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);
|
var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);
|
||||||
var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);
|
var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);
|
||||||
var ratio = (midY - off.top) / (off.bot - off.top);
|
var ratio = (midY - off.top) / (off.bot - off.top);
|
||||||
@ -259,19 +276,6 @@
|
|||||||
function makeConnections(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;
|
||||||
@ -281,34 +285,118 @@
|
|||||||
|
|
||||||
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) {
|
for (var i = 0; i < dv.chunks.length; i++) {
|
||||||
if (topEdit <= vpEdit.to && botEdit >= vpEdit.from &&
|
var ch = dv.chunks[i];
|
||||||
topOrig <= vpOrig.to && botOrig >= vpOrig.from)
|
if (ch.editFrom <= vpEdit.to && ch.editTo >= vpEdit.from &&
|
||||||
drawConnectorsForChunk(dv, topOrig, botOrig, topEdit, botEdit, sTopOrig, sTopEdit, w);
|
ch.origFrom <= vpOrig.to && ch.origTo >= vpOrig.from)
|
||||||
if (align && (topEdit <= vpEdit.to || topOrig <= vpOrig.to)) {
|
drawConnectorsForChunk(dv, ch, sTopOrig, sTopEdit, w);
|
||||||
var above = (botEdit < vpEdit.from && botOrig < vpOrig.from);
|
|
||||||
alignChunks(dv, topOrig, botOrig, topEdit, botEdit, above && extraSpaceAbove);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
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 drawConnectorsForChunk(dv, topOrig, botOrig, topEdit, botEdit, sTopOrig, sTopEdit, w) {
|
function getMatchingOrigLine(editLine, chunks) {
|
||||||
|
var editStart = 0, origStart = 0;
|
||||||
|
for (var i = 0; i < chunks.length; i++) {
|
||||||
|
var chunk = chunks[i];
|
||||||
|
if (chunk.editTo > editLine && chunk.editFrom <= editLine) return null;
|
||||||
|
if (chunk.editFrom > editLine) break;
|
||||||
|
editStart = chunk.editTo;
|
||||||
|
origStart = chunk.origTo;
|
||||||
|
}
|
||||||
|
return origStart + (editLine - editStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findAlignedLines(dv, other) {
|
||||||
|
var linesToAlign = [];
|
||||||
|
for (var i = 0; i < dv.chunks.length; i++) {
|
||||||
|
var chunk = dv.chunks[i];
|
||||||
|
linesToAlign.push([chunk.origTo, chunk.editTo, other ? getMatchingOrigLine(chunk.editTo, other.chunks) : null]);
|
||||||
|
}
|
||||||
|
if (other) {
|
||||||
|
for (var i = 0; i < other.chunks.length; i++) {
|
||||||
|
var chunk = other.chunks[i];
|
||||||
|
for (var j = 0; j < linesToAlign.length; j++) {
|
||||||
|
var align = linesToAlign[j];
|
||||||
|
if (align[1] == chunk.editTo) {
|
||||||
|
j = -1;
|
||||||
|
break;
|
||||||
|
} else if (align[1] > chunk.editTo) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j > -1)
|
||||||
|
linesToAlign.splice(j - 1, 0, [getMatchingOrigLine(chunk.editTo, dv.chunks), chunk.editTo, chunk.origTo]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return linesToAlign;
|
||||||
|
}
|
||||||
|
|
||||||
|
function alignChunks(dv, force) {
|
||||||
|
if (!dv.dealigned && !force) return;
|
||||||
|
if (!dv.orig.curOp) return dv.orig.operation(function() {
|
||||||
|
alignChunks(dv, force);
|
||||||
|
});
|
||||||
|
|
||||||
|
dv.dealigned = false;
|
||||||
|
var other = dv.mv.left == dv ? dv.mv.right : dv.mv.left;
|
||||||
|
if (other) {
|
||||||
|
ensureDiff(other);
|
||||||
|
other.dealigned = false;
|
||||||
|
}
|
||||||
|
var linesToAlign = findAlignedLines(dv, other);
|
||||||
|
|
||||||
|
// Clear old aligners
|
||||||
|
var aligners = dv.mv.aligners;
|
||||||
|
for (var i = 0; i < aligners.length; i++)
|
||||||
|
aligners[i].clear();
|
||||||
|
aligners.length = 0;
|
||||||
|
|
||||||
|
var cm = [dv.orig, dv.edit], scroll = [];
|
||||||
|
if (other) cm.push(other.orig);
|
||||||
|
for (var i = 0; i < cm.length; i++)
|
||||||
|
scroll.push(cm[i].getScrollInfo().top);
|
||||||
|
|
||||||
|
for (var ln = 0; ln < linesToAlign.length; ln++)
|
||||||
|
alignLines(cm, linesToAlign[ln], aligners);
|
||||||
|
|
||||||
|
for (var i = 0; i < cm.length; i++)
|
||||||
|
cm[i].scrollTo(null, scroll[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function alignLines(cm, lines, aligners) {
|
||||||
|
var maxOffset = 0, offset = [];
|
||||||
|
for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
|
||||||
|
var off = cm[i].heightAtLine(lines[i], "local");
|
||||||
|
offset[i] = off;
|
||||||
|
maxOffset = Math.max(maxOffset, off);
|
||||||
|
}
|
||||||
|
for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
|
||||||
|
var diff = maxOffset - offset[i];
|
||||||
|
if (diff > 1)
|
||||||
|
aligners.push(padAbove(cm[i], lines[i], diff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function padAbove(cm, line, size) {
|
||||||
|
var above = true;
|
||||||
|
if (line > cm.lastLine()) {
|
||||||
|
line--;
|
||||||
|
above = false;
|
||||||
|
}
|
||||||
|
var elt = document.createElement("div");
|
||||||
|
elt.className = "CodeMirror-merge-spacer";
|
||||||
|
elt.style.height = size + "px"; elt.style.minWidth = "1px";
|
||||||
|
return cm.addLineWidget(line, elt, {height: size, above: above});
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawConnectorsForChunk(dv, chunk, sTopOrig, sTopEdit, w) {
|
||||||
var flip = dv.type == "left";
|
var flip = dv.type == "left";
|
||||||
var top = dv.orig.heightAtLine(topOrig, "local") - sTopOrig;
|
var top = dv.orig.heightAtLine(chunk.origFrom, "local") - sTopOrig;
|
||||||
if (dv.svg) {
|
if (dv.svg) {
|
||||||
var topLpx = top;
|
var topLpx = top;
|
||||||
var topRpx = dv.edit.heightAtLine(topEdit, "local") - sTopEdit;
|
var topRpx = dv.edit.heightAtLine(chunk.editFrom, "local") - sTopEdit;
|
||||||
if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }
|
if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }
|
||||||
var botLpx = dv.orig.heightAtLine(botOrig, "local") - sTopOrig;
|
var botLpx = dv.orig.heightAtLine(chunk.origTo, "local") - sTopOrig;
|
||||||
var botRpx = dv.edit.heightAtLine(botEdit, "local") - sTopEdit;
|
var botRpx = dv.edit.heightAtLine(chunk.editTo, "local") - sTopEdit;
|
||||||
if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }
|
if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }
|
||||||
var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;
|
var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;
|
||||||
var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;
|
var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;
|
||||||
@ -321,48 +409,27 @@
|
|||||||
"CodeMirror-merge-copy"));
|
"CodeMirror-merge-copy"));
|
||||||
var editOriginals = dv.mv.options.allowEditingOriginals;
|
var editOriginals = dv.mv.options.allowEditingOriginals;
|
||||||
copy.title = editOriginals ? "Push to left" : "Revert chunk";
|
copy.title = editOriginals ? "Push to left" : "Revert chunk";
|
||||||
copy.chunk = {topEdit: topEdit, botEdit: botEdit, topOrig: topOrig, botOrig: botOrig};
|
copy.chunk = chunk;
|
||||||
copy.style.top = top + "px";
|
copy.style.top = top + "px";
|
||||||
|
|
||||||
if (editOriginals) {
|
if (editOriginals) {
|
||||||
var topReverse = dv.orig.heightAtLine(topEdit, "local") - sTopEdit;
|
var topReverse = dv.orig.heightAtLine(chunk.editFrom, "local") - sTopEdit;
|
||||||
var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\u21dd" : "\u21dc",
|
var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\u21dd" : "\u21dc",
|
||||||
"CodeMirror-merge-copy-reverse"));
|
"CodeMirror-merge-copy-reverse"));
|
||||||
copyReverse.title = "Push to right";
|
copyReverse.title = "Push to right";
|
||||||
copyReverse.chunk = {topEdit: topOrig, botEdit: botOrig, topOrig: topEdit, botOrig: botEdit};
|
copyReverse.chunk = {editFrom: chunk.origFrom, editTo: chunk.origTo,
|
||||||
|
origFrom: chunk.editFrom, origTo: chunk.editTo};
|
||||||
copyReverse.style.top = topReverse + "px";
|
copyReverse.style.top = topReverse + "px";
|
||||||
dv.type == "right" ? copyReverse.style.left = "2px" : copyReverse.style.right = "2px";
|
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) {
|
function copyChunk(dv, to, from, chunk) {
|
||||||
if (dv.diffOutOfDate) return;
|
if (dv.diffOutOfDate) return;
|
||||||
to.replaceRange(from.getRange(Pos(chunk.topOrig, 0), Pos(chunk.botOrig, 0)),
|
var editStart = chunk.editTo > to.lastLine() ? Pos(chunk.editFrom - 1) : Pos(chunk.editFrom, 0)
|
||||||
Pos(chunk.topEdit, 0), Pos(chunk.botEdit, 0));
|
var origStart = chunk.origTo > from.lastLine() ? Pos(chunk.origFrom - 1) : Pos(chunk.origFrom, 0)
|
||||||
|
to.replaceRange(from.getRange(origStart, Pos(chunk.origTo, 0)), editStart, Pos(chunk.editTo, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge view, containing 0, 1, or 2 diff views.
|
// Merge view, containing 0, 1, or 2 diff views.
|
||||||
@ -372,16 +439,11 @@
|
|||||||
|
|
||||||
this.options = 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;
|
||||||
|
var self = this;
|
||||||
|
|
||||||
if (hasLeft) {
|
if (hasLeft) {
|
||||||
left = this.left = new DiffView(this, "left");
|
left = this.left = new DiffView(this, "left");
|
||||||
@ -411,7 +473,13 @@
|
|||||||
if (right) right.init(rightPane, origRight, options);
|
if (right) right.init(rightPane, origRight, options);
|
||||||
|
|
||||||
if (options.collapseIdentical)
|
if (options.collapseIdentical)
|
||||||
collapseIdenticalStretches(left || right, options.collapseIdentical);
|
this.editor().operation(function() {
|
||||||
|
collapseIdenticalStretches(self, options.collapseIdentical);
|
||||||
|
});
|
||||||
|
if (options.connect == "align") {
|
||||||
|
this.aligners = [];
|
||||||
|
alignChunks(this.left || this.right, true);
|
||||||
|
}
|
||||||
|
|
||||||
var onResize = function() {
|
var onResize = function() {
|
||||||
if (left) makeConnections(left);
|
if (left) makeConnections(left);
|
||||||
@ -463,10 +531,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);
|
if (this.right) { ensureDiff(this.right); return this.right.chunks; }
|
||||||
},
|
},
|
||||||
leftChunks: function() {
|
leftChunks: function() {
|
||||||
return this.left && getChunks(this.left);
|
if (this.left) { ensureDiff(this.left); return this.left.chunks; }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -494,7 +562,8 @@
|
|||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
function iterateChunks(diff, f) {
|
function getChunks(diff) {
|
||||||
|
var chunks = [];
|
||||||
var startEdit = 0, startOrig = 0;
|
var startEdit = 0, startOrig = 0;
|
||||||
var edit = Pos(0, 0), orig = Pos(0, 0);
|
var edit = Pos(0, 0), orig = Pos(0, 0);
|
||||||
for (var i = 0; i < diff.length; ++i) {
|
for (var i = 0; i < diff.length; ++i) {
|
||||||
@ -506,7 +575,8 @@
|
|||||||
var endOff = endOfLineClean(diff, i) ? 1 : 0;
|
var endOff = endOfLineClean(diff, i) ? 1 : 0;
|
||||||
var cleanToEdit = edit.line + endOff, cleanToOrig = orig.line + endOff;
|
var cleanToEdit = edit.line + endOff, cleanToOrig = orig.line + endOff;
|
||||||
if (cleanToEdit > cleanFromEdit) {
|
if (cleanToEdit > cleanFromEdit) {
|
||||||
if (i) f(startOrig, cleanFromOrig, startEdit, cleanFromEdit);
|
if (i) chunks.push({origFrom: startOrig, origTo: cleanFromOrig,
|
||||||
|
editFrom: startEdit, editTo: cleanFromEdit});
|
||||||
startEdit = cleanToEdit; startOrig = cleanToOrig;
|
startEdit = cleanToEdit; startOrig = cleanToOrig;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -514,17 +584,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (startEdit <= edit.line || startOrig <= orig.line)
|
if (startEdit <= edit.line || startOrig <= orig.line)
|
||||||
f(startOrig, orig.line + 1, startEdit, edit.line + 1);
|
chunks.push({origFrom: startOrig, origTo: orig.line + 1,
|
||||||
}
|
editFrom: startEdit, editTo: edit.line + 1});
|
||||||
|
return chunks;
|
||||||
function getChunks(dv) {
|
|
||||||
ensureDiff(dv);
|
|
||||||
var collect = [];
|
|
||||||
iterateChunks(dv.diff, function(topOrig, botOrig, topEdit, botEdit) {
|
|
||||||
collect.push({origFrom: topOrig, origTo: botOrig,
|
|
||||||
editFrom: topEdit, editTo: botEdit});
|
|
||||||
});
|
|
||||||
return collect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function endOfLineClean(diff, i) {
|
function endOfLineClean(diff, i) {
|
||||||
@ -545,18 +607,19 @@
|
|||||||
return last.charCodeAt(last.length - 1) == 10;
|
return last.charCodeAt(last.length - 1) == 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
function chunkBoundariesAround(diff, n, nInEdit) {
|
function chunkBoundariesAround(chunks, n, nInEdit) {
|
||||||
var beforeE, afterE, beforeO, afterO;
|
var beforeE, afterE, beforeO, afterO;
|
||||||
iterateChunks(diff, function(fromOrig, toOrig, fromEdit, toEdit) {
|
for (var i = 0; i < chunks.length; i++) {
|
||||||
var fromLocal = nInEdit ? fromEdit : fromOrig;
|
var chunk = chunks[i];
|
||||||
var toLocal = nInEdit ? toEdit : toOrig;
|
var fromLocal = nInEdit ? chunk.editFrom : chunk.origFrom;
|
||||||
|
var toLocal = nInEdit ? chunk.editTo : chunk.origTo;
|
||||||
if (afterE == null) {
|
if (afterE == null) {
|
||||||
if (fromLocal > n) { afterE = fromEdit; afterO = fromOrig; }
|
if (fromLocal > n) { afterE = chunk.editFrom; afterO = chunk.origFrom; }
|
||||||
else if (toLocal > n) { afterE = toEdit; afterO = toOrig; }
|
else if (toLocal > n) { afterE = chunk.editTo; afterO = chunk.origTo; }
|
||||||
}
|
}
|
||||||
if (toLocal <= n) { beforeE = toEdit; beforeO = toOrig; }
|
if (toLocal <= n) { beforeE = chunk.editTo; beforeO = chunk.origTo; }
|
||||||
else if (fromLocal <= n) { beforeE = fromEdit; beforeO = fromOrig; }
|
else if (fromLocal <= n) { beforeE = chunk.editFrom; beforeO = chunk.origFrom; }
|
||||||
});
|
}
|
||||||
return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}};
|
return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,29 +638,54 @@
|
|||||||
mark.clear();
|
mark.clear();
|
||||||
cm.removeLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
|
cm.removeLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
|
||||||
}
|
}
|
||||||
widget.addEventListener("click", clear);
|
CodeMirror.on(widget, "click", clear);
|
||||||
return {mark: mark, clear: clear};
|
return {mark: mark, clear: clear};
|
||||||
}
|
}
|
||||||
|
|
||||||
function collapseStretch(dv, origStart, editStart, size) {
|
function collapseStretch(size, editors) {
|
||||||
var mOrig = collapseSingle(dv.orig, origStart, origStart + size);
|
var marks = [];
|
||||||
var mEdit = collapseSingle(dv.edit, editStart, editStart + size);
|
function clear() {
|
||||||
mOrig.mark.on("clear", function() { mEdit.clear(); });
|
for (var i = 0; i < marks.length; i++) marks[i].clear();
|
||||||
mEdit.mark.on("clear", function() { mOrig.clear(); });
|
}
|
||||||
|
for (var i = 0; i < editors.length; i++) {
|
||||||
|
var editor = editors[i];
|
||||||
|
var mark = collapseSingle(editor.cm, editor.line, editor.line + size);
|
||||||
|
marks.push(mark);
|
||||||
|
mark.mark.on("clear", clear);
|
||||||
|
}
|
||||||
|
return marks[0].mark;
|
||||||
}
|
}
|
||||||
|
|
||||||
function collapseIdenticalStretches(dv, margin) {
|
function unclearNearChunks(dv, margin, off, clear) {
|
||||||
|
for (var i = 0; i < dv.chunks.length; i++) {
|
||||||
|
var chunk = dv.chunks[i];
|
||||||
|
for (var l = chunk.editFrom - margin; l < chunk.editTo + margin; l++) {
|
||||||
|
var pos = l + off;
|
||||||
|
if (pos >= 0 && pos < clear.length) clear[pos] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function collapseIdenticalStretches(mv, margin) {
|
||||||
if (typeof margin != "number") margin = 2;
|
if (typeof margin != "number") margin = 2;
|
||||||
var lastOrig = dv.orig.firstLine(), lastEdit = dv.edit.firstLine();
|
var clear = [], edit = mv.editor(), off = edit.firstLine();
|
||||||
iterateChunks(dv.diff, function(topOrig, botOrig, _topEdit, botEdit) {
|
for (var l = off, e = edit.lastLine(); l <= e; l++) clear.push(true);
|
||||||
var identicalSize = topOrig - margin - lastOrig;
|
if (mv.left) unclearNearChunks(mv.left, margin, off, clear);
|
||||||
if (identicalSize > margin)
|
if (mv.right) unclearNearChunks(mv.right, margin, off, clear);
|
||||||
collapseStretch(dv, lastOrig, lastEdit, identicalSize);
|
|
||||||
lastOrig = botOrig + margin; lastEdit = botEdit + margin;
|
for (var i = 0; i < clear.length; i++) {
|
||||||
});
|
if (clear[i]) {
|
||||||
var bottomSize = dv.orig.lastLine() + 1 - lastOrig;
|
var line = i + off;
|
||||||
if (bottomSize > margin)
|
for (var size = 1; i < clear.length - 1 && clear[i + 1]; i++, size++) {}
|
||||||
collapseStretch(dv, lastOrig, lastEdit, bottomSize);
|
if (size > margin) {
|
||||||
|
var editors = [{line: line, cm: edit}];
|
||||||
|
if (mv.left) editors.push({line: getMatchingOrigLine(line, mv.left.chunks), cm: mv.left.orig});
|
||||||
|
if (mv.right) editors.push({line: getMatchingOrigLine(line, mv.right.chunks), cm: mv.right.orig});
|
||||||
|
var mark = collapseStretch(size, editors);
|
||||||
|
if (mv.options.onCollapse) mv.options.onCollapse(mv, line, size, mark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// General utilities
|
// General utilities
|
||||||
@ -644,4 +732,42 @@
|
|||||||
function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; }
|
function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; }
|
||||||
function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; }
|
function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; }
|
||||||
function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }
|
function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }
|
||||||
|
|
||||||
|
function findPrevDiff(chunks, start, isOrig) {
|
||||||
|
for (var i = chunks.length - 1; i >= 0; i--) {
|
||||||
|
var chunk = chunks[i];
|
||||||
|
var to = (isOrig ? chunk.origTo : chunk.editTo) - 1;
|
||||||
|
if (to < start) return to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findNextDiff(chunks, start, isOrig) {
|
||||||
|
for (var i = 0; i < chunks.length; i++) {
|
||||||
|
var chunk = chunks[i];
|
||||||
|
var from = (isOrig ? chunk.origFrom : chunk.editFrom);
|
||||||
|
if (from > start) return from;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function goNearbyDiff(cm, dir) {
|
||||||
|
var found = null, views = cm.state.diffViews, line = cm.getCursor().line;
|
||||||
|
if (views) for (var i = 0; i < views.length; i++) {
|
||||||
|
var dv = views[i], isOrig = cm == dv.orig;
|
||||||
|
ensureDiff(dv);
|
||||||
|
var pos = dir < 0 ? findPrevDiff(dv.chunks, line, isOrig) : findNextDiff(dv.chunks, line, isOrig);
|
||||||
|
if (pos != null && (found == null || (dir < 0 ? pos > found : pos < found)))
|
||||||
|
found = pos;
|
||||||
|
}
|
||||||
|
if (found != null)
|
||||||
|
cm.setCursor(found, 0);
|
||||||
|
else
|
||||||
|
return CodeMirror.Pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeMirror.commands.goNextDiff = function(cm) {
|
||||||
|
return goNearbyDiff(cm, 1);
|
||||||
|
};
|
||||||
|
CodeMirror.commands.goPrevDiff = function(cm) {
|
||||||
|
return goNearbyDiff(cm, -1);
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
@ -14,12 +14,14 @@
|
|||||||
CodeMirror.multiplexingMode = function(outer /*, others */) {
|
CodeMirror.multiplexingMode = function(outer /*, others */) {
|
||||||
// Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects
|
// Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects
|
||||||
var others = Array.prototype.slice.call(arguments, 1);
|
var others = Array.prototype.slice.call(arguments, 1);
|
||||||
var n_others = others.length;
|
|
||||||
|
|
||||||
function indexOf(string, pattern, from) {
|
function indexOf(string, pattern, from, returnEnd) {
|
||||||
if (typeof pattern == "string") return string.indexOf(pattern, from);
|
if (typeof pattern == "string") {
|
||||||
|
var found = string.indexOf(pattern, from);
|
||||||
|
return returnEnd && found > -1 ? found + pattern.length : found;
|
||||||
|
}
|
||||||
var m = pattern.exec(from ? string.slice(from) : string);
|
var m = pattern.exec(from ? string.slice(from) : string);
|
||||||
return m ? m.index + from : -1;
|
return m ? m.index + from + (returnEnd ? m[0].length : 0) : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -42,14 +44,14 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
|
|||||||
token: function(stream, state) {
|
token: function(stream, state) {
|
||||||
if (!state.innerActive) {
|
if (!state.innerActive) {
|
||||||
var cutOff = Infinity, oldContent = stream.string;
|
var cutOff = Infinity, oldContent = stream.string;
|
||||||
for (var i = 0; i < n_others; ++i) {
|
for (var i = 0; i < others.length; ++i) {
|
||||||
var other = others[i];
|
var other = others[i];
|
||||||
var found = indexOf(oldContent, other.open, stream.pos);
|
var found = indexOf(oldContent, other.open, stream.pos);
|
||||||
if (found == stream.pos) {
|
if (found == stream.pos) {
|
||||||
stream.match(other.open);
|
if (!other.parseDelimiters) stream.match(other.open);
|
||||||
state.innerActive = other;
|
state.innerActive = other;
|
||||||
state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
|
state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
|
||||||
return other.delimStyle;
|
return other.delimStyle && (other.delimStyle + " " + other.delimStyle + "-open");
|
||||||
} else if (found != -1 && found < cutOff) {
|
} else if (found != -1 && found < cutOff) {
|
||||||
cutOff = found;
|
cutOff = found;
|
||||||
}
|
}
|
||||||
@ -64,18 +66,21 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
|
|||||||
state.innerActive = state.inner = null;
|
state.innerActive = state.inner = null;
|
||||||
return this.token(stream, state);
|
return this.token(stream, state);
|
||||||
}
|
}
|
||||||
var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos) : -1;
|
var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos, curInner.parseDelimiters) : -1;
|
||||||
if (found == stream.pos) {
|
if (found == stream.pos && !curInner.parseDelimiters) {
|
||||||
stream.match(curInner.close);
|
stream.match(curInner.close);
|
||||||
state.innerActive = state.inner = null;
|
state.innerActive = state.inner = null;
|
||||||
return curInner.delimStyle;
|
return curInner.delimStyle && (curInner.delimStyle + " " + curInner.delimStyle + "-close");
|
||||||
}
|
}
|
||||||
if (found > -1) stream.string = oldContent.slice(0, found);
|
if (found > -1) stream.string = oldContent.slice(0, found);
|
||||||
var innerToken = curInner.mode.token(stream, state.inner);
|
var innerToken = curInner.mode.token(stream, state.inner);
|
||||||
if (found > -1) stream.string = oldContent;
|
if (found > -1) stream.string = oldContent;
|
||||||
|
|
||||||
|
if (found == stream.pos && curInner.parseDelimiters)
|
||||||
|
state.innerActive = state.inner = null;
|
||||||
|
|
||||||
if (curInner.innerStyle) {
|
if (curInner.innerStyle) {
|
||||||
if (innerToken) innerToken = innerToken + ' ' + curInner.innerStyle;
|
if (innerToken) innerToken = innerToken + " " + curInner.innerStyle;
|
||||||
else innerToken = curInner.innerStyle;
|
else innerToken = curInner.innerStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +100,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
|
|||||||
mode.blankLine(state.innerActive ? state.inner : state.outer);
|
mode.blankLine(state.innerActive ? state.inner : state.outer);
|
||||||
}
|
}
|
||||||
if (!state.innerActive) {
|
if (!state.innerActive) {
|
||||||
for (var i = 0; i < n_others; ++i) {
|
for (var i = 0; i < others.length; ++i) {
|
||||||
var other = others[i];
|
var other = others[i];
|
||||||
if (other.open === "\n") {
|
if (other.open === "\n") {
|
||||||
state.innerActive = other;
|
state.innerActive = other;
|
||||||
|
@ -29,5 +29,5 @@
|
|||||||
|
|
||||||
MT(
|
MT(
|
||||||
"stexInsideMarkdown",
|
"stexInsideMarkdown",
|
||||||
"[strong **Equation:**] [delim $][inner&tag \\pi][delim $]");
|
"[strong **Equation:**] [delim&delim-open $][inner&tag \\pi][delim&delim-close $]");
|
||||||
})();
|
})();
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
|
|
||||||
function ensureState(states, name) {
|
function ensureState(states, name) {
|
||||||
if (!states.hasOwnProperty(name))
|
if (!states.hasOwnProperty(name))
|
||||||
throw new Error("Undefined state " + name + "in simple mode");
|
throw new Error("Undefined state " + name + " in simple mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
function toRegex(val, caret) {
|
function toRegex(val, caret) {
|
||||||
|
@ -16,7 +16,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) {
|
|||||||
var ie = /MSIE \d/.test(navigator.userAgent);
|
var ie = /MSIE \d/.test(navigator.userAgent);
|
||||||
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
|
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
|
||||||
|
|
||||||
if (callback.nodeType == 1) {
|
if (callback.appendChild) {
|
||||||
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
|
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
|
||||||
var node = callback, col = 0;
|
var node = callback, col = 0;
|
||||||
node.innerHTML = "";
|
node.innerHTML = "";
|
||||||
|
@ -3,19 +3,37 @@
|
|||||||
|
|
||||||
/* Just enough of CodeMirror to run runMode under node.js */
|
/* Just enough of CodeMirror to run runMode under node.js */
|
||||||
|
|
||||||
// declare global: StringStream
|
function splitLines(string){return string.split(/\r\n?|\n/);};
|
||||||
|
|
||||||
function splitLines(string){ return string.split(/\r?\n|\r/); };
|
// Counts the column offset in a string, taking tabs into account.
|
||||||
|
// Used mostly to find indentation.
|
||||||
|
var countColumn = function(string, end, tabSize, startIndex, startValue) {
|
||||||
|
if (end == null) {
|
||||||
|
end = string.search(/[^\s\u00a0]/);
|
||||||
|
if (end == -1) end = string.length;
|
||||||
|
}
|
||||||
|
for (var i = startIndex || 0, n = startValue || 0;;) {
|
||||||
|
var nextTab = string.indexOf("\t", i);
|
||||||
|
if (nextTab < 0 || nextTab >= end)
|
||||||
|
return n + (end - i);
|
||||||
|
n += nextTab - i;
|
||||||
|
n += tabSize - (n % tabSize);
|
||||||
|
i = nextTab + 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function StringStream(string) {
|
function StringStream(string, tabSize) {
|
||||||
this.pos = this.start = 0;
|
this.pos = this.start = 0;
|
||||||
this.string = string;
|
this.string = string;
|
||||||
|
this.tabSize = tabSize || 8;
|
||||||
|
this.lastColumnPos = this.lastColumnValue = 0;
|
||||||
this.lineStart = 0;
|
this.lineStart = 0;
|
||||||
}
|
};
|
||||||
|
|
||||||
StringStream.prototype = {
|
StringStream.prototype = {
|
||||||
eol: function() {return this.pos >= this.string.length;},
|
eol: function() {return this.pos >= this.string.length;},
|
||||||
sol: function() {return this.pos == 0;},
|
sol: function() {return this.pos == this.lineStart;},
|
||||||
peek: function() {return this.string.charAt(this.pos) || null;},
|
peek: function() {return this.string.charAt(this.pos) || undefined;},
|
||||||
next: function() {
|
next: function() {
|
||||||
if (this.pos < this.string.length)
|
if (this.pos < this.string.length)
|
||||||
return this.string.charAt(this.pos++);
|
return this.string.charAt(this.pos++);
|
||||||
@ -42,8 +60,17 @@ StringStream.prototype = {
|
|||||||
if (found > -1) {this.pos = found; return true;}
|
if (found > -1) {this.pos = found; return true;}
|
||||||
},
|
},
|
||||||
backUp: function(n) {this.pos -= n;},
|
backUp: function(n) {this.pos -= n;},
|
||||||
column: function() {return this.start - this.lineStart;},
|
column: function() {
|
||||||
indentation: function() {return 0;},
|
if (this.lastColumnPos < this.start) {
|
||||||
|
this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
|
||||||
|
this.lastColumnPos = this.start;
|
||||||
|
}
|
||||||
|
return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
|
||||||
|
},
|
||||||
|
indentation: function() {
|
||||||
|
return countColumn(this.string, null, this.tabSize) -
|
||||||
|
(this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
|
||||||
|
},
|
||||||
match: function(pattern, consume, caseInsensitive) {
|
match: function(pattern, consume, caseInsensitive) {
|
||||||
if (typeof pattern == "string") {
|
if (typeof pattern == "string") {
|
||||||
var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
|
var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
|
||||||
@ -94,11 +121,42 @@ exports.resolveMode = function(spec) {
|
|||||||
if (typeof spec == "string") return {name: spec};
|
if (typeof spec == "string") return {name: spec};
|
||||||
else return spec || {name: "null"};
|
else return spec || {name: "null"};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function copyObj(obj, target, overwrite) {
|
||||||
|
if (!target) target = {};
|
||||||
|
for (var prop in obj)
|
||||||
|
if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
|
||||||
|
target[prop] = obj[prop];
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This can be used to attach properties to mode objects from
|
||||||
|
// outside the actual mode definition.
|
||||||
|
var modeExtensions = exports.modeExtensions = {};
|
||||||
|
exports.extendMode = function(mode, properties) {
|
||||||
|
var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
|
||||||
|
copyObj(properties, exts);
|
||||||
|
};
|
||||||
|
|
||||||
exports.getMode = function(options, spec) {
|
exports.getMode = function(options, spec) {
|
||||||
spec = exports.resolveMode(spec);
|
var spec = exports.resolveMode(spec);
|
||||||
var mfactory = modes[spec.name];
|
var mfactory = modes[spec.name];
|
||||||
if (!mfactory) throw new Error("Unknown mode: " + spec);
|
if (!mfactory) return exports.getMode(options, "text/plain");
|
||||||
return mfactory(options, spec);
|
var modeObj = mfactory(options, spec);
|
||||||
|
if (modeExtensions.hasOwnProperty(spec.name)) {
|
||||||
|
var exts = modeExtensions[spec.name];
|
||||||
|
for (var prop in exts) {
|
||||||
|
if (!exts.hasOwnProperty(prop)) continue;
|
||||||
|
if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
|
||||||
|
modeObj[prop] = exts[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modeObj.name = spec.name;
|
||||||
|
if (spec.helperType) modeObj.helperType = spec.helperType;
|
||||||
|
if (spec.modeProps) for (var prop in spec.modeProps)
|
||||||
|
modeObj[prop] = spec.modeProps[prop];
|
||||||
|
|
||||||
|
return modeObj;
|
||||||
};
|
};
|
||||||
exports.registerHelper = exports.registerGlobalHelper = Math.min;
|
exports.registerHelper = exports.registerGlobalHelper = Math.min;
|
||||||
|
|
||||||
@ -118,3 +176,4 @@ exports.runMode = function(string, modespec, callback, options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")];
|
require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")];
|
||||||
|
require.cache[require.resolve("../../addon/runmode/runmode")] = require.cache[require.resolve("./runmode.node")];
|
||||||
|
@ -11,28 +11,47 @@
|
|||||||
})(function(CodeMirror) {
|
})(function(CodeMirror) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
CodeMirror.defineExtension("annotateScrollbar", function(className) {
|
CodeMirror.defineExtension("annotateScrollbar", function(options) {
|
||||||
return new Annotation(this, className);
|
if (typeof options == "string") options = {className: options};
|
||||||
|
return new Annotation(this, options);
|
||||||
});
|
});
|
||||||
|
|
||||||
function Annotation(cm, className) {
|
CodeMirror.defineOption("scrollButtonHeight", 0);
|
||||||
|
|
||||||
|
function Annotation(cm, options) {
|
||||||
this.cm = cm;
|
this.cm = cm;
|
||||||
this.className = className;
|
this.options = options;
|
||||||
|
this.buttonHeight = options.scrollButtonHeight || cm.getOption("scrollButtonHeight");
|
||||||
this.annotations = [];
|
this.annotations = [];
|
||||||
|
this.doRedraw = this.doUpdate = null;
|
||||||
this.div = cm.getWrapperElement().appendChild(document.createElement("div"));
|
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.div.style.cssText = "position: absolute; right: 0; top: 0; z-index: 7; pointer-events: none";
|
||||||
this.computeScale();
|
this.computeScale();
|
||||||
|
|
||||||
|
function scheduleRedraw(delay) {
|
||||||
|
clearTimeout(self.doRedraw);
|
||||||
|
self.doRedraw = setTimeout(function() { self.redraw(); }, delay);
|
||||||
|
}
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
cm.on("refresh", this.resizeHandler = function(){
|
cm.on("refresh", this.resizeHandler = function() {
|
||||||
if (self.computeScale()) self.redraw();
|
clearTimeout(self.doUpdate);
|
||||||
|
self.doUpdate = setTimeout(function() {
|
||||||
|
if (self.computeScale()) scheduleRedraw(20);
|
||||||
|
}, 100);
|
||||||
});
|
});
|
||||||
|
cm.on("markerAdded", this.resizeHandler);
|
||||||
|
cm.on("markerCleared", this.resizeHandler);
|
||||||
|
if (options.listenForChanges !== false)
|
||||||
|
cm.on("change", this.changeHandler = function() {
|
||||||
|
scheduleRedraw(250);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Annotation.prototype.computeScale = function() {
|
Annotation.prototype.computeScale = function() {
|
||||||
var cm = this.cm;
|
var cm = this.cm;
|
||||||
var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight) /
|
var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight - this.buttonHeight * 2) /
|
||||||
cm.heightAtLine(cm.lastLine() + 1, "local");
|
cm.getScrollerElement().scrollHeight
|
||||||
if (hScale != this.hScale) {
|
if (hScale != this.hScale) {
|
||||||
this.hScale = hScale;
|
this.hScale = hScale;
|
||||||
return true;
|
return true;
|
||||||
@ -44,26 +63,46 @@
|
|||||||
this.redraw();
|
this.redraw();
|
||||||
};
|
};
|
||||||
|
|
||||||
Annotation.prototype.redraw = function() {
|
Annotation.prototype.redraw = function(compute) {
|
||||||
|
if (compute !== false) this.computeScale();
|
||||||
var cm = this.cm, hScale = this.hScale;
|
var cm = this.cm, hScale = this.hScale;
|
||||||
if (!cm.display.barWidth) return;
|
|
||||||
|
|
||||||
var frag = document.createDocumentFragment(), anns = this.annotations;
|
var frag = document.createDocumentFragment(), anns = this.annotations;
|
||||||
for (var i = 0, nextTop; i < anns.length; i++) {
|
|
||||||
|
var wrapping = cm.getOption("lineWrapping");
|
||||||
|
var singleLineH = wrapping && cm.defaultTextHeight() * 1.5;
|
||||||
|
var curLine = null, curLineObj = null;
|
||||||
|
function getY(pos, top) {
|
||||||
|
if (curLine != pos.line) {
|
||||||
|
curLine = pos.line;
|
||||||
|
curLineObj = cm.getLineHandle(curLine);
|
||||||
|
}
|
||||||
|
if (wrapping && curLineObj.height > singleLineH)
|
||||||
|
return cm.charCoords(pos, "local")[top ? "top" : "bottom"];
|
||||||
|
var topY = cm.heightAtLine(curLineObj, "local");
|
||||||
|
return topY + (top ? 0 : curLineObj.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cm.display.barWidth) for (var i = 0, nextTop; i < anns.length; i++) {
|
||||||
var ann = anns[i];
|
var ann = anns[i];
|
||||||
var top = nextTop || cm.charCoords(ann.from, "local").top * hScale;
|
var top = nextTop || getY(ann.from, true) * hScale;
|
||||||
var bottom = cm.charCoords(ann.to, "local").bottom * hScale;
|
var bottom = getY(ann.to, false) * hScale;
|
||||||
while (i < anns.length - 1) {
|
while (i < anns.length - 1) {
|
||||||
nextTop = cm.charCoords(anns[i + 1].from, "local").top * hScale;
|
nextTop = getY(anns[i + 1].from, true) * hScale;
|
||||||
if (nextTop > bottom + .9) break;
|
if (nextTop > bottom + .9) break;
|
||||||
ann = anns[++i];
|
ann = anns[++i];
|
||||||
bottom = cm.charCoords(ann.to, "local").bottom * hScale;
|
bottom = getY(ann.to, false) * hScale;
|
||||||
}
|
}
|
||||||
|
if (bottom == top) continue;
|
||||||
var height = Math.max(bottom - top, 3);
|
var height = Math.max(bottom - top, 3);
|
||||||
|
|
||||||
var elt = frag.appendChild(document.createElement("div"));
|
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.style.cssText = "position: absolute; right: 0px; width: " + Math.max(cm.display.barWidth - 1, 2) + "px; top: "
|
||||||
elt.className = this.className;
|
+ (top + this.buttonHeight) + "px; height: " + height + "px";
|
||||||
|
elt.className = this.options.className;
|
||||||
|
if (ann.id) {
|
||||||
|
elt.setAttribute("annotation-id", ann.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.div.textContent = "";
|
this.div.textContent = "";
|
||||||
this.div.appendChild(frag);
|
this.div.appendChild(frag);
|
||||||
@ -71,6 +110,9 @@
|
|||||||
|
|
||||||
Annotation.prototype.clear = function() {
|
Annotation.prototype.clear = function() {
|
||||||
this.cm.off("refresh", this.resizeHandler);
|
this.cm.off("refresh", this.resizeHandler);
|
||||||
|
this.cm.off("markerAdded", this.resizeHandler);
|
||||||
|
this.cm.off("markerCleared", this.resizeHandler);
|
||||||
|
if (this.changeHandler) this.cm.off("change", this.changeHandler);
|
||||||
this.div.parentNode.removeChild(this.div);
|
this.div.parentNode.removeChild(this.div);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -59,26 +59,35 @@
|
|||||||
CodeMirror.on(this.node, "DOMMouseScroll", onWheel);
|
CodeMirror.on(this.node, "DOMMouseScroll", onWheel);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bar.prototype.moveTo = function(pos, update) {
|
Bar.prototype.setPos = function(pos) {
|
||||||
if (pos < 0) pos = 0;
|
if (pos < 0) pos = 0;
|
||||||
if (pos > this.total - this.screen) pos = this.total - this.screen;
|
if (pos > this.total - this.screen) pos = this.total - this.screen;
|
||||||
if (pos == this.pos) return;
|
if (pos == this.pos) return false;
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
|
this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
|
||||||
(pos * (this.size / this.total)) + "px";
|
(pos * (this.size / this.total)) + "px";
|
||||||
if (update !== false) this.scroll(pos, this.orientation);
|
return true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Bar.prototype.moveTo = function(pos) {
|
||||||
|
if (this.setPos(pos)) this.scroll(pos, this.orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
var minButtonSize = 10;
|
||||||
|
|
||||||
Bar.prototype.update = function(scrollSize, clientSize, barSize) {
|
Bar.prototype.update = function(scrollSize, clientSize, barSize) {
|
||||||
this.screen = clientSize;
|
this.screen = clientSize;
|
||||||
this.total = scrollSize;
|
this.total = scrollSize;
|
||||||
this.size = barSize;
|
this.size = barSize;
|
||||||
|
|
||||||
// FIXME clip to min size?
|
var buttonSize = this.screen * (this.size / this.total);
|
||||||
|
if (buttonSize < minButtonSize) {
|
||||||
|
this.size -= minButtonSize - buttonSize;
|
||||||
|
buttonSize = minButtonSize;
|
||||||
|
}
|
||||||
this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
|
this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
|
||||||
this.screen * (this.size / this.total) + "px";
|
buttonSize + "px";
|
||||||
this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
|
this.setPos(this.pos);
|
||||||
this.pos * (this.size / this.total) + "px";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function SimpleScrollbars(cls, place, scroll) {
|
function SimpleScrollbars(cls, place, scroll) {
|
||||||
@ -105,7 +114,6 @@
|
|||||||
if (needsV) {
|
if (needsV) {
|
||||||
this.vert.update(measure.scrollHeight, measure.clientHeight,
|
this.vert.update(measure.scrollHeight, measure.clientHeight,
|
||||||
measure.viewHeight - (needsH ? width : 0));
|
measure.viewHeight - (needsH ? width : 0));
|
||||||
this.vert.node.style.display = "block";
|
|
||||||
this.vert.node.style.bottom = needsH ? width + "px" : "0";
|
this.vert.node.style.bottom = needsH ? width + "px" : "0";
|
||||||
}
|
}
|
||||||
if (needsH) {
|
if (needsH) {
|
||||||
@ -119,11 +127,11 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
SimpleScrollbars.prototype.setScrollTop = function(pos) {
|
SimpleScrollbars.prototype.setScrollTop = function(pos) {
|
||||||
this.vert.moveTo(pos, false);
|
this.vert.setPos(pos);
|
||||||
};
|
};
|
||||||
|
|
||||||
SimpleScrollbars.prototype.setScrollLeft = function(pos) {
|
SimpleScrollbars.prototype.setScrollLeft = function(pos) {
|
||||||
this.horiz.moveTo(pos, false);
|
this.horiz.setPos(pos);
|
||||||
};
|
};
|
||||||
|
|
||||||
SimpleScrollbars.prototype.clear = function() {
|
SimpleScrollbars.prototype.clear = function() {
|
||||||
|
49
web/pgadmin/static/js/codemirror/addon/search/jump-to-line.js
vendored
Normal file
49
web/pgadmin/static/js/codemirror/addon/search/jump-to-line.js
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
// Defines jumpToLine command. Uses dialog.js if present.
|
||||||
|
|
||||||
|
(function(mod) {
|
||||||
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
|
mod(require("../../lib/codemirror"), require("../dialog/dialog"));
|
||||||
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
|
define(["../../lib/codemirror", "../dialog/dialog"], mod);
|
||||||
|
else // Plain browser env
|
||||||
|
mod(CodeMirror);
|
||||||
|
})(function(CodeMirror) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function dialog(cm, text, shortText, deflt, f) {
|
||||||
|
if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true});
|
||||||
|
else f(prompt(shortText, deflt));
|
||||||
|
}
|
||||||
|
|
||||||
|
var jumpDialog =
|
||||||
|
'Jump to line: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use line:column or scroll% syntax)</span>';
|
||||||
|
|
||||||
|
function interpretLine(cm, string) {
|
||||||
|
var num = Number(string)
|
||||||
|
if (/^[-+]/.test(string)) return cm.getCursor().line + num
|
||||||
|
else return num - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeMirror.commands.jumpToLine = function(cm) {
|
||||||
|
var cur = cm.getCursor();
|
||||||
|
dialog(cm, jumpDialog, "Jump to line:", (cur.line + 1) + ":" + cur.ch, function(posStr) {
|
||||||
|
if (!posStr) return;
|
||||||
|
|
||||||
|
var match;
|
||||||
|
if (match = /^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(posStr)) {
|
||||||
|
cm.setCursor(interpretLine(cm, match[1]), Number(match[2]))
|
||||||
|
} else if (match = /^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(posStr)) {
|
||||||
|
var line = Math.round(cm.lineCount() * Number(match[1]) / 100);
|
||||||
|
if (/^[-+]/.test(match[1])) line = cur.line + line + 1;
|
||||||
|
cm.setCursor(line - 1, cur.ch);
|
||||||
|
} else if (match = /^\s*\:?\s*([\+\-]?\d+)\s*/.exec(posStr)) {
|
||||||
|
cm.setCursor(interpretLine(cm, match[1]), cur.ch);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
CodeMirror.keyMap["default"]["Alt-G"] = "jumpToLine";
|
||||||
|
});
|
@ -16,42 +16,40 @@
|
|||||||
// highlighted only if the selected text is a word. showToken, when enabled,
|
// highlighted only if the selected text is a word. showToken, when enabled,
|
||||||
// will cause the current token to be highlighted when nothing is selected.
|
// 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
|
// delay is used to specify how much time to wait, in milliseconds, before
|
||||||
// highlighting the matches.
|
// highlighting the matches. If annotateScrollbar is enabled, the occurences
|
||||||
|
// will be highlighted on the scrollbar via the matchesonscrollbar addon.
|
||||||
|
|
||||||
(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("./matchesonscrollbar"));
|
||||||
else if (typeof define == "function" && define.amd) // AMD
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
define(["../../lib/codemirror"], mod);
|
define(["../../lib/codemirror", "./matchesonscrollbar"], mod);
|
||||||
else // Plain browser env
|
else // Plain browser env
|
||||||
mod(CodeMirror);
|
mod(CodeMirror);
|
||||||
})(function(CodeMirror) {
|
})(function(CodeMirror) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var DEFAULT_MIN_CHARS = 2;
|
var defaults = {
|
||||||
var DEFAULT_TOKEN_STYLE = "matchhighlight";
|
style: "matchhighlight",
|
||||||
var DEFAULT_DELAY = 100;
|
minChars: 2,
|
||||||
var DEFAULT_WORDS_ONLY = false;
|
delay: 100,
|
||||||
|
wordsOnly: false,
|
||||||
|
annotateScrollbar: false,
|
||||||
|
showToken: false,
|
||||||
|
trim: true
|
||||||
|
}
|
||||||
|
|
||||||
function State(options) {
|
function State(options) {
|
||||||
if (typeof options == "object") {
|
this.options = {}
|
||||||
this.minChars = options.minChars;
|
for (var name in defaults)
|
||||||
this.style = options.style;
|
this.options[name] = (options && options.hasOwnProperty(name) ? options : defaults)[name]
|
||||||
this.showToken = options.showToken;
|
|
||||||
this.delay = options.delay;
|
|
||||||
this.wordsOnly = options.wordsOnly;
|
|
||||||
}
|
|
||||||
if (this.style == null) this.style = DEFAULT_TOKEN_STYLE;
|
|
||||||
if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS;
|
|
||||||
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;
|
||||||
|
this.matchesonscroll = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeMirror.defineOption("highlightSelectionMatches", false, function(cm, val, old) {
|
CodeMirror.defineOption("highlightSelectionMatches", false, function(cm, val, old) {
|
||||||
if (old && old != CodeMirror.Init) {
|
if (old && old != CodeMirror.Init) {
|
||||||
var over = cm.state.matchHighlighter.overlay;
|
removeOverlay(cm);
|
||||||
if (over) cm.removeOverlay(over);
|
|
||||||
clearTimeout(cm.state.matchHighlighter.timeout);
|
clearTimeout(cm.state.matchHighlighter.timeout);
|
||||||
cm.state.matchHighlighter = null;
|
cm.state.matchHighlighter = null;
|
||||||
cm.off("cursorActivity", cursorActivity);
|
cm.off("cursorActivity", cursorActivity);
|
||||||
@ -66,31 +64,51 @@
|
|||||||
function cursorActivity(cm) {
|
function cursorActivity(cm) {
|
||||||
var state = cm.state.matchHighlighter;
|
var state = cm.state.matchHighlighter;
|
||||||
clearTimeout(state.timeout);
|
clearTimeout(state.timeout);
|
||||||
state.timeout = setTimeout(function() {highlightMatches(cm);}, state.delay);
|
state.timeout = setTimeout(function() {highlightMatches(cm);}, state.options.delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addOverlay(cm, query, hasBoundary, style) {
|
||||||
|
var state = cm.state.matchHighlighter;
|
||||||
|
cm.addOverlay(state.overlay = makeOverlay(query, hasBoundary, style));
|
||||||
|
if (state.options.annotateScrollbar && cm.showMatchesOnScrollbar) {
|
||||||
|
var searchFor = hasBoundary ? new RegExp("\\b" + query + "\\b") : query;
|
||||||
|
state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, true,
|
||||||
|
{className: "CodeMirror-selection-highlight-scrollbar"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeOverlay(cm) {
|
||||||
|
var state = cm.state.matchHighlighter;
|
||||||
|
if (state.overlay) {
|
||||||
|
cm.removeOverlay(state.overlay);
|
||||||
|
state.overlay = null;
|
||||||
|
if (state.matchesonscroll) {
|
||||||
|
state.matchesonscroll.clear();
|
||||||
|
state.matchesonscroll = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function highlightMatches(cm) {
|
function highlightMatches(cm) {
|
||||||
cm.operation(function() {
|
cm.operation(function() {
|
||||||
var state = cm.state.matchHighlighter;
|
var state = cm.state.matchHighlighter;
|
||||||
if (state.overlay) {
|
removeOverlay(cm);
|
||||||
cm.removeOverlay(state.overlay);
|
if (!cm.somethingSelected() && state.options.showToken) {
|
||||||
state.overlay = null;
|
var re = state.options.showToken === true ? /[\w$]/ : state.options.showToken;
|
||||||
}
|
|
||||||
if (!cm.somethingSelected() && state.showToken) {
|
|
||||||
var re = state.showToken === true ? /[\w$]/ : state.showToken;
|
|
||||||
var cur = cm.getCursor(), line = cm.getLine(cur.line), start = cur.ch, end = start;
|
var cur = cm.getCursor(), line = cm.getLine(cur.line), start = cur.ch, end = start;
|
||||||
while (start && re.test(line.charAt(start - 1))) --start;
|
while (start && re.test(line.charAt(start - 1))) --start;
|
||||||
while (end < line.length && re.test(line.charAt(end))) ++end;
|
while (end < line.length && re.test(line.charAt(end))) ++end;
|
||||||
if (start < end)
|
if (start < end)
|
||||||
cm.addOverlay(state.overlay = makeOverlay(line.slice(start, end), re, state.style));
|
addOverlay(cm, line.slice(start, end), re, state.options.style);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var from = cm.getCursor("from"), to = cm.getCursor("to");
|
var from = cm.getCursor("from"), to = cm.getCursor("to");
|
||||||
if (from.line != to.line) return;
|
if (from.line != to.line) return;
|
||||||
if (state.wordsOnly && !isWord(cm, from, to)) return;
|
if (state.options.wordsOnly && !isWord(cm, from, to)) return;
|
||||||
var selection = cm.getRange(from, to).replace(/^\s+|\s+$/g, "");
|
var selection = cm.getRange(from, to)
|
||||||
if (selection.length >= state.minChars)
|
if (state.options.trim) selection = selection.replace(/^\s+|\s+$/g, "")
|
||||||
cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style));
|
if (selection.length >= state.options.minChars)
|
||||||
|
addOverlay(cm, selection, false, state.options.style);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,13 +11,19 @@
|
|||||||
})(function(CodeMirror) {
|
})(function(CodeMirror) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, className) {
|
CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, options) {
|
||||||
return new SearchAnnotation(this, query, caseFold, className);
|
if (typeof options == "string") options = {className: options};
|
||||||
|
if (!options) options = {};
|
||||||
|
return new SearchAnnotation(this, query, caseFold, options);
|
||||||
});
|
});
|
||||||
|
|
||||||
function SearchAnnotation(cm, query, caseFold, className) {
|
function SearchAnnotation(cm, query, caseFold, options) {
|
||||||
this.cm = cm;
|
this.cm = cm;
|
||||||
this.annotation = cm.annotateScrollbar(className || "CodeMirror-search-match");
|
this.options = options;
|
||||||
|
var annotateOptions = {listenForChanges: false};
|
||||||
|
for (var prop in options) annotateOptions[prop] = options[prop];
|
||||||
|
if (!annotateOptions.className) annotateOptions.className = "CodeMirror-search-match";
|
||||||
|
this.annotation = cm.annotateScrollbar(annotateOptions);
|
||||||
this.query = query;
|
this.query = query;
|
||||||
this.caseFold = caseFold;
|
this.caseFold = caseFold;
|
||||||
this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1};
|
this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1};
|
||||||
@ -41,11 +47,12 @@
|
|||||||
if (match.to.line >= this.gap.from) this.matches.splice(i--, 1);
|
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);
|
var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), this.caseFold);
|
||||||
|
var maxMatches = this.options && this.options.maxMatches || MAX_MATCHES;
|
||||||
while (cursor.findNext()) {
|
while (cursor.findNext()) {
|
||||||
var match = {from: cursor.from(), to: cursor.to()};
|
var match = {from: cursor.from(), to: cursor.to()};
|
||||||
if (match.from.line >= this.gap.to) break;
|
if (match.from.line >= this.gap.to) break;
|
||||||
this.matches.splice(i++, 0, match);
|
this.matches.splice(i++, 0, match);
|
||||||
if (this.matches.length > MAX_MATCHES) break;
|
if (this.matches.length > maxMatches) break;
|
||||||
}
|
}
|
||||||
this.gap = null;
|
this.gap = null;
|
||||||
};
|
};
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
mod(CodeMirror);
|
mod(CodeMirror);
|
||||||
})(function(CodeMirror) {
|
})(function(CodeMirror) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function searchOverlay(query, caseInsensitive) {
|
function searchOverlay(query, caseInsensitive) {
|
||||||
if (typeof query == "string")
|
if (typeof query == "string")
|
||||||
query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
|
query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
|
||||||
@ -28,7 +29,7 @@
|
|||||||
query.lastIndex = stream.pos;
|
query.lastIndex = stream.pos;
|
||||||
var match = query.exec(stream.string);
|
var match = query.exec(stream.string);
|
||||||
if (match && match.index == stream.pos) {
|
if (match && match.index == stream.pos) {
|
||||||
stream.pos += match[0].length;
|
stream.pos += match[0].length || 1;
|
||||||
return "searching";
|
return "searching";
|
||||||
} else if (match) {
|
} else if (match) {
|
||||||
stream.pos = match.index;
|
stream.pos = match.index;
|
||||||
@ -39,59 +40,112 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function SearchState() {
|
function SearchState() {
|
||||||
this.posFrom = this.posTo = this.query = null;
|
this.posFrom = this.posTo = this.lastQuery = this.query = null;
|
||||||
this.overlay = null;
|
this.overlay = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSearchState(cm) {
|
function getSearchState(cm) {
|
||||||
return cm.state.search || (cm.state.search = new SearchState());
|
return cm.state.search || (cm.state.search = new SearchState());
|
||||||
}
|
}
|
||||||
|
|
||||||
function queryCaseInsensitive(query) {
|
function queryCaseInsensitive(query) {
|
||||||
return typeof query == "string" && query == query.toLowerCase();
|
return typeof query == "string" && query == query.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSearchCursor(cm, query, pos) {
|
function getSearchCursor(cm, query, pos) {
|
||||||
// Heuristic: if the query string is all lowercase, do a case insensitive search.
|
// Heuristic: if the query string is all lowercase, do a case insensitive search.
|
||||||
return cm.getSearchCursor(query, pos, queryCaseInsensitive(query));
|
return cm.getSearchCursor(query, pos, queryCaseInsensitive(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function persistentDialog(cm, text, deflt, f) {
|
||||||
|
cm.openDialog(text, f, {
|
||||||
|
value: deflt,
|
||||||
|
selectValueOnOpen: true,
|
||||||
|
closeOnEnter: false,
|
||||||
|
onClose: function() { clearSearch(cm); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function dialog(cm, text, shortText, deflt, f) {
|
function dialog(cm, text, shortText, deflt, f) {
|
||||||
if (cm.openDialog) cm.openDialog(text, f, {value: deflt});
|
if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true});
|
||||||
else f(prompt(shortText, deflt));
|
else f(prompt(shortText, deflt));
|
||||||
}
|
}
|
||||||
|
|
||||||
function confirmDialog(cm, text, shortText, fs) {
|
function confirmDialog(cm, text, shortText, fs) {
|
||||||
if (cm.openConfirm) cm.openConfirm(text, fs);
|
if (cm.openConfirm) cm.openConfirm(text, fs);
|
||||||
else if (confirm(shortText)) fs[0]();
|
else if (confirm(shortText)) fs[0]();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseString(string) {
|
||||||
|
return string.replace(/\\(.)/g, function(_, ch) {
|
||||||
|
if (ch == "n") return "\n"
|
||||||
|
if (ch == "r") return "\r"
|
||||||
|
return ch
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function parseQuery(query) {
|
function parseQuery(query) {
|
||||||
var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
|
var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
|
||||||
if (isRE) {
|
if (isRE) {
|
||||||
try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
|
try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
|
||||||
catch(e) {} // Not a regular expression after all, do a string search
|
catch(e) {} // Not a regular expression after all, do a string search
|
||||||
|
} else {
|
||||||
|
query = parseString(query)
|
||||||
}
|
}
|
||||||
if (typeof query == "string" ? query == "" : query.test(""))
|
if (typeof query == "string" ? query == "" : query.test(""))
|
||||||
query = /x^/;
|
query = /x^/;
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
var queryDialog =
|
var queryDialog =
|
||||||
'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>';
|
'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 startSearch(cm, state, query) {
|
||||||
|
state.queryText = query;
|
||||||
|
state.query = parseQuery(query);
|
||||||
|
cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
|
||||||
|
state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function doSearch(cm, rev, persistent) {
|
||||||
var state = getSearchState(cm);
|
var state = getSearchState(cm);
|
||||||
if (state.query) return findNext(cm, rev);
|
if (state.query) return findNext(cm, rev);
|
||||||
dialog(cm, queryDialog, "Search for:", cm.getSelection(), function(query) {
|
var q = cm.getSelection() || state.lastQuery;
|
||||||
cm.operation(function() {
|
if (persistent && cm.openDialog) {
|
||||||
if (!query || state.query) return;
|
var hiding = null
|
||||||
state.query = parseQuery(query);
|
persistentDialog(cm, queryDialog, q, function(query, event) {
|
||||||
cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
|
CodeMirror.e_stop(event);
|
||||||
state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
|
if (!query) return;
|
||||||
cm.addOverlay(state.overlay);
|
if (query != state.queryText) {
|
||||||
if (cm.showMatchesOnScrollbar) {
|
startSearch(cm, state, query);
|
||||||
if (state.annotate) { state.annotate.clear(); state.annotate = null; }
|
state.posFrom = state.posTo = cm.getCursor();
|
||||||
state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
|
|
||||||
}
|
}
|
||||||
state.posFrom = state.posTo = cm.getCursor();
|
if (hiding) hiding.style.opacity = 1
|
||||||
findNext(cm, rev);
|
findNext(cm, event.shiftKey, function(_, to) {
|
||||||
|
var dialog
|
||||||
|
if (to.line < 3 && document.querySelector &&
|
||||||
|
(dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) &&
|
||||||
|
dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top)
|
||||||
|
(hiding = dialog).style.opacity = .4
|
||||||
|
})
|
||||||
});
|
});
|
||||||
});
|
} else {
|
||||||
|
dialog(cm, queryDialog, "Search for:", q, function(query) {
|
||||||
|
if (query && !state.query) cm.operation(function() {
|
||||||
|
startSearch(cm, state, query);
|
||||||
|
state.posFrom = state.posTo = cm.getCursor();
|
||||||
|
findNext(cm, rev);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function findNext(cm, rev) {cm.operation(function() {
|
|
||||||
|
function findNext(cm, rev, callback) {cm.operation(function() {
|
||||||
var state = getSearchState(cm);
|
var state = getSearchState(cm);
|
||||||
var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
|
var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
|
||||||
if (!cursor.find(rev)) {
|
if (!cursor.find(rev)) {
|
||||||
@ -99,39 +153,50 @@
|
|||||||
if (!cursor.find(rev)) return;
|
if (!cursor.find(rev)) return;
|
||||||
}
|
}
|
||||||
cm.setSelection(cursor.from(), cursor.to());
|
cm.setSelection(cursor.from(), cursor.to());
|
||||||
cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
|
cm.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20);
|
||||||
state.posFrom = cursor.from(); state.posTo = cursor.to();
|
state.posFrom = cursor.from(); state.posTo = cursor.to();
|
||||||
|
if (callback) callback(cursor.from(), cursor.to())
|
||||||
});}
|
});}
|
||||||
|
|
||||||
function clearSearch(cm) {cm.operation(function() {
|
function clearSearch(cm) {cm.operation(function() {
|
||||||
var state = getSearchState(cm);
|
var state = getSearchState(cm);
|
||||||
|
state.lastQuery = state.query;
|
||||||
if (!state.query) return;
|
if (!state.query) return;
|
||||||
state.query = null;
|
state.query = state.queryText = null;
|
||||||
cm.removeOverlay(state.overlay);
|
cm.removeOverlay(state.overlay);
|
||||||
if (state.annotate) { state.annotate.clear(); state.annotate = null; }
|
if (state.annotate) { state.annotate.clear(); state.annotate = null; }
|
||||||
});}
|
});}
|
||||||
|
|
||||||
var replaceQueryDialog =
|
var replaceQueryDialog =
|
||||||
'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>';
|
' <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" class="CodeMirror-search-field"/>';
|
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>All</button> <button>Stop</button>";
|
||||||
|
|
||||||
|
function replaceAll(cm, query, text) {
|
||||||
|
cm.operation(function() {
|
||||||
|
for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
|
||||||
|
if (typeof query != "string") {
|
||||||
|
var match = cm.getRange(cursor.from(), cursor.to()).match(query);
|
||||||
|
cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
|
||||||
|
} else cursor.replace(text);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function replace(cm, all) {
|
function replace(cm, all) {
|
||||||
if (cm.getOption("readOnly")) return;
|
if (cm.getOption("readOnly")) return;
|
||||||
dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) {
|
var query = cm.getSelection() || getSearchState(cm).lastQuery;
|
||||||
|
var dialogText = all ? "Replace all:" : "Replace:"
|
||||||
|
dialog(cm, dialogText + replaceQueryDialog, dialogText, query, function(query) {
|
||||||
if (!query) return;
|
if (!query) return;
|
||||||
query = parseQuery(query);
|
query = parseQuery(query);
|
||||||
dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
|
dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
|
||||||
|
text = parseString(text)
|
||||||
if (all) {
|
if (all) {
|
||||||
cm.operation(function() {
|
replaceAll(cm, query, text)
|
||||||
for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
|
|
||||||
if (typeof query != "string") {
|
|
||||||
var match = cm.getRange(cursor.from(), cursor.to()).match(query);
|
|
||||||
cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
|
|
||||||
} else cursor.replace(text);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
clearSearch(cm);
|
clearSearch(cm);
|
||||||
var cursor = getSearchCursor(cm, query, cm.getCursor());
|
var cursor = getSearchCursor(cm, query, cm.getCursor("from"));
|
||||||
var advance = function() {
|
var advance = function() {
|
||||||
var start = cursor.from(), match;
|
var start = cursor.from(), match;
|
||||||
if (!(match = cursor.findNext())) {
|
if (!(match = cursor.findNext())) {
|
||||||
@ -142,7 +207,8 @@
|
|||||||
cm.setSelection(cursor.from(), cursor.to());
|
cm.setSelection(cursor.from(), cursor.to());
|
||||||
cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
|
cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
|
||||||
confirmDialog(cm, doReplaceConfirm, "Replace?",
|
confirmDialog(cm, doReplaceConfirm, "Replace?",
|
||||||
[function() {doReplace(match);}, advance]);
|
[function() {doReplace(match);}, advance,
|
||||||
|
function() {replaceAll(cm, query, text)}]);
|
||||||
};
|
};
|
||||||
var doReplace = function(match) {
|
var doReplace = function(match) {
|
||||||
cursor.replace(typeof query == "string" ? text :
|
cursor.replace(typeof query == "string" ? text :
|
||||||
@ -156,6 +222,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
|
CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
|
||||||
|
CodeMirror.commands.findPersistent = function(cm) {clearSearch(cm); doSearch(cm, false, true);};
|
||||||
CodeMirror.commands.findNext = doSearch;
|
CodeMirror.commands.findNext = doSearch;
|
||||||
CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
|
CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
|
||||||
CodeMirror.commands.clearSearch = clearSearch;
|
CodeMirror.commands.clearSearch = clearSearch;
|
||||||
|
@ -148,10 +148,10 @@
|
|||||||
from: function() {if (this.atOccurrence) return this.pos.from;},
|
from: function() {if (this.atOccurrence) return this.pos.from;},
|
||||||
to: function() {if (this.atOccurrence) return this.pos.to;},
|
to: function() {if (this.atOccurrence) return this.pos.to;},
|
||||||
|
|
||||||
replace: function(newText) {
|
replace: function(newText, origin) {
|
||||||
if (!this.atOccurrence) return;
|
if (!this.atOccurrence) return;
|
||||||
var lines = CodeMirror.splitLines(newText);
|
var lines = CodeMirror.splitLines(newText);
|
||||||
this.doc.replaceRange(lines, this.pos.from, this.pos.to);
|
this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin);
|
||||||
this.pos.to = Pos(this.pos.from.line + lines.length - 1,
|
this.pos.to = Pos(this.pos.from.line + lines.length - 1,
|
||||||
lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
|
lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
|
||||||
}
|
}
|
||||||
@ -177,9 +177,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
|
CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
|
||||||
var ranges = [], next;
|
var ranges = [];
|
||||||
var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold);
|
var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold);
|
||||||
while (next = cur.findNext()) {
|
while (cur.findNext()) {
|
||||||
if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break;
|
if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break;
|
||||||
ranges.push({anchor: cur.from(), head: cur.to()});
|
ranges.push({anchor: cur.from(), head: cur.to()});
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
var WRAP_CLASS = "CodeMirror-activeline";
|
var WRAP_CLASS = "CodeMirror-activeline";
|
||||||
var BACK_CLASS = "CodeMirror-activeline-background";
|
var BACK_CLASS = "CodeMirror-activeline-background";
|
||||||
|
var GUTT_CLASS = "CodeMirror-activeline-gutter";
|
||||||
|
|
||||||
CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
|
CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
|
||||||
var prev = old && old != CodeMirror.Init;
|
var prev = old && old != CodeMirror.Init;
|
||||||
@ -36,6 +37,7 @@
|
|||||||
for (var i = 0; i < cm.state.activeLines.length; i++) {
|
for (var i = 0; i < cm.state.activeLines.length; i++) {
|
||||||
cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);
|
cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);
|
||||||
cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);
|
cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);
|
||||||
|
cm.removeLineClass(cm.state.activeLines[i], "gutter", GUTT_CLASS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +62,7 @@
|
|||||||
for (var i = 0; i < active.length; i++) {
|
for (var i = 0; i < active.length; i++) {
|
||||||
cm.addLineClass(active[i], "wrap", WRAP_CLASS);
|
cm.addLineClass(active[i], "wrap", WRAP_CLASS);
|
||||||
cm.addLineClass(active[i], "background", BACK_CLASS);
|
cm.addLineClass(active[i], "background", BACK_CLASS);
|
||||||
|
cm.addLineClass(active[i], "gutter", GUTT_CLASS);
|
||||||
}
|
}
|
||||||
cm.state.activeLines = active;
|
cm.state.activeLines = active;
|
||||||
});
|
});
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
if (data) {
|
if (data) {
|
||||||
CodeMirror.off(cm.getWrapperElement(), "mousemove", data.mousemove);
|
CodeMirror.off(cm.getWrapperElement(), "mousemove", data.mousemove);
|
||||||
CodeMirror.off(cm.getWrapperElement(), "mouseout", data.mouseout);
|
CodeMirror.off(cm.getWrapperElement(), "mouseout", data.mouseout);
|
||||||
|
CodeMirror.off(window, "scroll", data.windowScroll);
|
||||||
cm.off("cursorActivity", reset);
|
cm.off("cursorActivity", reset);
|
||||||
cm.off("scroll", reset);
|
cm.off("scroll", reset);
|
||||||
cm.state.selectionPointer = null;
|
cm.state.selectionPointer = null;
|
||||||
@ -26,12 +27,14 @@
|
|||||||
value: typeof val == "string" ? val : "default",
|
value: typeof val == "string" ? val : "default",
|
||||||
mousemove: function(event) { mousemove(cm, event); },
|
mousemove: function(event) { mousemove(cm, event); },
|
||||||
mouseout: function(event) { mouseout(cm, event); },
|
mouseout: function(event) { mouseout(cm, event); },
|
||||||
|
windowScroll: function() { reset(cm); },
|
||||||
rects: null,
|
rects: null,
|
||||||
mouseX: null, mouseY: null,
|
mouseX: null, mouseY: null,
|
||||||
willUpdate: false
|
willUpdate: false
|
||||||
};
|
};
|
||||||
CodeMirror.on(cm.getWrapperElement(), "mousemove", data.mousemove);
|
CodeMirror.on(cm.getWrapperElement(), "mousemove", data.mousemove);
|
||||||
CodeMirror.on(cm.getWrapperElement(), "mouseout", data.mouseout);
|
CodeMirror.on(cm.getWrapperElement(), "mouseout", data.mouseout);
|
||||||
|
CodeMirror.on(window, "scroll", data.windowScroll);
|
||||||
cm.on("cursorActivity", reset);
|
cm.on("cursorActivity", reset);
|
||||||
cm.on("scroll", reset);
|
cm.on("scroll", reset);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
.CodeMirror-Tern-completion {
|
.CodeMirror-Tern-completion {
|
||||||
padding-left: 22px;
|
padding-left: 22px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
.CodeMirror-Tern-completion:before {
|
.CodeMirror-Tern-completion:before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
this.options = options || {};
|
this.options = options || {};
|
||||||
var plugins = this.options.plugins || (this.options.plugins = {});
|
var plugins = this.options.plugins || (this.options.plugins = {});
|
||||||
if (!plugins.doc_comment) plugins.doc_comment = true;
|
if (!plugins.doc_comment) plugins.doc_comment = true;
|
||||||
|
this.docs = Object.create(null);
|
||||||
if (this.options.useWorker) {
|
if (this.options.useWorker) {
|
||||||
this.server = new WorkerServer(this);
|
this.server = new WorkerServer(this);
|
||||||
} else {
|
} else {
|
||||||
@ -69,7 +70,6 @@
|
|||||||
plugins: plugins
|
plugins: plugins
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.docs = Object.create(null);
|
|
||||||
this.trackChange = function(doc, change) { trackChange(self, doc, change); };
|
this.trackChange = function(doc, change) { trackChange(self, doc, change); };
|
||||||
|
|
||||||
this.cachedArgHints = null;
|
this.cachedArgHints = null;
|
||||||
@ -124,12 +124,22 @@
|
|||||||
var self = this;
|
var self = this;
|
||||||
var doc = findDoc(this, cm.getDoc());
|
var doc = findDoc(this, cm.getDoc());
|
||||||
var request = buildRequest(this, doc, query, pos);
|
var request = buildRequest(this, doc, query, pos);
|
||||||
|
var extraOptions = request.query && this.options.queryOptions && this.options.queryOptions[request.query.type]
|
||||||
|
if (extraOptions) for (var prop in extraOptions) request.query[prop] = extraOptions[prop];
|
||||||
|
|
||||||
this.server.request(request, function (error, data) {
|
this.server.request(request, function (error, data) {
|
||||||
if (!error && self.options.responseFilter)
|
if (!error && self.options.responseFilter)
|
||||||
data = self.options.responseFilter(doc, query, request, error, data);
|
data = self.options.responseFilter(doc, query, request, error, data);
|
||||||
c(error, data);
|
c(error, data);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function () {
|
||||||
|
closeArgHints(this)
|
||||||
|
if (this.worker) {
|
||||||
|
this.worker.terminate();
|
||||||
|
this.worker = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -169,7 +179,7 @@
|
|||||||
var data = findDoc(ts, doc);
|
var data = findDoc(ts, doc);
|
||||||
|
|
||||||
var argHints = ts.cachedArgHints;
|
var argHints = ts.cachedArgHints;
|
||||||
if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) <= 0)
|
if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) >= 0)
|
||||||
ts.cachedArgHints = null;
|
ts.cachedArgHints = null;
|
||||||
|
|
||||||
var changed = data.changed;
|
var changed = data.changed;
|
||||||
@ -207,7 +217,7 @@
|
|||||||
var completion = data.completions[i], className = typeToIcon(completion.type);
|
var completion = data.completions[i], className = typeToIcon(completion.type);
|
||||||
if (data.guess) className += " " + cls + "guess";
|
if (data.guess) className += " " + cls + "guess";
|
||||||
completions.push({text: completion.name + after,
|
completions.push({text: completion.name + after,
|
||||||
displayText: completion.name,
|
displayText: completion.displayName || completion.name,
|
||||||
className: className,
|
className: className,
|
||||||
data: completion});
|
data: completion});
|
||||||
}
|
}
|
||||||
@ -252,10 +262,12 @@
|
|||||||
tip.appendChild(document.createTextNode(" — " + data.doc));
|
tip.appendChild(document.createTextNode(" — " + data.doc));
|
||||||
if (data.url) {
|
if (data.url) {
|
||||||
tip.appendChild(document.createTextNode(" "));
|
tip.appendChild(document.createTextNode(" "));
|
||||||
tip.appendChild(elt("a", null, "[docs]")).href = data.url;
|
var child = tip.appendChild(elt("a", null, "[docs]"));
|
||||||
|
child.href = data.url;
|
||||||
|
child.target = "_blank";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tempTooltip(cm, tip);
|
tempTooltip(cm, tip, ts);
|
||||||
if (c) c();
|
if (c) c();
|
||||||
}, pos);
|
}, pos);
|
||||||
}
|
}
|
||||||
@ -294,7 +306,7 @@
|
|||||||
ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) {
|
ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) {
|
||||||
if (error || !data.type || !(/^fn\(/).test(data.type)) return;
|
if (error || !data.type || !(/^fn\(/).test(data.type)) return;
|
||||||
ts.cachedArgHints = {
|
ts.cachedArgHints = {
|
||||||
start: pos,
|
start: start,
|
||||||
type: parseFnType(data.type),
|
type: parseFnType(data.type),
|
||||||
name: data.exprName || data.name || "fn",
|
name: data.exprName || data.name || "fn",
|
||||||
guess: data.guess,
|
guess: data.guess,
|
||||||
@ -433,8 +445,8 @@
|
|||||||
|
|
||||||
function atInterestingExpression(cm) {
|
function atInterestingExpression(cm) {
|
||||||
var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos);
|
var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos);
|
||||||
if (tok.start < pos.ch && (tok.type == "comment" || tok.type == "string")) return false;
|
if (tok.start < pos.ch && tok.type == "comment") return false;
|
||||||
return /\w/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
|
return /[\w)\]]/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variable renaming
|
// Variable renaming
|
||||||
@ -455,11 +467,12 @@
|
|||||||
ts.request(cm, {type: "refs"}, function(error, data) {
|
ts.request(cm, {type: "refs"}, function(error, data) {
|
||||||
if (error) return showError(ts, cm, error);
|
if (error) return showError(ts, cm, error);
|
||||||
var ranges = [], cur = 0;
|
var ranges = [], cur = 0;
|
||||||
|
var curPos = cm.getCursor();
|
||||||
for (var i = 0; i < data.refs.length; i++) {
|
for (var i = 0; i < data.refs.length; i++) {
|
||||||
var ref = data.refs[i];
|
var ref = data.refs[i];
|
||||||
if (ref.file == name) {
|
if (ref.file == name) {
|
||||||
ranges.push({anchor: ref.start, head: ref.end});
|
ranges.push({anchor: ref.start, head: ref.end});
|
||||||
if (cmpPos(cur, ref.start) >= 0 && cmpPos(cur, ref.end) <= 0)
|
if (cmpPos(curPos, ref.start) >= 0 && cmpPos(curPos, ref.end) <= 0)
|
||||||
cur = ranges.length - 1;
|
cur = ranges.length - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -581,16 +594,34 @@
|
|||||||
|
|
||||||
// Tooltips
|
// Tooltips
|
||||||
|
|
||||||
function tempTooltip(cm, content) {
|
function tempTooltip(cm, content, ts) {
|
||||||
|
if (cm.state.ternTooltip) remove(cm.state.ternTooltip);
|
||||||
var where = cm.cursorCoords();
|
var where = cm.cursorCoords();
|
||||||
var tip = makeTooltip(where.right + 1, where.bottom, content);
|
var tip = cm.state.ternTooltip = makeTooltip(where.right + 1, where.bottom, content);
|
||||||
|
function maybeClear() {
|
||||||
|
old = true;
|
||||||
|
if (!mouseOnTip) clear();
|
||||||
|
}
|
||||||
function clear() {
|
function clear() {
|
||||||
|
cm.state.ternTooltip = null;
|
||||||
if (!tip.parentNode) return;
|
if (!tip.parentNode) return;
|
||||||
cm.off("cursorActivity", clear);
|
cm.off("cursorActivity", clear);
|
||||||
|
cm.off('blur', clear);
|
||||||
|
cm.off('scroll', clear);
|
||||||
fadeOut(tip);
|
fadeOut(tip);
|
||||||
}
|
}
|
||||||
setTimeout(clear, 1700);
|
var mouseOnTip = false, old = false;
|
||||||
|
CodeMirror.on(tip, "mousemove", function() { mouseOnTip = true; });
|
||||||
|
CodeMirror.on(tip, "mouseout", function(e) {
|
||||||
|
if (!CodeMirror.contains(tip, e.relatedTarget || e.toElement)) {
|
||||||
|
if (old) clear();
|
||||||
|
else mouseOnTip = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setTimeout(maybeClear, ts.options.hintDelay ? ts.options.hintDelay : 1700);
|
||||||
cm.on("cursorActivity", clear);
|
cm.on("cursorActivity", clear);
|
||||||
|
cm.on('blur', clear);
|
||||||
|
cm.on('scroll', clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeTooltip(x, y, content) {
|
function makeTooltip(x, y, content) {
|
||||||
@ -615,7 +646,7 @@
|
|||||||
if (ts.options.showError)
|
if (ts.options.showError)
|
||||||
ts.options.showError(cm, msg);
|
ts.options.showError(cm, msg);
|
||||||
else
|
else
|
||||||
tempTooltip(cm, String(msg));
|
tempTooltip(cm, String(msg), ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeArgHints(ts) {
|
function closeArgHints(ts) {
|
||||||
@ -631,7 +662,7 @@
|
|||||||
// Worker wrapper
|
// Worker wrapper
|
||||||
|
|
||||||
function WorkerServer(ts) {
|
function WorkerServer(ts) {
|
||||||
var worker = new Worker(ts.options.workerScript);
|
var worker = ts.worker = new Worker(ts.options.workerScript);
|
||||||
worker.postMessage({type: "init",
|
worker.postMessage({type: "init",
|
||||||
defs: ts.options.defs,
|
defs: ts.options.defs,
|
||||||
plugins: ts.options.plugins,
|
plugins: ts.options.plugins,
|
||||||
|
@ -39,6 +39,6 @@ function startServer(defs, plugins, scripts) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var console = {
|
this.console = {
|
||||||
log: function(v) { postMessage({type: "debug", message: v}); }
|
log: function(v) { postMessage({type: "debug", message: v}); }
|
||||||
};
|
};
|
||||||
|
@ -32,11 +32,13 @@
|
|||||||
function findBreakPoint(text, column, wrapOn, killTrailingSpace) {
|
function findBreakPoint(text, column, wrapOn, killTrailingSpace) {
|
||||||
for (var at = column; at > 0; --at)
|
for (var at = column; at > 0; --at)
|
||||||
if (wrapOn.test(text.slice(at - 1, at + 1))) break;
|
if (wrapOn.test(text.slice(at - 1, at + 1))) break;
|
||||||
if (at == 0) at = column;
|
for (var first = true;; first = false) {
|
||||||
var endOfText = at;
|
var endOfText = at;
|
||||||
if (killTrailingSpace)
|
if (killTrailingSpace)
|
||||||
while (text.charAt(endOfText - 1) == " ") --endOfText;
|
while (text.charAt(endOfText - 1) == " ") --endOfText;
|
||||||
return {from: endOfText, to: at};
|
if (endOfText == 0 && first) at = column;
|
||||||
|
else return {from: endOfText, to: at};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapRange(cm, from, to, options) {
|
function wrapRange(cm, from, to, options) {
|
||||||
@ -86,7 +88,8 @@
|
|||||||
if (changes.length) cm.operation(function() {
|
if (changes.length) cm.operation(function() {
|
||||||
for (var i = 0; i < changes.length; ++i) {
|
for (var i = 0; i < changes.length; ++i) {
|
||||||
var change = changes[i];
|
var change = changes[i];
|
||||||
cm.replaceRange(change.text, change.from, change.to);
|
if (change.text || CodeMirror.cmpPos(change.from, change.to))
|
||||||
|
cm.replaceRange(change.text, change.from, change.to);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null;
|
return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null;
|
||||||
|
2305
web/pgadmin/static/js/codemirror/lib/codemirror.js
vendored
2305
web/pgadmin/static/js/codemirror/lib/codemirror.js
vendored
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
|||||||
define(
|
define(
|
||||||
['jquery','alertify', 'pgadmin','codemirror', 'codemirror/mode/sql',
|
['jquery','alertify', 'pgadmin','codemirror', 'codemirror/mode/sql/sql',
|
||||||
'pgadmin.browser', 'wcdocker'],
|
'pgadmin.browser', 'wcdocker'],
|
||||||
function($, alertify, pgAdmin, CodeMirror) {
|
function($, alertify, pgAdmin, CodeMirror) {
|
||||||
// Some scripts do export their object in the window only.
|
// Some scripts do export their object in the window only.
|
||||||
@ -235,7 +235,7 @@ define(
|
|||||||
lineWrapping: true,
|
lineWrapping: true,
|
||||||
matchBrackets: true,
|
matchBrackets: true,
|
||||||
indentUnit: 4,
|
indentUnit: 4,
|
||||||
mode: "text/x-sql"
|
mode: "text/x-pgsql"
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1402,7 +1402,7 @@ define(
|
|||||||
code_editor_area.get(0), {
|
code_editor_area.get(0), {
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
gutters: ["note-gutter", "CodeMirror-linenumbers", "breakpoints"],
|
gutters: ["note-gutter", "CodeMirror-linenumbers", "breakpoints"],
|
||||||
mode: "text/x-sql",
|
mode: "sql/x-pgsql",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
define(
|
define(
|
||||||
['jquery', 'underscore', 'alertify', 'pgadmin', 'backbone', 'backgrid', 'codemirror',
|
['jquery', 'underscore', 'alertify', 'pgadmin', 'backbone', 'backgrid', 'codemirror',
|
||||||
'codemirror/mode/sql', 'codemirror/addon/selection/mark-selection', 'codemirror/addon/selection/active-line',
|
'codemirror/mode/sql/sql', 'codemirror/addon/selection/mark-selection', 'codemirror/addon/selection/active-line',
|
||||||
'backgrid.select.all', 'backbone.paginator', 'backgrid.paginator', 'backgrid.filter',
|
'backgrid.select.all', 'backbone.paginator', 'backgrid.paginator', 'backgrid.filter',
|
||||||
'bootstrap', 'pgadmin.browser', 'wcdocker'],
|
'bootstrap', 'pgadmin.browser', 'wcdocker'],
|
||||||
function($, _, alertify, pgAdmin, Backbone, Backgrid, CodeMirror) {
|
function($, _, alertify, pgAdmin, Backbone, Backgrid, CodeMirror) {
|
||||||
@ -294,7 +294,7 @@ define(
|
|||||||
lineWrapping: true,
|
lineWrapping: true,
|
||||||
matchBrackets: true,
|
matchBrackets: true,
|
||||||
indentUnit: 4,
|
indentUnit: 4,
|
||||||
mode: "text/x-sql"
|
mode: "text/x-pgsql"
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create main wcDocker instance
|
// Create main wcDocker instance
|
||||||
|
Loading…
Reference in New Issue
Block a user