From 2e6f12725bc01011c545c99c1f1c1da6065063d9 Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Wed, 1 Jan 2014 00:41:45 -0600 Subject: [PATCH 001/315] #1744: Refactor document delta handling Refactor delta handling code to: - Combine the "insertText" and "insertLines" delta types into a single "insert" delta type - Combine the "removeText" and "removeLines" delta types into a single "remove" delta type - Make all document mutations in a single applyDelta function. - Add basic delta validation (more needed . . . see TODOs) - Rework anchor logic to handle new delta types (also simplified) - Rename "insert()" to "insertText()" and "remove()" to "removeText()" - Rename "insertLines()" to "insertFullLines()" and "removeLines()" to "removeFullLines()" See related issue for more information. All tests are passing and the changes appear functional under preliminary testing, but careful review and testing will be necessary. --- lib/ace/anchor.js | 108 +++--- lib/ace/anchor_test.js | 16 +- lib/ace/autocomplete.js | 2 +- lib/ace/background_tokenizer.js | 2 +- lib/ace/background_tokenizer_test.js | 2 +- lib/ace/commands/default_commands.js | 4 +- lib/ace/document.js | 516 +++++++++++++------------ lib/ace/document_test.js | 18 +- lib/ace/edit_session.js | 58 ++- lib/ace/edit_session/folding.js | 2 +- lib/ace/edit_session_test.js | 18 +- lib/ace/editor.js | 39 +- lib/ace/editor_change_document_test.js | 2 +- lib/ace/editor_navigation_test.js | 2 +- lib/ace/ext/chromevox.js | 4 +- lib/ace/ext/elastic_tabstops_lite.js | 2 +- lib/ace/ext/whitespace.js | 2 +- lib/ace/keyboard/vim/commands.js | 10 +- lib/ace/keyboard/vim/maps/motions.js | 6 +- lib/ace/layer/gutter.js | 4 +- lib/ace/line_widgets.js | 2 +- lib/ace/mode/javascript_test.js | 2 +- lib/ace/mode/text.js | 12 +- lib/ace/mouse/dragdrop_handler.js | 2 +- lib/ace/multi_select.js | 10 +- lib/ace/occur_test.js | 12 +- lib/ace/placeholder.js | 12 +- lib/ace/placeholder_test.js | 18 +- 28 files changed, 437 insertions(+), 450 deletions(-) diff --git a/lib/ace/anchor.js b/lib/ace/anchor.js index 3a62e632..91a62eb0 100644 --- a/lib/ace/anchor.js +++ b/lib/ace/anchor.js @@ -100,67 +100,55 @@ var Anchor = exports.Anchor = function(doc, row, column) { * **/ this.onChange = function(e) { - var delta = e.data; - var range = delta.range; - - if (range.start.row == range.end.row && range.start.row != this.row) - return; - - if (range.start.row > this.row) - return; - - if (range.start.row == this.row && range.start.column > this.column) - return; - - var row = this.row; - var column = this.column; - var start = range.start; - var end = range.end; - - if (delta.action === "insertText") { - if (start.row === row && start.column <= column) { - if (start.column === column && this.$insertRight) { - // do nothing - } else if (start.row === end.row) { - column += end.column - start.column; - } else { - column -= start.column; - row += end.row - start.row; - } - } else if (start.row !== end.row && start.row < row) { - row += end.row - start.row; - } - } else if (delta.action === "insertLines") { - if (start.row <= row) { - row += end.row - start.row; - } - } else if (delta.action === "removeText") { - if (start.row === row && start.column < column) { - if (end.column >= column) - column = start.column; - else - column = Math.max(0, column - (end.column - start.column)); - - } else if (start.row !== end.row && start.row < row) { - if (end.row === row) - column = Math.max(0, column - end.column) + start.column; - row -= (end.row - start.row); - } else if (end.row === row) { - row -= end.row - start.row; - column = Math.max(0, column - end.column) + start.column; - } - } else if (delta.action == "removeLines") { - if (start.row <= row) { - if (end.row <= row) - row -= end.row - start.row; - else { - row = start.row; - column = 0; - } - } + + function _pointsInOrder(point1, point2, equalPointsInOrder) + { + var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column; + return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter); } - - this.setPosition(row, column, true); + + function getTransformedPoint(delta, point, moveIfEqual) + { + // Get delta info. + var deltaIsInsert = (delta.action == 'insert') + var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.range.end.row - delta.range.start.row); + var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.range.end.column - delta.range.start.column); + var deltaStart = delta.range.start; + var deltaEnd = (deltaIsInsert ? deltaStart : delta.range.end); // Collapse insert range. + + // DELTA AFTER POINT: No change needed. + if (_pointsInOrder(point, deltaStart, moveIfEqual)) + { + return ( + { + row: point.row, + column: point.column + }); + } + + // DELTA BEFORE POINT: Move point by delta shift. + if (_pointsInOrder(deltaEnd, point, !moveIfEqual)) + { + return ( + { + row: point.row + deltaRowShift, + column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0) + }); + } + + // DELTA ENVELOPS POINT (delete only): Move point to delta start. + if (delta.action != 'delete') + throw 'Delete action expected.'; + return ( + { + row: deltaStart.row, + column: deltaStart.column + }); + } + + var delta = e.data; + var point = getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight); + this.setPosition(point.row, point.column, true); }; /** diff --git a/lib/ace/anchor_test.js b/lib/ace/anchor_test.js index 2d7fcb63..0588c9b6 100644 --- a/lib/ace/anchor_test.js +++ b/lib/ace/anchor_test.js @@ -54,7 +54,7 @@ module.exports = { var doc = new Document("juhu\nkinners"); var anchor = new Anchor(doc, 1, 4); - doc.insert({row: 1, column: 1}, "123"); + doc.insertText({row: 1, column: 1}, "123"); assert.position(anchor.getPosition(), 1, 7); }, @@ -62,7 +62,7 @@ module.exports = { var doc = new Document("juhu\nkinners"); var anchor = new Anchor(doc, 1, 4); - doc.insertLines(1, ["123", "456"]); + doc.insertFullLines(1, ["123", "456"]); assert.position(anchor.getPosition(), 3, 4); }, @@ -70,7 +70,7 @@ module.exports = { var doc = new Document("juhu\nkinners"); var anchor = new Anchor(doc, 1, 4); - doc.insertNewLine({row: 0, column: 0}); + doc.insertLines({row: 0, column: 0}, ['', '']); assert.position(anchor.getPosition(), 2, 4); }, @@ -78,7 +78,7 @@ module.exports = { var doc = new Document("juhu\nkinners"); var anchor = new Anchor(doc, 1, 4); - doc.insertNewLine({row: 1, column: 2}); + doc.insertLines({row: 1, column: 2}, ['', '']); assert.position(anchor.getPosition(), 2, 2); }, @@ -110,7 +110,7 @@ module.exports = { var doc = new Document("juhu\n1\n2\nkinners"); var anchor = new Anchor(doc, 3, 4); - doc.removeLines(1, 2); + doc.removeFullLines(1, 2); assert.position(anchor.getPosition(), 1, 4); }, @@ -134,7 +134,7 @@ module.exports = { var doc = new Document("juhu\nkinners\n123"); var anchor = new Anchor(doc, 1, 5); - doc.removeLines(1, 1); + doc.removeFullLines(1, 1); assert.position(anchor.getPosition(), 1, 0); }, @@ -173,9 +173,9 @@ module.exports = { var doc = new Document("juhu\nkinners\n123"); var anchor = new Anchor(doc, 2, 4); - doc.removeLines(0, 3); + doc.removeFullLines(0, 3); assert.position(anchor.getPosition(), 0, 0); - doc.insertLines(0, ["a", "b", "c"]); + doc.insertFullLines(0, ["a", "b", "c"]); assert.position(anchor.getPosition(), 3, 0); assert.equal(doc.getValue(), "a\nb\nc\n"); } diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index 50154c01..2344aede 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -170,7 +170,7 @@ var Autocomplete = function() { "Ctrl-Down|Ctrl-End": function(editor) { editor.completer.goTo("end"); }, "Esc": function(editor) { editor.completer.detach(); }, - "Space": function(editor) { editor.completer.detach(); editor.insert(" ");}, + "Space": function(editor) { editor.completer.detach(); editor.insertText(" ");}, "Return": function(editor) { editor.completer.insertMatch(); }, "Shift-Return": function(editor) { editor.completer.insertMatch(true); }, "Tab": function(editor) { editor.completer.insertMatch(); }, diff --git a/lib/ace/background_tokenizer.js b/lib/ace/background_tokenizer.js index 217be1b3..cb3ffe23 100644 --- a/lib/ace/background_tokenizer.js +++ b/lib/ace/background_tokenizer.js @@ -183,7 +183,7 @@ var BackgroundTokenizer = function(tokenizer, editor) { if (len === 0) { this.lines[startRow] = null; - } else if (delta.action == "removeText" || delta.action == "removeLines") { + } else if (delta.action == "delete") { this.lines.splice(startRow, len + 1, null); this.states.splice(startRow, len + 1, null); } else { diff --git a/lib/ace/background_tokenizer_test.js b/lib/ace/background_tokenizer_test.js index 7a4cc78c..16c63132 100644 --- a/lib/ace/background_tokenizer_test.js +++ b/lib/ace/background_tokenizer_test.js @@ -70,7 +70,7 @@ module.exports = { forceTokenize(doc) testStates(doc, ["comment_regex_allowed", "comment_regex_allowed"]) - doc.insert({row:0, column:2}, "\n*/") + doc.insertText({row:0, column:2}, "\n*/") testStates(doc, [undefined, undefined, "comment_regex_allowed"]) forceTokenize(doc) diff --git a/lib/ace/commands/default_commands.js b/lib/ace/commands/default_commands.js index e4a8212e..0fd9686c 100644 --- a/lib/ace/commands/default_commands.js +++ b/lib/ace/commands/default_commands.js @@ -508,13 +508,13 @@ exports.commands = [{ scrollIntoView: "selectionPart" }, { name: "insertstring", - exec: function(editor, str) { editor.insert(str); }, + exec: function(editor, str) { editor.insertText(str); }, multiSelectAction: "forEach", scrollIntoView: "cursor" }, { name: "inserttext", exec: function(editor, args) { - editor.insert(lang.stringRepeat(args.text || "", args.times || 1)); + editor.insertText(lang.stringRepeat(args.text || "", args.times || 1)); }, multiSelectAction: "forEach" }, { diff --git a/lib/ace/document.js b/lib/ace/document.js index 75a7920d..ace69e32 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -51,17 +51,17 @@ var Anchor = require("./anchor").Anchor; * @constructor **/ -var Document = function(text) { - this.$lines = []; +var Document = function(textOrLines) { + this.$lines = ['']; // There has to be one line at least in the document. If you pass an empty // string to the insert function, nothing will happen. Workaround. - if (text.length == 0) { + if (textOrLines.length == 0) { this.$lines = [""]; - } else if (Array.isArray(text)) { - this._insertLines(0, text); + } else if (Array.isArray(textOrLines)) { + this.insertLines({row: 0, column: 0}, textOrLines); } else { - this.insert({row: 0, column:0}, text); + this.insertText({row: 0, column:0}, textOrLines); } }; @@ -77,7 +77,7 @@ var Document = function(text) { this.setValue = function(text) { var len = this.getLength(); this.remove(new Range(0, 0, len, this.getLine(len-1).length)); - this.insert({row: 0, column:0}, text); + this.insertText({row: 0, column:0}, text); }; /** @@ -211,27 +211,85 @@ var Document = function(text) { * @returns {String} **/ this.getTextRange = function(range) { + return this._getLinesForRange(range).join(this.getNewLineCharacter()); + }; + + this._getLinesForRange = function(range) { if (range.start.row == range.end.row) { - return this.getLine(range.start.row) - .substring(range.start.column, range.end.column); + return [this.getLine(range.start.row) + .substring(range.start.column, range.end.column)]; } var lines = this.getLines(range.start.row, range.end.row); lines[0] = (lines[0] || "").substring(range.start.column); var l = lines.length - 1; if (range.end.row - range.start.row == l) lines[l] = lines[l].substring(0, range.end.column); - return lines.join(this.getNewLineCharacter()); + return lines; }; this.$clipPosition = function(position) { + var length = this.getLength(); - if (position.row >= length) { + if (position.row >= length) + { position.row = Math.max(0, length - 1); - position.column = this.getLine(length-1).length; - } else if (position.row < 0) - position.row = 0; + position.column = this.getLine(length - 1).length; + } + else + { + position.row = Math.max(0, position.row); + position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length); + } return position; }; + + this.$getClippedRange = function(range) + { + // Get Range object. + if (!range instanceof Range) + range = Range.fromPoints(range.start, range.end); + + // Return clipped range. + this.$clipPosition(range.start); + this.$clipPosition(range.end); + return range; + } + + this.$validateDelta = function(delta) + { + function fnThrow(errorText) + { + errorText = 'Invalid Delta: ' + errorText; + console.log(errorText, delta); + throw errorText; + } + + if (!delta.lines instanceof Array) + { + fnThrow('Delta object lines must be an array'); + } + + if (!delta.range instanceof Range) + { + fnThrow('Range object is not an instance of the Range class'); + } + + var start = delta.range.start; + if (Math.min(Math.max(start.row, 0), this.getLength() - 1 ) != start.row || + Math.min(Math.max(start.column, 0), this.$lines[start.row].length) != start.column) + { + fnThrow('Range start point not contained in document'); + } + + if (delta.lines.length - 1 != delta.range.end.row - delta.range.start.row) + { + fnThrow('Range row offsets does not match delta lines'); + } + + // TODO: Validate that the ending column offset matches the lines. + // TODO: Validate for deletions that the lines deleted match the lines + // in the document. + }, /** * Inserts a block of `text` at the indicated `position`. @@ -240,54 +298,34 @@ var Document = function(text) { * @returns {Object} The position ({row, column}) of the last line of `text`. If the length of `text` is 0, this function simply returns `position`. * **/ - this.insert = function(position, text) { - if (!text || text.length === 0) - return position; - - position = this.$clipPosition(position); - - // only detect new lines if the document has no line break yet + this.insertText = function(position, text) { + + // Only detect new lines if the document has no line break yet. if (this.getLength() <= 1) this.$detectNewLine(text); - - var lines = this.$split(text); - var firstLine = lines.splice(0, 1)[0]; - var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0]; - - position = this.insertInLine(position, firstLine); - if (lastLine !== null) { - position = this.insertNewLine(position); // terminate first line - position = this._insertLines(position.row, lines); - position = this.insertInLine(position, lastLine || ""); - } - return position; + + return this.insertLines(position, this.$split(text)); }; /** - * Fires whenever the document changes. - * - * Several methods trigger different `"change"` events. Below is a list of each action type, followed by each property that's also available: - * - * * `"insertLines"` (emitted by [[Document.insertLines]]) - * * `range`: the [[Range]] of the change within the document - * * `lines`: the lines in the document that are changing - * * `"insertText"` (emitted by [[Document.insertNewLine]]) - * * `range`: the [[Range]] of the change within the document - * * `text`: the text that's being added - * * `"removeLines"` (emitted by [[Document.insertLines]]) - * * `range`: the [[Range]] of the change within the document - * * `lines`: the lines in the document that were removed - * * `nl`: the new line character (as defined by [[Document.getNewLineCharacter]]) - * * `"removeText"` (emitted by [[Document.removeInLine]] and [[Document.removeNewLine]]) - * * `range`: the [[Range]] of the change within the document - * * `text`: the text that's being removed - * - * @event change - * @param {Object} e Contains at least one property called `"action"`. `"action"` indicates the action that triggered the change. Each action also has a set of additional properties. - * - **/ + * Fires whenever the document changes. + * + * Several methods trigger different `"change"` events. Below is a list of each action type, followed by each property that's also available: + * + * * `"insert"` + * * `range`: the [[Range]] of the change within the document + * * `lines`: the lines being added + * * `"delete"` + * * `range`: the [[Range]] of the change within the document + * * `lines`: the lines being removed + * + * @event change + * @param {Object} e Contains at least one property called `"action"`. `"action"` indicates the action that triggered the change. Each action also has a set of additional properties. + * + **/ + /** - * Inserts the elements in `lines` into the document, starting at the row index given by `row`. This method also triggers the `'change'` event. + * Inserts the elements in `lines` into the document as full lines (does not merge with existing line), starting at the row index given by `row`. This method also triggers the `'change'` event. * @param {Number} row The index of the row to insert at * @param {Array} lines An array of strings * @returns {Object} Contains the final row and column, like this: @@ -300,100 +338,62 @@ var Document = function(text) { * ``` * **/ - this.insertLines = function(row, lines) { - if (row >= this.getLength()) - return this.insert({row: row, column: 0}, "\n" + lines.join("\n")); - return this._insertLines(Math.max(row, 0), lines); - }; - this._insertLines = function(row, lines) { - if (lines.length == 0) - return {row: row, column: 0}; - - // apply doesn't work for big arrays (smallest threshold is on safari 0xFFFF) - // to circumvent that we have to break huge inserts into smaller chunks here - if (lines.length > 0xFFFF) { - var end = this._insertLines(row, lines.slice(0xFFFF)); - lines = lines.slice(0, 0xFFFF); + this.insertFullLines = function(row, lines) + { + // Clip to document. + // Allow one past the document end. + row = Math.min(Math.max(row, 0), this.getLength()); + + // Calculate insertion point. + var column = 0; + if (row < this.getLength()) // Insert before the specified row. + { + lines = lines.concat(['']); + column = 0; } + else // Insert after the last row in the document. + { + lines = [''].concat(lines); + row--; + var column = this.$lines[row].length; + } + + // Insert. + this.insertLines({row: row, column: column}, lines); + }, - var args = [row, 0]; - args.push.apply(args, lines); - this.$lines.splice.apply(this.$lines, args); + /** + * Inserts the elements in `lines` into the document, starting at the position index given by `row`. This method also triggers the `'change'` event. + * @param {Number} row The index of the row to insert at + * @param {Array} lines An array of strings + * @returns {Object} Contains the final row and column, like this: + * ``` + * {row: endRow, column: 0} + * ``` + * If `lines` is empty, this function returns an object containing the current row, and column, like this: + * ``` + * {row: row, column: 0} + * ``` + * + **/ + this.insertLines = function(position, lines){ - var range = new Range(row, 0, row + lines.length, 0); - var delta = { - action: "insertLines", - range: range, + // Calculate insertion range end point. + this.$clipPosition(position); + var endPoint = { + row : position.row + lines.length - 1, + column : (lines.length == 1 ? position.column : 0) + lines[lines.length - 1].length + }; + + // Apply delta (emits change). + this.applyDelta({ + action: "insert", + range: Range.fromPoints(position, endPoint), lines: lines - }; - this._emit("change", { data: delta }); - return end || range.end; - }; - - /** - * Inserts a new line into the document at the current row's `position`. This method also triggers the `'change'` event. - * @param {Object} position The position to insert at - * @returns {Object} Returns an object containing the final row and column, like this:
- * ``` - * {row: endRow, column: 0} - * ``` - * - **/ - this.insertNewLine = function(position) { - position = this.$clipPosition(position); - var line = this.$lines[position.row] || ""; - - this.$lines[position.row] = line.substring(0, position.column); - this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length)); - - var end = { - row : position.row + 1, - column : 0 - }; - - var delta = { - action: "insertText", - range: Range.fromPoints(position, end), - text: this.getNewLineCharacter() - }; - this._emit("change", { data: delta }); - - return end; - }; - - /** - * Inserts `text` into the `position` at the current row. This method also triggers the `'change'` event. - * @param {Object} position The position to insert at; it's an object that looks like `{ row: row, column: column}` - * @param {String} text A chunk of text - * @returns {Object} Returns an object containing the final row and column, like this: - * ``` - * {row: endRow, column: 0} - * ``` - * - **/ - this.insertInLine = function(position, text) { - if (text.length == 0) - return position; - - var line = this.$lines[position.row] || ""; - - this.$lines[position.row] = line.substring(0, position.column) + text - + line.substring(position.column); - - var end = { - row : position.row, - column : position.column + text.length - }; - - var delta = { - action: "insertText", - range: Range.fromPoints(position, end), - text: text - }; - this._emit("change", { data: delta }); - - return end; - }; + }); + + return endPoint; + } /** * Removes the `range` from the document. @@ -402,37 +402,16 @@ var Document = function(text) { * **/ this.remove = function(range) { - if (!range instanceof Range) - range = Range.fromPoints(range.start, range.end); - // clip to document - range.start = this.$clipPosition(range.start); - range.end = this.$clipPosition(range.end); - - if (range.isEmpty()) - return range.start; - - var firstRow = range.start.row; - var lastRow = range.end.row; - - if (range.isMultiLine()) { - var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1; - var lastFullRow = lastRow - 1; - - if (range.end.column > 0) - this.removeInLine(lastRow, 0, range.end.column); - - if (lastFullRow >= firstFullRow) - this._removeLines(firstFullRow, lastFullRow); - - if (firstFullRow != firstRow) { - this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length); - this.removeNewLine(range.start.row); - } - } - else { - this.removeInLine(firstRow, range.start.column, range.end.column); - } - return range.start; + + // Apply delta (emits change). + range = this.$getClippedRange(range); + this.applyDelta( + { + action: 'delete', + range: range, + lines: this._getLinesForRange(range), + }); + return range.start; }; /** @@ -444,21 +423,18 @@ var Document = function(text) { * **/ this.removeInLine = function(row, startColumn, endColumn) { - if (startColumn == endColumn) - return; - + + // Calculate deleteion range. var range = new Range(row, startColumn, row, endColumn); - var line = this.getLine(row); - var removed = line.substring(startColumn, endColumn); - var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length); - this.$lines.splice(row, 1, newLine); - - var delta = { - action: "removeText", + range = this.$getClippedRange(range); + + // Apply delta (emits change). + this.applyDelta({ + action: "delete", range: range, - text: removed - }; - this._emit("change", { data: delta }); + lines: this._getLinesForRange(range) + }); + return range.start; }; @@ -469,24 +445,35 @@ var Document = function(text) { * @returns {[String]} Returns all the removed lines. * **/ - this.removeLines = function(firstRow, lastRow) { - if (firstRow < 0 || lastRow >= this.getLength()) - return this.remove(new Range(firstRow, 0, lastRow + 1, 0)); - return this._removeLines(firstRow, lastRow); - }; - - this._removeLines = function(firstRow, lastRow) { - var range = new Range(firstRow, 0, lastRow + 1, 0); - var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1); - - var delta = { - action: "removeLines", + this.removeFullLines = function(firstRow, lastRow) { + + // Clip to document. + firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1); + lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1); + + // Calculate deletion range. + // Delete the ending new line unless we're at the end of the document. + // If we're at the end of the document, delete the starting new line. + var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0; + var deleteLastNewLine = lastRow < this.getLength() - 1; + var startRow = ( deleteFirstNewLine ? firstRow - 1 : firstRow ); + var startCol = ( deleteFirstNewLine ? this.getLine(startRow).length : 0 ); + var endRow = ( deleteLastNewLine ? lastRow + 1 : lastRow ); + var endCol = ( deleteLastNewLine ? 0 : this.getLine(endRow).length ); + var range = new Range(startRow, startCol, endRow, endCol); + + // Store delelted lines with bounding newlines ommitted (maintains previous behavior). + var deletedLines = this.$lines.slice(firstRow, lastRow + 1); + + // Apply delta (emits change). + this.applyDelta({ + action: "delete", range: range, - nl: this.getNewLineCharacter(), - lines: removed - }; - this._emit("change", { data: delta }); - return removed; + lines: this._getLinesForRange(range) + }); + + // Return the deleted lines. + return deletedLines; }; /** @@ -495,20 +482,16 @@ var Document = function(text) { * **/ this.removeNewLine = function(row) { - var firstLine = this.getLine(row); - var secondLine = this.getLine(row+1); - - var range = new Range(row, firstLine.length, row+1, 0); - var line = firstLine + secondLine; - - this.$lines.splice(row, 2, line); - - var delta = { - action: "removeText", - range: range, - text: this.getNewLineCharacter() - }; - this._emit("change", { data: delta }); + + if (row < this.getLength() - 1 && row >= 0) + { + // Apply delta (emits change). + this.applyDelta({ + action: "delete", + range: new Range(row, this.getLine(row).length, row + 1, 0), + lines: ['', ''] + }); + } }; /** @@ -534,53 +517,90 @@ var Document = function(text) { this.remove(range); if (text) { - var end = this.insert(range.start, text); + var end = this.insertText(range.start, text); } else { end = range.start; } - + return end; }; /** - * Applies all the changes previously accumulated. These can be either `'includeText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`. + * Applies all the changes previously accumulated. These can be either `'insert'` or `'delete'`. **/ this.applyDeltas = function(deltas) { for (var i=0; i=0; i--) { - var delta = deltas[i]; - - var range = Range.fromPoints(delta.range.start, delta.range.end); - - if (delta.action == "insertLines") - this._removeLines(range.start.row, range.end.row - 1); - else if (delta.action == "insertText") - this.remove(range); - else if (delta.action == "removeLines") - this._insertLines(range.start.row, delta.lines); - else if (delta.action == "removeText") - this.insert(range.start, delta.text); + this.revertDelta(deltas[i]); } }; + + this.revertDelta = function(delta) + { + this.applyDelta({ + action: (delta.action == 'insert' ? 'delete' : 'insert'), + range: delta.range.clone(), + lines: delta.lines.slice() + }); + }, /** * Converts an index position in a document to a `{row, column}` object. diff --git a/lib/ace/document_test.js b/lib/ace/document_test.js index 5c324db0..50bd8b49 100644 --- a/lib/ace/document_test.js +++ b/lib/ace/document_test.js @@ -48,7 +48,7 @@ module.exports = { var deltas = []; doc.on("change", function(e) { deltas.push(e.data); }); - doc.insert({row: 0, column: 1}, "juhu"); + doc.insertText({row: 0, column: 1}, "juhu"); assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n")); var d = deltas.concat(); @@ -65,7 +65,7 @@ module.exports = { var deltas = []; doc.on("change", function(e) { deltas.push(e.data); }); - doc.insertNewLine({row: 0, column: 1}); + doc.insertLines({row: 0, column: 1}, ['', '']); assert.equal(doc.getValue(), ["1", "2", "34"].join("\n")); var d = deltas.concat(); @@ -82,7 +82,7 @@ module.exports = { var deltas = []; doc.on("change", function(e) { deltas.push(e.data); }); - doc.insertLines(0, ["aa", "bb"]); + doc.insertFullLines(0, ["aa", "bb"]); assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n")); var d = deltas.concat(); @@ -99,7 +99,7 @@ module.exports = { var deltas = []; doc.on("change", function(e) { deltas.push(e.data); }); - doc.insertLines(2, ["aa", "bb"]); + doc.insertFullLines(2, ["aa", "bb"]); assert.equal(doc.getValue(), ["12", "34", "aa", "bb"].join("\n")); }, @@ -109,7 +109,7 @@ module.exports = { var deltas = []; doc.on("change", function(e) { deltas.push(e.data); }); - doc.insertLines(1, ["aa", "bb"]); + doc.insertFullLines(1, ["aa", "bb"]); assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n")); var d = deltas.concat(); @@ -126,7 +126,7 @@ module.exports = { var deltas = []; doc.on("change", function(e) { deltas.push(e.data); }); - doc.insert({row: 0, column: 0}, "aa\nbb\ncc"); + doc.insertText({row: 0, column: 0}, "aa\nbb\ncc"); assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n")); var d = deltas.concat(); @@ -143,7 +143,7 @@ module.exports = { var deltas = []; doc.on("change", function(e) { deltas.push(e.data); }); - doc.insert({row: 2, column: 0}, "aa\nbb\ncc"); + doc.insertText({row: 1, column: 2}, "aa\nbb\ncc"); assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n")); var d = deltas.concat(); @@ -160,7 +160,7 @@ module.exports = { var deltas = []; doc.on("change", function(e) { deltas.push(e.data); }); - doc.insert({row: 0, column: 1}, "aa\nbb\ncc"); + doc.insertText({row: 0, column: 1}, "aa\nbb\ncc"); assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n")); var d = deltas.concat(); @@ -235,7 +235,7 @@ module.exports = { "test: remove lines should return the removed lines" : function() { var doc = new Document(["1234", "5678", "abcd"]); - var removed = doc.removeLines(1, 2); + var removed = doc.removeFullLines(1, 2); assert.equal(removed.join("\n"), ["5678", "abcd"].join("\n")); }, diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index a63ceeef..98c255a4 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1136,8 +1136,8 @@ var EditSession = function(text, mode) { * * **/ - this.insert = function(position, text) { - return this.doc.insert(position, text); + this.insertText = function(position, text) { + return this.doc.insertText(position, text); }; /** @@ -1151,6 +1151,19 @@ var EditSession = function(text, mode) { this.remove = function(range) { return this.doc.remove(range); }; + + /** + * Removes a range of full lines. This method also triggers the `'change'` event. + * @param {Number} firstRow The first row to be removed + * @param {Number} lastRow The last row to be removed + * @returns {[String]} Returns all the removed lines. + * + * @related Document.removeFullLines + * + **/ + this.removeFullLines = function(firstRow, lastRow){ + return this.doc.removeFullLines(firstRow, lastRow) + } /** * Reverts previous changes to your document. @@ -1227,9 +1240,7 @@ var EditSession = function(text, mode) { this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) { function isInsert(delta) { - var insert = - delta.action === "insertText" || delta.action === "insertLines"; - return isUndo ? !insert : insert; + return isUndo ? delta.action !== "insert" : delta.action === "insert"; } var delta = deltas[0]; @@ -1339,7 +1350,7 @@ var EditSession = function(text, mode) { } } - toRange.end = this.insert(toRange.start, text); + toRange.end = this.insertText(toRange.start, text); if (folds.length) { var oldStart = fromRange.start; var newStart = toRange.start; @@ -1373,7 +1384,7 @@ var EditSession = function(text, mode) { this.indentRows = function(startRow, endRow, indentString) { indentString = indentString.replace(/\t/g, this.getTabString()); for (var row=startRow; row<=endRow; row++) - this.insert({row: row, column:0}, indentString); + this.insertText({row: row, column:0}, indentString); }; /** @@ -1430,11 +1441,11 @@ var EditSession = function(text, mode) { x.end.row += diff; return x; }); - + var lines = dir == 0 ? this.doc.getLines(firstRow, lastRow) - : this.doc.removeLines(firstRow, lastRow); - this.doc.insertLines(firstRow+diff, lines); + : this.doc.removeFullLines(firstRow, lastRow); + this.doc.insertFullLines(firstRow+diff, lines); folds.length && this.addFolds(folds); return diff; }; @@ -1444,8 +1455,6 @@ var EditSession = function(text, mode) { * @param {Number} lastRow The final row to move up * @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1. * - * @related Document.insertLines - * **/ this.moveLinesUp = function(firstRow, lastRow) { return this.$moveLines(firstRow, lastRow, -1); @@ -1456,8 +1465,6 @@ var EditSession = function(text, mode) { * @param {Number} firstRow The starting row to move down * @param {Number} lastRow The final row to move down * @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1. - * - * @related Document.insertLines **/ this.moveLinesDown = function(firstRow, lastRow) { return this.$moveLines(firstRow, lastRow, 1); @@ -1668,28 +1675,17 @@ var EditSession = function(text, mode) { this.$updateInternalDataOnChange = function(e) { var useWrapMode = this.$useWrapMode; - var len; var action = e.data.action; - var firstRow = e.data.range.start.row; - var lastRow = e.data.range.end.row; var start = e.data.range.start; var end = e.data.range.end; + var firstRow = start.row; + var lastRow = end.row; + var len = lastRow - firstRow; var removedFolds = null; - - if (action.indexOf("Lines") != -1) { - if (action == "insertLines") { - lastRow = firstRow + (e.data.lines.length); - } else { - lastRow = firstRow; - } - len = e.data.lines ? e.data.lines.length : lastRow - firstRow; - } else { - len = lastRow - firstRow; - } - + this.$updating = true; if (len != 0) { - if (action.indexOf("remove") != -1) { + if (action == "delete") { this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len); var foldLines = this.$foldData; @@ -1764,7 +1760,7 @@ var EditSession = function(text, mode) { // Realign folds. E.g. if you add some new chars before a fold, the // fold should "move" to the right. len = Math.abs(e.data.range.start.column - e.data.range.end.column); - if (action.indexOf("remove") != -1) { + if (action == "delete") { // Get all the folds in the change range and remove them. removedFolds = this.getFoldsInRange(e.data.range); this.removeFolds(removedFolds); diff --git a/lib/ace/edit_session/folding.js b/lib/ace/edit_session/folding.js index 474818b2..9df35593 100644 --- a/lib/ace/edit_session/folding.js +++ b/lib/ace/edit_session/folding.js @@ -833,7 +833,7 @@ function Folding() { if (len === 0) { this.foldWidgets[firstRow] = null; - } else if (delta.action == "removeText" || delta.action == "removeLines") { + } else if (delta.action == "delete") { this.foldWidgets.splice(firstRow, len + 1, null); } else { var args = Array(len + 1); diff --git a/lib/ace/edit_session_test.js b/lib/ace/edit_session_test.js index 87cc9567..855da4d1 100644 --- a/lib/ace/edit_session_test.js +++ b/lib/ace/edit_session_test.js @@ -430,12 +430,12 @@ module.exports = { session.setTabSize(4); assert.equal(session.getScreenWidth(), 2); - session.doc.insertNewLine({row: 0, column: Infinity}); - session.doc.insertLines(1, ["123"]); + session.doc.insertLines({row: 0, column: Infinity}, ['', '']); + session.doc.insertFullLines(1, ["123"]); assert.equal(session.getScreenWidth(), 3); - session.doc.insertNewLine({row: 0, column: Infinity}); - session.doc.insertLines(1, ["\t\t"]); + session.doc.insertLines({row: 0, column: Infinity}, ['', '']); + session.doc.insertFullLines(1, ["\t\t"]); assert.equal(session.getScreenWidth(), 8); @@ -459,9 +459,9 @@ module.exports = { session.setUseWrapMode(true); - document.insertLines(0, ["a", "b"]); - document.insertLines(2, ["c", "d"]); - document.removeLines(1, 2); + document.insertFullLines(0, ["a", "b"]); + document.insertFullLines(2, ["c", "d"]); + document.removeFullLines(1, 2); }, "test wrapMode init has to create wrapData array": function() { @@ -649,7 +649,7 @@ module.exports = { var foldLines = session.$foldData; function insert(row, column, text) { - session.insert({row: row, column: column}, text); + session.insertText({row: row, column: column}, text); // Force the session to store all changes made to the document NOW // on the undoManager's queue. Otherwise we can't undo in separate @@ -748,7 +748,7 @@ module.exports = { undoManager = session.getUndoManager(), foldLines = session.$foldData; function insert(row, column, text) { - session.insert({row: row, column: column}, text); + session.insertText({row: row, column: column}, text); // Force the session to store all changes made to the document NOW // on the undoManager's queue. Otherwise we can't undo in separate // steps later. diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 6486a881..3926fc81 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -601,19 +601,10 @@ var Editor = function(renderer, session) { * **/ this.onDocumentChange = function(e) { - var delta = e.data; - var range = delta.range; - var lastRow; - - if (range.start.row == range.end.row && delta.action != "insertLines" && delta.action != "removeLines") - lastRow = range.end.row; - else - lastRow = Infinity; - this.renderer.updateLines(range.start.row, lastRow); - + this.renderer.updateLines(e.data.range.start.row, e.data.range.end.row); this._emit("change", e); - - // update cursor because tab characters can influence the cursor position + + // update cursor because tab characters can influence the cursor position. this.$cursorChange(); }; @@ -827,7 +818,7 @@ var Editor = function(renderer, session) { if (this.$readOnly) return; this._emit("paste", text); - this.insert(text); + this.insertText(text); }; @@ -841,7 +832,7 @@ var Editor = function(renderer, session) { * * **/ - this.insert = function(text) { + this.insertText = function(text) { var session = this.session; var mode = session.getMode(); var cursor = this.getCursorPosition(); @@ -887,7 +878,7 @@ var Editor = function(renderer, session) { var lineState = session.getState(cursor.row); var line = session.getLine(cursor.row); var shouldOutdent = mode.checkOutdent(lineState, line, text); - var end = session.insert(cursor, text); + var end = session.insertText(cursor, text); if (transform && transform.selection) { if (transform.selection.length == 2) { // Transform relative to the current column @@ -906,7 +897,7 @@ var Editor = function(renderer, session) { if (session.getDocument().isNewLine(text)) { var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString()); - session.insert({row: cursor.row+1, column: 0}, lineIndent); + session.insertText({row: cursor.row+1, column: 0}, lineIndent); } if (shouldOutdent) mode.autoOutdent(lineState, session, cursor.row); @@ -1279,7 +1270,7 @@ var Editor = function(renderer, session) { } var cursor = this.getCursorPosition(); - this.insert("\n"); + this.insertText("\n"); this.moveCursorToPosition(cursor); }; @@ -1378,7 +1369,7 @@ var Editor = function(renderer, session) { this.selection.setSelectionRange(range); indentString = "\t"; } - return this.insert(indentString); + return this.insertText(indentString); }; /** @@ -1516,15 +1507,7 @@ var Editor = function(renderer, session) { **/ this.removeLines = function() { var rows = this.$getSelectedRows(); - var range; - if (rows.first === 0 || rows.last+1 < this.session.getLength()) - range = new Range(rows.first, 0, rows.last+1, 0); - else - range = new Range( - rows.first-1, this.session.getLine(rows.first-1).length, - rows.last, this.session.getLine(rows.last).length - ); - this.session.remove(range); + this.session.removeFullLines(rows.first, rows.last); this.clearSelection(); }; @@ -1538,7 +1521,7 @@ var Editor = function(renderer, session) { doc.duplicateLines(row, row); } else { var point = reverse ? range.start : range.end; - var endPoint = doc.insert(point, doc.getTextRange(range), false); + var endPoint = doc.insertText(point, doc.getTextRange(range), false); range.start = point; range.end = endPoint; diff --git a/lib/ace/editor_change_document_test.js b/lib/ace/editor_change_document_test.js index a1fdaad9..83fffeb3 100644 --- a/lib/ace/editor_change_document_test.js +++ b/lib/ace/editor_change_document_test.js @@ -172,7 +172,7 @@ module.exports = { self.session1.setMode(new HtmlMode()); // 5. Try to type valid HTML - self.session1.insert({row: 0, column: 0}, ""); + self.session1.insertText({row: 0, column: 0}, ""); setTimeout(function() { assert.equal(Object.keys(self.session1.getAnnotations()).length, 0); diff --git a/lib/ace/editor_navigation_test.js b/lib/ace/editor_navigation_test.js index ab348241..b60d391d 100644 --- a/lib/ace/editor_navigation_test.js +++ b/lib/ace/editor_navigation_test.js @@ -150,7 +150,7 @@ module.exports = { var editor = new Editor(new MockRenderer(), new EditSession(["1234", "1234567890"])); editor.navigateTo(0, 3); - editor.insert("juhu"); + editor.insertText("juhu"); editor.navigateDown(); assert.position(editor.getCursorPosition(), 1, 7); diff --git a/lib/ace/ext/chromevox.js b/lib/ace/ext/chromevox.js index 9f7a7996..20bbb6c7 100644 --- a/lib/ace/ext/chromevox.js +++ b/lib/ace/ext/chromevox.js @@ -581,12 +581,12 @@ var onSelectionChange = function(evt) { var onChange = function(evt) { var data = evt.data; switch (data.action) { - case 'removeText': + case 'delete': cvox.Api.speak(data.text, 0, DELETED_PROP); /* Let the future cursor change event know it's from text change. */ changed = true; break; - case 'insertText': + case 'insert': cvox.Api.speak(data.text, 0); /* Let the future cursor change event know it's from text change. */ changed = true; diff --git a/lib/ace/ext/elastic_tabstops_lite.js b/lib/ace/ext/elastic_tabstops_lite.js index 9901c5df..4d3a40d4 100644 --- a/lib/ace/ext/elastic_tabstops_lite.js +++ b/lib/ace/ext/elastic_tabstops_lite.js @@ -236,7 +236,7 @@ var ElasticTabstopsLite = function(editor) { if (difference > 0) { // put the spaces after the tab and then delete the tab, so any insertion // points behave as expected - this.$editor.session.getDocument().insertInLine({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t"); + this.$editor.session.getDocument().insertText({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t"); this.$editor.session.getDocument().removeInLine(row, it, it + 1); bias += difference; diff --git a/lib/ace/ext/whitespace.js b/lib/ace/ext/whitespace.js index 83486fb0..736e991d 100644 --- a/lib/ace/ext/whitespace.js +++ b/lib/ace/ext/whitespace.js @@ -153,7 +153,7 @@ exports.convertIndentation = function(session, ch, len) { if (toInsert != match) { doc.removeInLine(i, 0, match.length); - doc.insertInLine({row: i, column: 0}, toInsert); + doc.insertText({row: i, column: 0}, toInsert); } } } diff --git a/lib/ace/keyboard/vim/commands.js b/lib/ace/keyboard/vim/commands.js index dd3357d6..defca037 100644 --- a/lib/ace/keyboard/vim/commands.js +++ b/lib/ace/keyboard/vim/commands.js @@ -104,7 +104,7 @@ var actions = exports.actions = { if (param && param.length) { if (param.length > 1) param = param == "return" ? "\n" : param == "tab" ? "\t" : param; - repeat(function() { editor.insert(param); }, count || 1); + repeat(function() { editor.insertText(param); }, count || 1); editor.navigateLeft(); } } @@ -224,12 +224,12 @@ var actions = exports.actions = { var pos = editor.getCursorPosition(); pos.column = editor.session.getLine(pos.row).length; var text = lang.stringRepeat("\n" + defaultReg.text, count || 1); - editor.session.insert(pos, text); + editor.session.insertText(pos, text); editor.moveCursorTo(pos.row + 1, 0); } else { editor.navigateRight(); - editor.insert(lang.stringRepeat(defaultReg.text, count || 1)); + editor.insertText(lang.stringRepeat(defaultReg.text, count || 1)); editor.navigateLeft(); } editor.setOverwrite(true); @@ -245,11 +245,11 @@ var actions = exports.actions = { var pos = editor.getCursorPosition(); pos.column = 0; var text = lang.stringRepeat(defaultReg.text + "\n", count || 1); - editor.session.insert(pos, text); + editor.session.insertText(pos, text); editor.moveCursorToPosition(pos); } else { - editor.insert(lang.stringRepeat(defaultReg.text, count || 1)); + editor.insertText(lang.stringRepeat(defaultReg.text, count || 1)); } editor.setOverwrite(true); editor.selection.clearSelection(); diff --git a/lib/ace/keyboard/vim/maps/motions.js b/lib/ace/keyboard/vim/maps/motions.js index 91c8b8af..2bf580b0 100644 --- a/lib/ace/keyboard/vim/maps/motions.js +++ b/lib/ace/keyboard/vim/maps/motions.js @@ -545,7 +545,7 @@ module.exports = { if (content.length) { editor.navigateLineEnd() - editor.insert(content); + editor.insertText(content); util.insertMode(editor); } } @@ -562,9 +562,9 @@ module.exports = { if(row > 0) { editor.navigateUp(); editor.navigateLineEnd() - editor.insert(content); + editor.insertText(content); } else { - editor.session.insert({row: 0, column: 0}, content); + editor.session.insertText({row: 0, column: 0}, content); editor.navigateUp(); } util.insertMode(editor); diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index 5a535094..9d813d2a 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -108,8 +108,8 @@ var Gutter = function(parentEl) { var len = range.end.row - firstRow; if (len === 0) { // do nothing - } else if (delta.action == "removeText" || delta.action == "removeLines") { - this.$annotations.splice(firstRow, len + 1, null); + } else if (delta.action == "delete") { + this.$annotations.splice(firstRow, len, null); } else { var args = new Array(len + 1); args.unshift(firstRow, 1); diff --git a/lib/ace/line_widgets.js b/lib/ace/line_widgets.js index 597b3ca2..4023bd55 100644 --- a/lib/ace/line_widgets.js +++ b/lib/ace/line_widgets.js @@ -123,7 +123,7 @@ function LineWidgets(session) { if (len === 0) { // return - } else if (delta.action == "removeText" || delta.action == "removeLines") { + } else if (delta.action == "delete") { var removed = cells.splice(startRow + 1, len); removed.forEach(function(w) { w && this.removeLineWidget(w); diff --git a/lib/ace/mode/javascript_test.js b/lib/ace/mode/javascript_test.js index b413765a..cc2b22d7 100644 --- a/lib/ace/mode/javascript_test.js +++ b/lib/ace/mode/javascript_test.js @@ -131,7 +131,7 @@ module.exports = { this.mode.toggleCommentLines("start", session, 0, 2); assert.equal([" abc", " cde", " fg"].join("\n"), session.toString()); - session.insert({row: 0, column: 0}, " "); + session.insertText({row: 0, column: 0}, " "); this.mode.toggleCommentLines("start", session, 0, 2); assert.equal(["// abc", "// cde", "// fg"].join("\n"), session.toString()); }, diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index d04fed78..534ac03c 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -92,8 +92,8 @@ var Mode = function() { if (testRemove(line, i)) return; if (!ignoreBlankLines || /\S/.test(line)) { - doc.insertInLine({row: i, column: line.length}, lineCommentEnd); - doc.insertInLine({row: i, column: minIndent}, lineCommentStart); + doc.insertText({row: i, column: line.length}, lineCommentEnd); + doc.insertText({row: i, column: minIndent}, lineCommentStart); } }; @@ -138,9 +138,9 @@ var Mode = function() { var comment = function(line, i) { if (!ignoreBlankLines || /\S/.test(line)) { if (shouldInsertSpace(line, minIndent, minIndent)) - doc.insertInLine({row: i, column: minIndent}, commentWithSpace); + doc.insertText({row: i, column: minIndent}, commentWithSpace); else - doc.insertInLine({row: i, column: minIndent}, lineCommentStart); + doc.insertText({row: i, column: minIndent}, lineCommentStart); } }; var testRemove = function(line, i) { @@ -244,8 +244,8 @@ var Mode = function() { } else { colDiff = comment.start.length startRow = range.start.row; - session.insert(range.end, comment.end); - session.insert(range.start, comment.start); + session.insertText(range.end, comment.end); + session.insertText(range.start, comment.start); } // todo: selection should have ended up in the right place automatically! if (initialRange.start.row == startRow) diff --git a/lib/ace/mouse/dragdrop_handler.js b/lib/ace/mouse/dragdrop_handler.js index 3a4bc188..3ad54bb8 100644 --- a/lib/ace/mouse/dragdrop_handler.js +++ b/lib/ace/mouse/dragdrop_handler.js @@ -176,7 +176,7 @@ function DragdropHandler(mouseHandler) { var dropData = dataTransfer.getData('Text'); range = { start: dragCursor, - end: editor.session.insert(dragCursor, dropData) + end: editor.session.insertText(dragCursor, dropData) }; editor.focus(); dragOperation = null; diff --git a/lib/ace/multi_select.js b/lib/ace/multi_select.js index 7f4c5355..883d9a7c 100644 --- a/lib/ace/multi_select.js +++ b/lib/ace/multi_select.js @@ -544,7 +544,7 @@ var Editor = require("./editor").Editor; this._signal("paste", text); if (!this.inMultiSelectMode || this.inVirtualSelectionMode) - return this.insert(text); + return this.insertText(text); var lines = text.split(/\r\n|\r|\n/); var ranges = this.selection.rangeList.ranges; @@ -557,7 +557,7 @@ var Editor = require("./editor").Editor; if (!range.isEmpty()) this.session.remove(range); - this.session.insert(range.start, lines[i]); + this.session.insertText(range.start, lines[i]); } }; @@ -740,9 +740,9 @@ var Editor = require("./editor").Editor; if (fr < 0) fr = 0; if (lr >= max) lr = max - 1; } - var lines = this.session.doc.removeLines(fr, lr); + var lines = this.session.removeFullLines(fr, lr); lines = this.$reAlignText(lines, guessRange); - this.session.doc.insert({row: fr, column: 0}, lines.join("\n") + "\n"); + this.session.insertText({row: fr, column: 0}, lines.join("\n") + "\n"); if (!guessRange) { range.start.column = 0; range.end.column = lines[lines.length - 1].length; @@ -778,7 +778,7 @@ var Editor = require("./editor").Editor; var l = maxCol - p.column; var d = spaceOffsets[i] - minSpace; if (l > d) - session.insert(p, lang.stringRepeat(" ", l - d)); + session.insertText(p, lang.stringRepeat(" ", l - d)); else session.remove(new Range(p.row, p.column, p.row, p.column - l + d)); diff --git a/lib/ace/occur_test.js b/lib/ace/occur_test.js index 59fb8548..a9b2c894 100644 --- a/lib/ace/occur_test.js +++ b/lib/ace/occur_test.js @@ -55,7 +55,7 @@ module.exports = { }, "test: find lines matching" : function() { - editor.session.insert({row: 0, column: 0}, 'abc\ndef\nxyz\nbcxbc'); + editor.session.insertText({row: 0, column: 0}, 'abc\ndef\nxyz\nbcxbc'); var result = occur.matchingLines(editor.session, {needle: 'bc'}), expected = [{row: 0, content: 'abc'}, {row: 3, content: 'bcxbc'}]; assert.deepEqual(result, expected); @@ -63,7 +63,7 @@ module.exports = { "test: display occurrences" : function() { var text = 'abc\ndef\nxyz\nbcx\n'; - editor.session.insert({row: 0, column: 0}, text); + editor.session.insertText({row: 0, column: 0}, text); occur.displayOccurContent(editor, {needle: 'bc'}); assert.equal(editor.getValue(), 'abc\nbcx'); occur.displayOriginalContent(editor); @@ -72,7 +72,7 @@ module.exports = { "test: original position from occur doc" : function() { var text = 'abc\ndef\nxyz\nbcx\n'; - editor.session.insert({row: 0, column: 0}, text); + editor.session.insertText({row: 0, column: 0}, text); occur.displayOccurContent(editor, {needle: 'bc'}); assert.equal(editor.getValue(), 'abc\nbcx'); var pos = occur.occurToOriginalPosition(editor.session, {row: 1, column: 2}); @@ -82,7 +82,7 @@ module.exports = { "test: occur command" : function() { // setup var text = 'hel\nlo\n\nwo\nrld\n'; - editor.session.insert({row: 0, column: 0}, text); + editor.session.insertText({row: 0, column: 0}, text); editor.commands.addCommand(occurStartCommand); // run occur for lines including 'o' @@ -106,7 +106,7 @@ module.exports = { "test: occur navigation" : function() { // setup var text = 'hel\nlo\n\nwo\nrld\n'; - editor.session.insert({row: 0, column: 0}, text); + editor.session.insertText({row: 0, column: 0}, text); editor.commands.addCommand(occurStartCommand); editor.moveCursorToPosition({row: 1, column: 1}); @@ -125,7 +125,7 @@ module.exports = { "test: recursive occur" : function() { // setup var text = 'x\nabc1\nx\nabc2\n'; - editor.session.insert({row: 0, column: 0}, text); + editor.session.insertText({row: 0, column: 0}, text); editor.commands.addCommand(occurStartCommand); // orig -> occur1 diff --git a/lib/ace/placeholder.js b/lib/ace/placeholder.js index bcb44ce2..9d0a3c3c 100644 --- a/lib/ace/placeholder.js +++ b/lib/ace/placeholder.js @@ -155,21 +155,21 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) if(range.start.row !== this.pos.row) return; if (this.$updating) return; this.$updating = true; - var lengthDiff = delta.action === "insertText" ? range.end.column - range.start.column : range.start.column - range.end.column; + var lengthDiff = delta.action === "insert" ? range.end.column - range.start.column : range.start.column - range.end.column; if(range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1) { var distanceFromStart = range.start.column - this.pos.column; this.length += lengthDiff; if(!this.session.$fromUndo) { - if(delta.action === "insertText") { + if(delta.action === "insert") { for (var i = this.others.length - 1; i >= 0; i--) { var otherPos = this.others[i]; var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; if(otherPos.row === range.start.row && range.start.column < otherPos.column) newPos.column += lengthDiff; - this.doc.insert(newPos, delta.text); + this.doc.insertLines(newPos, delta.lines); } - } else if(delta.action === "removeText") { + } else if(delta.action === "delete") { for (var i = this.others.length - 1; i >= 0; i--) { var otherPos = this.others[i]; var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; @@ -179,7 +179,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) } } // Special case: insert in beginning - if(range.start.column === this.pos.column && delta.action === "insertText") { + if(range.start.column === this.pos.column && delta.action === "insert") { setTimeout(function() { this.pos.setPosition(this.pos.row, this.pos.column - lengthDiff); for (var i = 0; i < this.others.length; i++) { @@ -191,7 +191,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) } }.bind(this), 0); } - else if(range.start.column === this.pos.column && delta.action === "removeText") { + else if(range.start.column === this.pos.column && delta.action === "delete") { setTimeout(function() { for (var i = 0; i < this.others.length; i++) { var other = this.others[i]; diff --git a/lib/ace/placeholder_test.js b/lib/ace/placeholder_test.js index 97e561fd..dc7e4b23 100644 --- a/lib/ace/placeholder_test.js +++ b/lib/ace/placeholder_test.js @@ -53,9 +53,9 @@ module.exports = { new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]); editor.moveCursorTo(0, 5); - editor.insert('b'); + editor.insertText('b'); assert.equal(session.doc.getValue(), "var ab = 10;\nconsole.log(ab, ab);"); - editor.insert('cd'); + editor.insertText('cd'); assert.equal(session.doc.getValue(), "var abcd = 10;\nconsole.log(abcd, abcd);"); editor.remove('left'); editor.remove('left'); @@ -70,7 +70,7 @@ module.exports = { new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]); editor.moveCursorTo(2, 0); - editor.insert('b'); + editor.insertText('b'); assert.equal(session.doc.getValue(), "var a = 10;\nconsole.log(a, a);\nb"); }, @@ -81,12 +81,12 @@ module.exports = { var p = new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]); editor.moveCursorTo(0, 4); - editor.insert('$'); + editor.insertText('$'); assert.equal(session.doc.getValue(), "var $a = 10;\nconsole.log($a, $a);"); editor.moveCursorTo(0, 4); // Have to put this in a setTimeout because the anchor is only fixed later. setTimeout(function() { - editor.insert('v'); + editor.insertText('v'); assert.equal(session.doc.getValue(), "var v$a = 10;\nconsole.log(v$a, v$a);"); next(); }, 10); @@ -99,10 +99,10 @@ module.exports = { var p = new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]); editor.moveCursorTo(0, 5); - editor.insert('b'); + editor.insertText('b'); assert.equal(session.doc.getValue(), "var ab = 10;\nconsole.log(ab, ab);"); p.detach(); - editor.insert('cd'); + editor.insertText('cd'); assert.equal(session.doc.getValue(), "var abcd = 10;\nconsole.log(ab, ab);"); }, @@ -136,8 +136,8 @@ module.exports = { var p = new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]); editor.moveCursorTo(0, 5); - editor.insert('b'); - editor.insert('cd'); + editor.insertText('b'); + editor.insertText('cd'); editor.remove('left'); assert.equal(session.doc.getValue(), "var abc = 10;\nconsole.log(abc, abc);"); // Wait a little for the changes to enter the undo stack From 27768230c86eadb6f3a65f6c212af6c0f6a2972b Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Wed, 1 Jan 2014 11:05:27 -0600 Subject: [PATCH 002/315] Maintain public API and update coding convention This seeks to keep the public API in-tact while improving method names within ace by keeping the old methods as wrappers around the new better-named methods. For example, document.insert() now simply calls document.insertText() and warns the caller via a console.log() that they are using a deprecated method. I've also updated the coding style of my changes (where I noticed discrepancies) to match the rest of Ace. --- lib/ace/anchor.js | 22 ++++------ lib/ace/anchor_test.js | 4 +- lib/ace/document.js | 80 +++++++++++++++++++++--------------- lib/ace/document_test.js | 2 +- lib/ace/edit_session.js | 6 +++ lib/ace/edit_session_test.js | 4 +- lib/ace/editor.js | 6 +++ lib/ace/placeholder.js | 2 +- 8 files changed, 73 insertions(+), 53 deletions(-) diff --git a/lib/ace/anchor.js b/lib/ace/anchor.js index 91a62eb0..affb4f19 100644 --- a/lib/ace/anchor.js +++ b/lib/ace/anchor.js @@ -117,33 +117,29 @@ var Anchor = exports.Anchor = function(doc, row, column) { var deltaEnd = (deltaIsInsert ? deltaStart : delta.range.end); // Collapse insert range. // DELTA AFTER POINT: No change needed. - if (_pointsInOrder(point, deltaStart, moveIfEqual)) - { - return ( - { + if (_pointsInOrder(point, deltaStart, moveIfEqual)) { + return { row: point.row, column: point.column - }); + }; } // DELTA BEFORE POINT: Move point by delta shift. - if (_pointsInOrder(deltaEnd, point, !moveIfEqual)) - { - return ( - { + if (_pointsInOrder(deltaEnd, point, !moveIfEqual)) { + return { row: point.row + deltaRowShift, column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0) - }); + }; } // DELTA ENVELOPS POINT (delete only): Move point to delta start. if (delta.action != 'delete') throw 'Delete action expected.'; - return ( - { + + return { row: deltaStart.row, column: deltaStart.column - }); + }; } var delta = e.data; diff --git a/lib/ace/anchor_test.js b/lib/ace/anchor_test.js index 0588c9b6..0661765b 100644 --- a/lib/ace/anchor_test.js +++ b/lib/ace/anchor_test.js @@ -70,7 +70,7 @@ module.exports = { var doc = new Document("juhu\nkinners"); var anchor = new Anchor(doc, 1, 4); - doc.insertLines({row: 0, column: 0}, ['', '']); + doc.insertMergedLines({row: 0, column: 0}, ['', '']); assert.position(anchor.getPosition(), 2, 4); }, @@ -78,7 +78,7 @@ module.exports = { var doc = new Document("juhu\nkinners"); var anchor = new Anchor(doc, 1, 4); - doc.insertLines({row: 1, column: 2}, ['', '']); + doc.insertMergedLines({row: 1, column: 2}, ['', '']); assert.position(anchor.getPosition(), 2, 2); }, diff --git a/lib/ace/document.js b/lib/ace/document.js index ace69e32..07726de7 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -59,7 +59,7 @@ var Document = function(textOrLines) { if (textOrLines.length == 0) { this.$lines = [""]; } else if (Array.isArray(textOrLines)) { - this.insertLines({row: 0, column: 0}, textOrLines); + this.insertMergedLines({row: 0, column: 0}, textOrLines); } else { this.insertText({row: 0, column:0}, textOrLines); } @@ -230,13 +230,10 @@ var Document = function(textOrLines) { this.$clipPosition = function(position) { var length = this.getLength(); - if (position.row >= length) - { + if (position.row >= length) { position.row = Math.max(0, length - 1); position.column = this.getLine(length - 1).length; - } - else - { + } else { position.row = Math.max(0, position.row); position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length); } @@ -264,16 +261,15 @@ var Document = function(textOrLines) { throw errorText; } + // Validate lines. if (!delta.lines instanceof Array) - { fnThrow('Delta object lines must be an array'); - } + // Validate range type. if (!delta.range instanceof Range) - { fnThrow('Range object is not an instance of the Range class'); - } + // Validate start point. var start = delta.range.start; if (Math.min(Math.max(start.row, 0), this.getLength() - 1 ) != start.row || Math.min(Math.max(start.column, 0), this.$lines[start.row].length) != start.column) @@ -281,16 +277,37 @@ var Document = function(textOrLines) { fnThrow('Range start point not contained in document'); } + // Validate ending row offset. if (delta.lines.length - 1 != delta.range.end.row - delta.range.start.row) - { fnThrow('Range row offsets does not match delta lines'); - } - // TODO: Validate that the ending column offset matches the lines. - // TODO: Validate for deletions that the lines deleted match the lines - // in the document. + // TODO: + // - Validate that the ending column offset matches the lines. + // - Validate the deleted lines match the lines in the document. }, + // Deprecated methods retained for backwards compatibility. + this.insert = function(position, text){ + console.log('Warning: document.insert is deprecated. Use the insertText method instead.'); + return this.insertText(position, text); + } + this.insertLines = function(row, lines) { + console.log('Warning: document.insertLines is deprecated. Use the insertFullLines method instead.'); + return this.insertFullLines(row, lines); + } + this.removeLines = function(firstRow, lastRow) { + console.log('Warning: document.removeLines is deprecated. Use the removeFullLines method instead.'); + return this.removeFullLines(firstRow, lastRow); + } + this.insertNewLine = function(position) { + console.log('Warning: document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead.'); + return this.insertMergedLines(position, ['', '']); + } + this.insertInLine = function(position, text) { + console.log('Warning: document.insertInLine is deprecated. Use insertText instead.'); + return this.insertText(position, text); + } + /** * Inserts a block of `text` at the indicated `position`. * @param {Object} position The position to start inserting at; it's an object that looks like `{ row: row, column: column}` @@ -304,9 +321,9 @@ var Document = function(textOrLines) { if (this.getLength() <= 1) this.$detectNewLine(text); - return this.insertLines(position, this.$split(text)); + return this.insertMergedLines(position, this.$split(text)); }; - + /** * Fires whenever the document changes. * @@ -338,28 +355,26 @@ var Document = function(textOrLines) { * ``` * **/ - this.insertFullLines = function(row, lines) - { + this.insertFullLines = function(row, lines) { // Clip to document. // Allow one past the document end. row = Math.min(Math.max(row, 0), this.getLength()); // Calculate insertion point. var column = 0; - if (row < this.getLength()) // Insert before the specified row. - { + if (row < this.getLength()) { + // Insert before the specified row. lines = lines.concat(['']); column = 0; - } - else // Insert after the last row in the document. - { + } else { + // Insert after the last row in the document. lines = [''].concat(lines); row--; var column = this.$lines[row].length; } // Insert. - this.insertLines({row: row, column: column}, lines); + this.insertMergedLines({row: row, column: column}, lines); }, /** @@ -376,7 +391,7 @@ var Document = function(textOrLines) { * ``` * **/ - this.insertLines = function(position, lines){ + this.insertMergedLines = function(position, lines) { // Calculate insertion range end point. this.$clipPosition(position); @@ -405,8 +420,7 @@ var Document = function(textOrLines) { // Apply delta (emits change). range = this.$getClippedRange(range); - this.applyDelta( - { + this.applyDelta({ action: 'delete', range: range, lines: this._getLinesForRange(range), @@ -483,14 +497,13 @@ var Document = function(textOrLines) { **/ this.removeNewLine = function(row) { - if (row < this.getLength() - 1 && row >= 0) - { + if (row < this.getLength() - 1 && row >= 0) { // Apply delta (emits change). this.applyDelta({ action: "delete", range: new Range(row, this.getLine(row).length, row + 1, 0), lines: ['', ''] - }); + }); } }; @@ -558,8 +571,7 @@ var Document = function(textOrLines) { { case 'insert': splitLine(this.$lines, delta.range.start); - for (var i = 0; i < delta.lines.length; i++) - { + for (var i = 0; i < delta.lines.length; i++) { var row = delta.range.start.row + 1 + i; this.$lines.splice(row, 0, delta.lines[i]); } @@ -571,7 +583,7 @@ var Document = function(textOrLines) { splitLine(this.$lines, delta.range.end); splitLine(this.$lines, delta.range.start); this.$lines.splice( - delta.range.start.row + 1, // Where to start deleting + delta.range.start.row + 1, // Where to start deleting delta.range.end.row - delta.range.start.row + 1 // Num lines to delete. ); joinLineWithNext(this.$lines, delta.range.start.row); diff --git a/lib/ace/document_test.js b/lib/ace/document_test.js index 50bd8b49..c29d6133 100644 --- a/lib/ace/document_test.js +++ b/lib/ace/document_test.js @@ -65,7 +65,7 @@ module.exports = { var deltas = []; doc.on("change", function(e) { deltas.push(e.data); }); - doc.insertLines({row: 0, column: 1}, ['', '']); + doc.insertMergedLines({row: 0, column: 1}, ['', '']); assert.equal(doc.getValue(), ["1", "2", "34"].join("\n")); var d = deltas.concat(); diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 98c255a4..e48bdc37 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1127,6 +1127,12 @@ var EditSession = function(text, mode) { this.getTextRange = function(range) { return this.doc.getTextRange(range || this.selection.getRange()); }; + + // Deprecated method retained for backwards compatibility. + this.insert = function(position, text){ + console.log('Warning: editsession.insert is deprecated. Use the insertText method instead.'); + return this.insertText(position, text) + } /** * Inserts a block of `text` and the indicated `position`. diff --git a/lib/ace/edit_session_test.js b/lib/ace/edit_session_test.js index 855da4d1..fd20259c 100644 --- a/lib/ace/edit_session_test.js +++ b/lib/ace/edit_session_test.js @@ -430,11 +430,11 @@ module.exports = { session.setTabSize(4); assert.equal(session.getScreenWidth(), 2); - session.doc.insertLines({row: 0, column: Infinity}, ['', '']); + session.doc.insertMergedLines({row: 0, column: Infinity}, ['', '']); session.doc.insertFullLines(1, ["123"]); assert.equal(session.getScreenWidth(), 3); - session.doc.insertLines({row: 0, column: Infinity}, ['', '']); + session.doc.insertMergedLines({row: 0, column: Infinity}, ['', '']); session.doc.insertFullLines(1, ["\t\t"]); assert.equal(session.getScreenWidth(), 8); diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 3926fc81..2854eaaf 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -825,6 +825,12 @@ var Editor = function(renderer, session) { this.execCommand = function(command, args) { this.commands.exec(command, this, args); }; + + // Deprecated method retained for backwards compatibility. + this.insert = function(text){ + console.log('Warning: editor.insert is deprecated. Use the insertText method instead.'); + return this.insertText(text) + } /** * Inserts `text` into wherever the cursor is pointing. diff --git a/lib/ace/placeholder.js b/lib/ace/placeholder.js index 9d0a3c3c..c9a44e50 100644 --- a/lib/ace/placeholder.js +++ b/lib/ace/placeholder.js @@ -167,7 +167,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; if(otherPos.row === range.start.row && range.start.column < otherPos.column) newPos.column += lengthDiff; - this.doc.insertLines(newPos, delta.lines); + this.doc.insertMergedLines(newPos, delta.lines); } } else if(delta.action === "delete") { for (var i = this.others.length - 1; i >= 0; i--) { From 026af74016a2829003a7dfa2ccde906309abd40b Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Wed, 1 Jan 2014 12:04:12 -0600 Subject: [PATCH 003/315] Fix render bugs Both were introduced in 2e6f12725bc01011c545c99c1f1c1da6065063d9. --- lib/ace/editor.js | 8 ++++++-- lib/ace/layer/gutter.js | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 2854eaaf..73873b4a 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -601,10 +601,14 @@ var Editor = function(renderer, session) { * **/ this.onDocumentChange = function(e) { - this.renderer.updateLines(e.data.range.start.row, e.data.range.end.row); + + // Rerender and emit "change" event. + var range = e.data.range; + var lastRow = (range.start.row == range.end.row ? range.end.row : Infinity); + this.renderer.updateLines(range.start.row, lastRow); this._emit("change", e); - // update cursor because tab characters can influence the cursor position. + // Update cursor because tab characters can influence the cursor position. this.$cursorChange(); }; diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index 9d813d2a..82dcf245 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -109,7 +109,7 @@ var Gutter = function(parentEl) { if (len === 0) { // do nothing } else if (delta.action == "delete") { - this.$annotations.splice(firstRow, len, null); + this.$annotations.splice(firstRow, len + 1, null); } else { var args = new Array(len + 1); args.unshift(firstRow, 1); From 810e196cc6f1d49da208c8c4ed98045e6c29ebbb Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Wed, 1 Jan 2014 12:06:19 -0600 Subject: [PATCH 004/315] Use console.warn for deprecated methods console.warn makes better sense than console.log and matches similar warnings in ace (see gutter.js for example). --- lib/ace/document.js | 10 +++++----- lib/ace/edit_session.js | 2 +- lib/ace/editor.js | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index 07726de7..c689553c 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -288,23 +288,23 @@ var Document = function(textOrLines) { // Deprecated methods retained for backwards compatibility. this.insert = function(position, text){ - console.log('Warning: document.insert is deprecated. Use the insertText method instead.'); + console.warn('Use of document.insert is deprecated. Use the insertText method instead.'); return this.insertText(position, text); } this.insertLines = function(row, lines) { - console.log('Warning: document.insertLines is deprecated. Use the insertFullLines method instead.'); + console.warn('Use of document.insertLines is deprecated. Use the insertFullLines method instead.'); return this.insertFullLines(row, lines); } this.removeLines = function(firstRow, lastRow) { - console.log('Warning: document.removeLines is deprecated. Use the removeFullLines method instead.'); + console.warn('Use of document.removeLines is deprecated. Use the removeFullLines method instead.'); return this.removeFullLines(firstRow, lastRow); } this.insertNewLine = function(position) { - console.log('Warning: document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead.'); + console.warn('Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead.'); return this.insertMergedLines(position, ['', '']); } this.insertInLine = function(position, text) { - console.log('Warning: document.insertInLine is deprecated. Use insertText instead.'); + console.warn('Use of document.insertInLine is deprecated. Use insertText instead.'); return this.insertText(position, text); } diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index e48bdc37..0845418b 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1130,7 +1130,7 @@ var EditSession = function(text, mode) { // Deprecated method retained for backwards compatibility. this.insert = function(position, text){ - console.log('Warning: editsession.insert is deprecated. Use the insertText method instead.'); + console.warn('Use of editsession.insert is deprecated. Use the insertText method instead.'); return this.insertText(position, text) } diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 73873b4a..6f5980a1 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -832,7 +832,7 @@ var Editor = function(renderer, session) { // Deprecated method retained for backwards compatibility. this.insert = function(text){ - console.log('Warning: editor.insert is deprecated. Use the insertText method instead.'); + console.warn('Use of editor.insert is deprecated. Use the insertText method instead.'); return this.insertText(text) } From 612478e39f26e32c985ca8e66b8a4a37ca3834a5 Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Wed, 1 Jan 2014 14:45:54 -0600 Subject: [PATCH 005/315] Speed up single-line deltas 2e6f12725bc01011c545c99c1f1c1da6065063d9 slowed down the application of deltas that only affect a single line. The slow-down, though trivial for a single line, is significant for operations than separately modify thousands of rows (such as indenting a large document). This commit speeds up single-line deltas by avoiding unnecessary calls to splitLine() and joinLineWithNext(). --- lib/ace/document.js | 70 ++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index c689553c..9d6aaac3 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -261,9 +261,13 @@ var Document = function(textOrLines) { throw errorText; } + // Validate action. + if (delta.action != 'insert' && delta.action != 'delete') + fnThrow('Delta action must be "insert" or "delete".'); + // Validate lines. if (!delta.lines instanceof Array) - fnThrow('Delta object lines must be an array'); + fnThrow('Delta lines must be an array'); // Validate range type. if (!delta.range instanceof Range) @@ -567,30 +571,50 @@ var Document = function(textOrLines) { this.$validateDelta(delta); // Apply delta. - switch (delta.action) + if (delta.range.start.row == delta.range.end.row) { - case 'insert': - splitLine(this.$lines, delta.range.start); - for (var i = 0; i < delta.lines.length; i++) { - var row = delta.range.start.row + 1 + i; - this.$lines.splice(row, 0, delta.lines[i]); - } - joinLineWithNext(this.$lines, delta.range.start.row); - joinLineWithNext(this.$lines, delta.range.end.row); - break; + // Apply single-line delta. + // Note: The multi-line code below correctly handle single-line + // deltas too, but we need to short-circuit for speed. + var row = delta.range.start.row; + var startColumn = delta.range.start.column; + var endColumn = delta.range.end.column; + var line = this.$lines[row]; + switch (delta.action) { + + case 'insert': + this.$lines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); + break; + + case 'delete': + this.$lines[row] = line.substring(0, startColumn) + line.substring(endColumn); + break; + } + } else { - case 'delete': - splitLine(this.$lines, delta.range.end); - splitLine(this.$lines, delta.range.start); - this.$lines.splice( - delta.range.start.row + 1, // Where to start deleting - delta.range.end.row - delta.range.start.row + 1 // Num lines to delete. - ); - joinLineWithNext(this.$lines, delta.range.start.row); - break; - - default: - throw 'Invalid delta type: ' + delta.action + // Apply multi-line delta. + switch (delta.action) { + + case 'insert': + splitLine(this.$lines, delta.range.start); + for (var i = 0; i < delta.lines.length; i++) { + var row = delta.range.start.row + 1 + i; + this.$lines.splice(row, 0, delta.lines[i]); + } + joinLineWithNext(this.$lines, delta.range.start.row); + joinLineWithNext(this.$lines, delta.range.end.row); + break; + + case 'delete': + splitLine(this.$lines, delta.range.end); + splitLine(this.$lines, delta.range.start); + this.$lines.splice( + delta.range.start.row + 1, // Where to start deleting + delta.range.end.row - delta.range.start.row + 1 // Num lines to delete. + ); + joinLineWithNext(this.$lines, delta.range.start.row); + break; + } } this._emit("change", { data: delta }); From b503e65e0370cb01a251a34719bde5ddb508e2c4 Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Fri, 3 Jan 2014 14:59:22 -0600 Subject: [PATCH 006/315] Break on applyDelta into its own module This makes it possible to break out helper functions without exposing them to the rest of the document class. Also, long term, we may want to have a stand-alone test suite for applyDelta, so it makes sense in its own file. All other changes involve syntax corrections (some syntax issues were mine, others pre-existed) to make the documentation compilation work. --- lib/ace/apply_delta.js | 137 +++++++++++++++++++++++++++ lib/ace/document.js | 204 +++++++++++++--------------------------- lib/ace/edit_session.js | 14 +-- lib/ace/editor.js | 8 +- lib/ace/scrollbar.js | 8 +- 5 files changed, 215 insertions(+), 156 deletions(-) create mode 100644 lib/ace/apply_delta.js diff --git a/lib/ace/apply_delta.js b/lib/ace/apply_delta.js new file mode 100644 index 00000000..02c0a498 --- /dev/null +++ b/lib/ace/apply_delta.js @@ -0,0 +1,137 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var Range = require("./range").Range; + +function splitLine (lines, point) { + var text = lines[point.row]; + lines[point.row] = text.slice(0, point.column); + lines.splice(point.row + 1, 0, text.slice(point.column)); +} + +function joinLineWithNext(lines, row) { + lines[row] += lines[row + 1]; + lines.splice(row + 1, 1); +} + +function throwDeltaError(delta, errorText){ + errorText = 'Invalid Delta: ' + errorText; + console.log(errorText, delta); + throw errorText; +} + +function validateDelta(lines, delta) { + + // Validate action. + if (delta.action != 'insert' && delta.action != 'delete') + fnThrow('Delta action must be "insert" or "delete".'); + + // Validate lines. + if (!delta.lines instanceof Array) + fnThrow('Delta lines must be an array'); + + // Validate range type. + if (!delta.range instanceof Range) + fnThrow('Range object is not an instance of the Range class'); + + // Validate start point. + var start = delta.range.start; + if (Math.min(Math.max(start.row, 0), lines.length - 1 ) != start.row || + Math.min(Math.max(start.column, 0), lines[start.row].length) != start.column) + { + fnThrow('Range start point not contained in document'); + } + + // Validate ending row offset. + if (delta.lines.length - 1 != delta.range.end.row - delta.range.start.row) + fnThrow('Range row offsets does not match delta lines'); + + // TODO: + // - Validate that the ending column offset matches the lines. + // - Validate the deleted lines match the lines in the document. +} + + +exports.applyDelta = function(lines, delta) { + + // Validate delta. + validateDelta(lines, delta); + + // Apply delta. + if (delta.range.start.row == delta.range.end.row) + { + // Apply single-line delta. + // Note: The multi-line code below correctly handle single-line + // deltas too, but we need to short-circuit for speed. + var row = delta.range.start.row; + var startColumn = delta.range.start.column; + var endColumn = delta.range.end.column; + var line = lines[row]; + switch (delta.action) { + + case 'insert': + lines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); + break; + + case 'delete': + lines[row] = line.substring(0, startColumn) + line.substring(endColumn); + break; + } + } else { + + // Apply multi-line delta. + switch (delta.action) { + + case 'insert': + splitLine(lines, delta.range.start); + for (var i = 0; i < delta.lines.length; i++) { + var row = delta.range.start.row + 1 + i; + lines.splice(row, 0, delta.lines[i]); + } + joinLineWithNext(lines, delta.range.start.row); + joinLineWithNext(lines, delta.range.end.row); + break; + + case 'delete': + splitLine(lines, delta.range.end); + splitLine(lines, delta.range.start); + lines.splice( + delta.range.start.row + 1, // Where to start deleting + delta.range.end.row - delta.range.start.row + 1 // Num lines to delete. + ); + joinLineWithNext(lines, delta.range.start.row); + break; + } + } +} +}); diff --git a/lib/ace/document.js b/lib/ace/document.js index 9d6aaac3..768182a4 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -32,6 +32,7 @@ define(function(require, exports, module) { "use strict"; var oop = require("./lib/oop"); +var applyDelta = require("./apply_delta").applyDelta; var EventEmitter = require("./lib/event_emitter").EventEmitter; var Range = require("./range").Range; var Anchor = require("./anchor").Anchor; @@ -56,7 +57,7 @@ var Document = function(textOrLines) { // There has to be one line at least in the document. If you pass an empty // string to the insert function, nothing will happen. Workaround. - if (textOrLines.length == 0) { + if (textOrLines.length === 0) { this.$lines = [""]; } else if (Array.isArray(textOrLines)) { this.insertMergedLines({row: 0, column: 0}, textOrLines); @@ -107,10 +108,10 @@ var Document = function(textOrLines) { **/ // check for IE split bug - if ("aaa".split(/a/).length == 0) + if ("aaa".split(/a/).length === 0) this.$split = function(text) { return text.replace(/\r\n|\r/g, "\n").split("\n"); - } + }; else this.$split = function(text) { return text.split(/\r\n|\r|\n/); @@ -205,30 +206,41 @@ var Document = function(textOrLines) { }; /** - * [Given a range within the document, this function returns all the text within that range as a single string.]{: #Document.getTextRange.desc} - * @param {Range} range The range to work with + * Returns all the text within `range` as a single string. + * @param {Range} range The range to work with. * * @returns {String} **/ this.getTextRange = function(range) { - return this._getLinesForRange(range).join(this.getNewLineCharacter()); + return this.getLinesForRange(range).join(this.getNewLineCharacter()); }; - this._getLinesForRange = function(range) { + /** + * Returns all the text within `range` as an array of lines. + * @param {Range} range The range to work with. + * + * @returns {Array} + **/ + this.getLinesForRange = function(range) { + var lines; if (range.start.row == range.end.row) { - return [this.getLine(range.start.row) - .substring(range.start.column, range.end.column)]; + + // Handle a single-line range. + lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)]; + + } else { + + // Handle a multi-line range. + lines = this.getLines(range.start.row, range.end.row); + lines[0] = (lines[0] || "").substring(range.start.column); + var l = lines.length - 1; + if (range.end.row - range.start.row == l) + lines[l] = lines[l].substring(0, range.end.column); } - var lines = this.getLines(range.start.row, range.end.row); - lines[0] = (lines[0] || "").substring(range.start.column); - var l = lines.length - 1; - if (range.end.row - range.start.row == l) - lines[l] = lines[l].substring(0, range.end.column); return lines; }; this.$clipPosition = function(position) { - var length = this.getLength(); if (position.row >= length) { position.row = Math.max(0, length - 1); @@ -240,8 +252,8 @@ var Document = function(textOrLines) { return position; }; - this.$getClippedRange = function(range) - { + this.$getClippedRange = function(range) { + // Get Range object. if (!range instanceof Range) range = Range.fromPoints(range.start, range.end); @@ -250,67 +262,29 @@ var Document = function(textOrLines) { this.$clipPosition(range.start); this.$clipPosition(range.end); return range; - } + }; - this.$validateDelta = function(delta) - { - function fnThrow(errorText) - { - errorText = 'Invalid Delta: ' + errorText; - console.log(errorText, delta); - throw errorText; - } - - // Validate action. - if (delta.action != 'insert' && delta.action != 'delete') - fnThrow('Delta action must be "insert" or "delete".'); - - // Validate lines. - if (!delta.lines instanceof Array) - fnThrow('Delta lines must be an array'); - - // Validate range type. - if (!delta.range instanceof Range) - fnThrow('Range object is not an instance of the Range class'); - - // Validate start point. - var start = delta.range.start; - if (Math.min(Math.max(start.row, 0), this.getLength() - 1 ) != start.row || - Math.min(Math.max(start.column, 0), this.$lines[start.row].length) != start.column) - { - fnThrow('Range start point not contained in document'); - } - - // Validate ending row offset. - if (delta.lines.length - 1 != delta.range.end.row - delta.range.start.row) - fnThrow('Range row offsets does not match delta lines'); - - // TODO: - // - Validate that the ending column offset matches the lines. - // - Validate the deleted lines match the lines in the document. - }, - // Deprecated methods retained for backwards compatibility. this.insert = function(position, text){ console.warn('Use of document.insert is deprecated. Use the insertText method instead.'); return this.insertText(position, text); - } + }; this.insertLines = function(row, lines) { console.warn('Use of document.insertLines is deprecated. Use the insertFullLines method instead.'); return this.insertFullLines(row, lines); - } + }; this.removeLines = function(firstRow, lastRow) { console.warn('Use of document.removeLines is deprecated. Use the removeFullLines method instead.'); return this.removeFullLines(firstRow, lastRow); - } + }; this.insertNewLine = function(position) { console.warn('Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead.'); return this.insertMergedLines(position, ['', '']); - } + }; this.insertInLine = function(position, text) { console.warn('Use of document.insertInLine is deprecated. Use insertText instead.'); return this.insertText(position, text); - } + }; /** * Inserts a block of `text` at the indicated `position`. @@ -374,12 +348,12 @@ var Document = function(textOrLines) { // Insert after the last row in the document. lines = [''].concat(lines); row--; - var column = this.$lines[row].length; + column = this.$lines[row].length; } // Insert. this.insertMergedLines({row: row, column: column}, lines); - }, + }; /** * Inserts the elements in `lines` into the document, starting at the position index given by `row`. This method also triggers the `'change'` event. @@ -412,7 +386,7 @@ var Document = function(textOrLines) { }); return endPoint; - } + }; /** * Removes the `range` from the document. @@ -427,7 +401,7 @@ var Document = function(textOrLines) { this.applyDelta({ action: 'delete', range: range, - lines: this._getLinesForRange(range), + lines: this.getLinesForRange(range), }); return range.start; }; @@ -450,7 +424,7 @@ var Document = function(textOrLines) { this.applyDelta({ action: "delete", range: range, - lines: this._getLinesForRange(range) + lines: this.getLinesForRange(range) }); return range.start; @@ -487,7 +461,7 @@ var Document = function(textOrLines) { this.applyDelta({ action: "delete", range: range, - lines: this._getLinesForRange(range) + lines: this.getLinesForRange(range) }); // Return the deleted lines. @@ -524,7 +498,7 @@ var Document = function(textOrLines) { this.replace = function(range, text) { if (!range instanceof Range) range = Range.fromPoints(range.start, range.end); - if (text.length == 0 && range.isEmpty()) + if (text.length === 0 && range.isEmpty()) return range.start; // Shortcut: If the text we want to insert is the same as it is already @@ -533,8 +507,9 @@ var Document = function(textOrLines) { return range.end; this.remove(range); + var end; if (text) { - var end = this.insertText(range.start, text); + end = this.insertText(range.start, text); } else { end = range.start; @@ -544,7 +519,8 @@ var Document = function(textOrLines) { }; /** - * Applies all the changes previously accumulated. These can be either `'insert'` or `'delete'`. + * Applies all changes in `deltas` to the document. + * @param {Array} deltas An array of delta objects (can include 'insert' and 'delete' actions) **/ this.applyDeltas = function(deltas) { for (var i=0; i=0; i--) { @@ -629,6 +538,19 @@ var Document = function(textOrLines) { } }; + /** + * Applies `delta` to the document. + * @param {Object} delta A delta object (can include 'insert' and 'delete' actions) + **/ + this.applyDelta = function(delta) { + applyDelta(this.$lines, delta); + this._emit("change", { data: delta }); + }; + + /** + * Reverts `delta` from the document. + * @param {Object} delta A delta object (can include 'insert' and 'delete' actions) + **/ this.revertDelta = function(delta) { this.applyDelta({ @@ -636,8 +558,8 @@ var Document = function(textOrLines) { range: delta.range.clone(), lines: delta.lines.slice() }); - }, - + }; + /** * Converts an index position in a document to a `{row, column}` object. * diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 0845418b..0d4df080 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1131,8 +1131,8 @@ var EditSession = function(text, mode) { // Deprecated method retained for backwards compatibility. this.insert = function(position, text){ console.warn('Use of editsession.insert is deprecated. Use the insertText method instead.'); - return this.insertText(position, text) - } + return this.insertText(position, text); + }; /** * Inserts a block of `text` and the indicated `position`. @@ -1168,8 +1168,8 @@ var EditSession = function(text, mode) { * **/ this.removeFullLines = function(firstRow, lastRow){ - return this.doc.removeFullLines(firstRow, lastRow) - } + return this.doc.removeFullLines(firstRow, lastRow); + }; /** * Reverts previous changes to your document. @@ -1619,7 +1619,7 @@ var EditSession = function(text, mode) { * @private **/ this.adjustWrapLimit = function(desiredLimit, $printMargin) { - var limits = this.$wrapLimitRange + var limits = this.$wrapLimitRange; if (limits.max < 0) limits = {min: $printMargin, max: $printMargin}; var wrapLimit = this.$constrainWrapLimit(desiredLimit, limits.min, limits.max); @@ -1738,7 +1738,7 @@ var EditSession = function(text, mode) { var foldLine = this.getFoldLine(firstRow); var idx = 0; if (foldLine) { - var cmp = foldLine.range.compareInside(start.row, start.column) + var cmp = foldLine.range.compareInside(start.row, start.column); // Inside of the foldLine range. Need to split stuff up. if (cmp == 0) { foldLine = foldLine.split(start.row, start.column); @@ -2215,7 +2215,7 @@ var EditSession = function(text, mode) { return { row: maxRow, column: this.getLine(maxRow).length - } + }; } else { line = this.getLine(docRow); foldLine = null; diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 6f5980a1..79f59e68 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -833,8 +833,8 @@ var Editor = function(renderer, session) { // Deprecated method retained for backwards compatibility. this.insert = function(text){ console.warn('Use of editor.insert is deprecated. Use the insertText method instead.'); - return this.insertText(text) - } + return this.insertText(text); + }; /** * Inserts `text` into wherever the cursor is pointing. @@ -876,7 +876,7 @@ var Editor = function(renderer, session) { } if (text == "\n" || text == "\r\n") { - var line = session.getLine(cursor.row) + var line = session.getLine(cursor.row); if (cursor.column > line.search(/\S|$/)) { var d = line.substr(cursor.column).search(/\S|$/); session.doc.removeInLine(cursor.row, cursor.column, cursor.column + d); @@ -1362,7 +1362,7 @@ var Editor = function(renderer, session) { } } - var line = session.getLine(range.start.row) + var line = session.getLine(range.start.row); var position = range.start; var size = session.getTabSize(); var column = session.documentToScreenColumn(position.row, position.column); diff --git a/lib/ace/scrollbar.js b/lib/ace/scrollbar.js index 28f41fe4..466d1af1 100644 --- a/lib/ace/scrollbar.js +++ b/lib/ace/scrollbar.js @@ -156,9 +156,9 @@ oop.inherits(VScrollBar, ScrollBar); * Sets the scroll top of the scroll bar. * @param {Number} scrollTop The new scroll top **/ - // on chrome 17+ for small zoom levels after calling this function - // this.element.scrollTop != scrollTop which makes page to scroll up. this.setScrollTop = function(scrollTop) { + // on chrome 17+ for small zoom levels after calling this function + // this.element.scrollTop != scrollTop which makes page to scroll up. if (this.scrollTop != scrollTop) { this.skipEvent = true; this.scrollTop = this.element.scrollTop = scrollTop; @@ -249,9 +249,9 @@ oop.inherits(HScrollBar, ScrollBar); * Sets the scroll left of the scroll bar. * @param {Number} scrollTop The new scroll left **/ - // on chrome 17+ for small zoom levels after calling this function - // this.element.scrollTop != scrollTop which makes page to scroll up. this.setScrollLeft = function(scrollLeft) { + // on chrome 17+ for small zoom levels after calling this function + // this.element.scrollTop != scrollTop which makes page to scroll up. if (this.scrollLeft != scrollLeft) { this.skipEvent = true; this.scrollLeft = this.element.scrollLeft = scrollLeft; From 8624ab8dcb9bac917488feb8856e8b709418adb7 Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Sat, 4 Jan 2014 01:59:30 -0600 Subject: [PATCH 007/315] Stop using splice.appy() in ace Since .apply() can't handle more than 65535 parameters, splice.apply() is brittle. It's also hard to read. This replaces splice.apply() calls throughout ace code with lang.spliceIntoArray(). --- lib/ace/background_tokenizer.js | 14 ++++++++------ lib/ace/edit_session.js | 14 +++++++------- lib/ace/edit_session/folding.js | 6 +++--- lib/ace/layer/gutter.js | 5 ++--- lib/ace/lib/lang.js | 14 ++++++++++++++ lib/ace/line_widgets.js | 5 ++--- lib/ace/mode/asciidoc_highlight_rules.js | 8 +++++--- lib/ace/mode/text_highlight_rules.js | 6 +++--- lib/ace/snippets.js | 18 +++++++++--------- 9 files changed, 53 insertions(+), 37 deletions(-) diff --git a/lib/ace/background_tokenizer.js b/lib/ace/background_tokenizer.js index cb3ffe23..4b82f19a 100644 --- a/lib/ace/background_tokenizer.js +++ b/lib/ace/background_tokenizer.js @@ -32,6 +32,7 @@ define(function(require, exports, module) { "use strict"; var oop = require("./lib/oop"); +var lang = require("./lib/lang"); var EventEmitter = require("./lib/event_emitter").EventEmitter; @@ -187,14 +188,15 @@ var BackgroundTokenizer = function(tokenizer, editor) { this.lines.splice(startRow, len + 1, null); this.states.splice(startRow, len + 1, null); } else { - var args = Array(len + 1); - args.unshift(startRow, 1); - this.lines.splice.apply(this.lines, args); - this.states.splice.apply(this.states, args); + this.lines.splice( startRow, 1); + this.states.splice(startRow, 1); + var toInsert = Array(len + 1); + lang.spliceIntoArray(this.lines, startRow, toInsert); + lang.spliceIntoArray(this.states, startRow, toInsert); } - + this.currentLine = Math.min(startRow, this.currentLine, this.doc.getLength()); - + this.stop(); }; diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 0d4df080..cd14c1a5 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1723,15 +1723,15 @@ var EditSession = function(text, mode) { } else { var args; if (useWrapMode) { - args = [firstRow, 0]; - for (var i = 0; i < len; i++) args.push([]); - this.$wrapData.splice.apply(this.$wrapData, args); + var toInsert = []; + for (var i = 0; i < len; i++) + toInsert.push([]); + lang.spliceIntoArray(this.$wrapData, firstRow, toInsert); } else { - args = Array(len); - args.unshift(firstRow, 0); - this.$rowLengthCache.splice.apply(this.$rowLengthCache, args); + var toInsert = Array(len); + lang.spliceIntoArray(this.$rowLengthCache, firstRow, toInsert); } - + // If some new line is added inside of a foldLine, then split // the fold line up. var foldLines = this.$foldData; diff --git a/lib/ace/edit_session/folding.js b/lib/ace/edit_session/folding.js index 9df35593..1563bd67 100644 --- a/lib/ace/edit_session/folding.js +++ b/lib/ace/edit_session/folding.js @@ -31,6 +31,7 @@ define(function(require, exports, module) { "use strict"; +var lang = require("../lib/lang"); var Range = require("../range").Range; var FoldLine = require("./fold_line").FoldLine; var Fold = require("./fold").Fold; @@ -836,9 +837,8 @@ function Folding() { } else if (delta.action == "delete") { this.foldWidgets.splice(firstRow, len + 1, null); } else { - var args = Array(len + 1); - args.unshift(firstRow, 1); - this.foldWidgets.splice.apply(this.foldWidgets, args); + this.foldWidgets.splice(firstRow, 1); + lang.spliceIntoArray(this.foldWidgets, firstRow, Array(len + 1)); } }; diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index 82dcf245..24f9c430 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -111,9 +111,8 @@ var Gutter = function(parentEl) { } else if (delta.action == "delete") { this.$annotations.splice(firstRow, len + 1, null); } else { - var args = new Array(len + 1); - args.unshift(firstRow, 1); - this.$annotations.splice.apply(this.$annotations, args); + this.$annotations.splice(firstRow, 1); + lang.spliceIntoArray(this.$annotations, firstRow, new Array(len + 1)); } }; diff --git a/lib/ace/lib/lang.js b/lib/ace/lib/lang.js index 4405b5c2..e0e9d826 100644 --- a/lib/ace/lib/lang.js +++ b/lib/ace/lib/lang.js @@ -123,6 +123,20 @@ exports.arrayRemove = function(array, value) { } }; +/* + * Splice the items in `a2` into `a1` at position `offset`. + */ +exports.spliceIntoArray = function(a1, offset, a2) { + + // Handle negative offsets. + if (offset < 0) + offset = Math.max(a1.length + offset, 0); + + // Splice. + for (var i = 0; i < a2.length; i++) + a1.splice(i + offset, 0, a2[i]); +} + exports.escapeRegExp = function(str) { return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1'); }; diff --git a/lib/ace/line_widgets.js b/lib/ace/line_widgets.js index 4023bd55..7cbe9809 100644 --- a/lib/ace/line_widgets.js +++ b/lib/ace/line_widgets.js @@ -32,6 +32,7 @@ define(function(require, exports, module) { "use strict"; var oop = require("./lib/oop"); +var lang = require("./lib/lang"); var dom = require("./lib/dom"); var Range = require("./range").Range; @@ -130,9 +131,7 @@ function LineWidgets(session) { }, this); this.$updateRows(); } else { - var args = Array(len); - args.unshift(startRow, 0); - cells.splice.apply(cells, args); + lang.spliceIntoArray(cells, startRow, new Array(len)); this.$updateRows(); } }; diff --git a/lib/ace/mode/asciidoc_highlight_rules.js b/lib/ace/mode/asciidoc_highlight_rules.js index c0d1a305..308fc8e4 100644 --- a/lib/ace/mode/asciidoc_highlight_rules.js +++ b/lib/ace/mode/asciidoc_highlight_rules.js @@ -32,6 +32,7 @@ define(function(require, exports, module) { "use strict"; var oop = require("../lib/oop"); +var lang = require("../lib/lang"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var AsciidocHighlightRules = function() { @@ -215,13 +216,14 @@ var AsciidocHighlightRules = function() { for (var i = stateRules.length; i--; ) { var rule = stateRules[i]; if (rule.include || typeof rule == "string") { - var args = [i, 1].concat(this.$rules[rule.include || rule]); + var toInsert = this.$rules[rule.include || rule]; if (rule.noEscape) { - args = args.filter(function(x) { + toInsert = toInsert.filter(function(x) { return !x.next; }); } - stateRules.splice.apply(stateRules, args); + stateRules.splice(i, 1); + lang.spliceIntoArray(stateRules, i, toInsert); } else if (rule.token in tokenMap) { rule.token = tokenMap[rule.token]; } diff --git a/lib/ace/mode/text_highlight_rules.js b/lib/ace/mode/text_highlight_rules.js index 48e016b0..9e304a53 100644 --- a/lib/ace/mode/text_highlight_rules.js +++ b/lib/ace/mode/text_highlight_rules.js @@ -181,10 +181,10 @@ var TextHighlightRules = function() { toInsert = rule; if (toInsert) { - var args = [i, 1].concat(toInsert); if (rule.noEscape) - args = args.filter(function(x) {return !x.next;}); - state.splice.apply(state, args); + toInsert = toInsert.filter(function(x) {return !x.next;}); + state.splice(i, 1); + lang.spliceIntoArray(state, i, toInsert); // skip included rules since they are already processed //i += args.length - 3; i--; diff --git a/lib/ace/snippets.js b/lib/ace/snippets.js index ee1a5498..e5d585bb 100644 --- a/lib/ace/snippets.js +++ b/lib/ace/snippets.js @@ -335,12 +335,12 @@ var SnippetManager = function() { } var ts = tabstops[id]; - var arg = typeof ts.value == "string" ? [ts.value] : copyValue(ts.value); - arg.unshift(i + 1, Math.max(0, i1 - i)); - arg.push(p); + var toInsert = typeof ts.value == "string" ? [ts.value] : copyValue(ts.value); + toInsert.push(p); expanding[id] = p; - tokens.splice.apply(tokens, arg); - + tokens.splice(i + 1, Math.max(0, i1 - i)); + lang.spliceIntoArray(tokens, i + 1, toInsert); + if (ts.indexOf(p) === -1) ts.push(p); }; @@ -755,7 +755,7 @@ var TabstopManager = function(editor) { } var i = this.index; - var arg = [i, 0]; + var toInsert = []; var ranges = this.ranges; var editor = this.editor; tabstops.forEach(function(ts) { @@ -776,12 +776,12 @@ var TabstopManager = function(editor) { } if (!ts.firstNonLinked) ts.hasLinkedRanges = false; - arg.push(ts); + toInsert.push(ts); this.addTabstopMarkers(ts); }, this); // tabstop 0 is the last one - arg.push(arg.splice(2, 1)[0]); - this.tabstops.splice.apply(this.tabstops, arg); + toInsert.push(toInsert.splice(0, 1)[0]); + lang.spliceIntoArray(this.tabstops, this.index, toInsert); }; this.addTabstopMarkers = function(ts) { From 91df7cd6635110dca0a97e7419150739f8d9ffd6 Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Wed, 8 Jan 2014 21:39:30 -0600 Subject: [PATCH 008/315] Revert "Stop using splice.appy() in ace" This reverts commit 8624ab8dcb9bac917488feb8856e8b709418adb7. --- lib/ace/background_tokenizer.js | 14 ++++++-------- lib/ace/edit_session.js | 14 +++++++------- lib/ace/edit_session/folding.js | 6 +++--- lib/ace/layer/gutter.js | 5 +++-- lib/ace/lib/lang.js | 14 -------------- lib/ace/line_widgets.js | 5 +++-- lib/ace/mode/asciidoc_highlight_rules.js | 8 +++----- lib/ace/mode/text_highlight_rules.js | 6 +++--- lib/ace/snippets.js | 18 +++++++++--------- 9 files changed, 37 insertions(+), 53 deletions(-) diff --git a/lib/ace/background_tokenizer.js b/lib/ace/background_tokenizer.js index 4b82f19a..cb3ffe23 100644 --- a/lib/ace/background_tokenizer.js +++ b/lib/ace/background_tokenizer.js @@ -32,7 +32,6 @@ define(function(require, exports, module) { "use strict"; var oop = require("./lib/oop"); -var lang = require("./lib/lang"); var EventEmitter = require("./lib/event_emitter").EventEmitter; @@ -188,15 +187,14 @@ var BackgroundTokenizer = function(tokenizer, editor) { this.lines.splice(startRow, len + 1, null); this.states.splice(startRow, len + 1, null); } else { - this.lines.splice( startRow, 1); - this.states.splice(startRow, 1); - var toInsert = Array(len + 1); - lang.spliceIntoArray(this.lines, startRow, toInsert); - lang.spliceIntoArray(this.states, startRow, toInsert); + var args = Array(len + 1); + args.unshift(startRow, 1); + this.lines.splice.apply(this.lines, args); + this.states.splice.apply(this.states, args); } - + this.currentLine = Math.min(startRow, this.currentLine, this.doc.getLength()); - + this.stop(); }; diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index cd14c1a5..0d4df080 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1723,15 +1723,15 @@ var EditSession = function(text, mode) { } else { var args; if (useWrapMode) { - var toInsert = []; - for (var i = 0; i < len; i++) - toInsert.push([]); - lang.spliceIntoArray(this.$wrapData, firstRow, toInsert); + args = [firstRow, 0]; + for (var i = 0; i < len; i++) args.push([]); + this.$wrapData.splice.apply(this.$wrapData, args); } else { - var toInsert = Array(len); - lang.spliceIntoArray(this.$rowLengthCache, firstRow, toInsert); + args = Array(len); + args.unshift(firstRow, 0); + this.$rowLengthCache.splice.apply(this.$rowLengthCache, args); } - + // If some new line is added inside of a foldLine, then split // the fold line up. var foldLines = this.$foldData; diff --git a/lib/ace/edit_session/folding.js b/lib/ace/edit_session/folding.js index 1563bd67..9df35593 100644 --- a/lib/ace/edit_session/folding.js +++ b/lib/ace/edit_session/folding.js @@ -31,7 +31,6 @@ define(function(require, exports, module) { "use strict"; -var lang = require("../lib/lang"); var Range = require("../range").Range; var FoldLine = require("./fold_line").FoldLine; var Fold = require("./fold").Fold; @@ -837,8 +836,9 @@ function Folding() { } else if (delta.action == "delete") { this.foldWidgets.splice(firstRow, len + 1, null); } else { - this.foldWidgets.splice(firstRow, 1); - lang.spliceIntoArray(this.foldWidgets, firstRow, Array(len + 1)); + var args = Array(len + 1); + args.unshift(firstRow, 1); + this.foldWidgets.splice.apply(this.foldWidgets, args); } }; diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index 24f9c430..82dcf245 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -111,8 +111,9 @@ var Gutter = function(parentEl) { } else if (delta.action == "delete") { this.$annotations.splice(firstRow, len + 1, null); } else { - this.$annotations.splice(firstRow, 1); - lang.spliceIntoArray(this.$annotations, firstRow, new Array(len + 1)); + var args = new Array(len + 1); + args.unshift(firstRow, 1); + this.$annotations.splice.apply(this.$annotations, args); } }; diff --git a/lib/ace/lib/lang.js b/lib/ace/lib/lang.js index e0e9d826..4405b5c2 100644 --- a/lib/ace/lib/lang.js +++ b/lib/ace/lib/lang.js @@ -123,20 +123,6 @@ exports.arrayRemove = function(array, value) { } }; -/* - * Splice the items in `a2` into `a1` at position `offset`. - */ -exports.spliceIntoArray = function(a1, offset, a2) { - - // Handle negative offsets. - if (offset < 0) - offset = Math.max(a1.length + offset, 0); - - // Splice. - for (var i = 0; i < a2.length; i++) - a1.splice(i + offset, 0, a2[i]); -} - exports.escapeRegExp = function(str) { return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1'); }; diff --git a/lib/ace/line_widgets.js b/lib/ace/line_widgets.js index 7cbe9809..4023bd55 100644 --- a/lib/ace/line_widgets.js +++ b/lib/ace/line_widgets.js @@ -32,7 +32,6 @@ define(function(require, exports, module) { "use strict"; var oop = require("./lib/oop"); -var lang = require("./lib/lang"); var dom = require("./lib/dom"); var Range = require("./range").Range; @@ -131,7 +130,9 @@ function LineWidgets(session) { }, this); this.$updateRows(); } else { - lang.spliceIntoArray(cells, startRow, new Array(len)); + var args = Array(len); + args.unshift(startRow, 0); + cells.splice.apply(cells, args); this.$updateRows(); } }; diff --git a/lib/ace/mode/asciidoc_highlight_rules.js b/lib/ace/mode/asciidoc_highlight_rules.js index 308fc8e4..c0d1a305 100644 --- a/lib/ace/mode/asciidoc_highlight_rules.js +++ b/lib/ace/mode/asciidoc_highlight_rules.js @@ -32,7 +32,6 @@ define(function(require, exports, module) { "use strict"; var oop = require("../lib/oop"); -var lang = require("../lib/lang"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var AsciidocHighlightRules = function() { @@ -216,14 +215,13 @@ var AsciidocHighlightRules = function() { for (var i = stateRules.length; i--; ) { var rule = stateRules[i]; if (rule.include || typeof rule == "string") { - var toInsert = this.$rules[rule.include || rule]; + var args = [i, 1].concat(this.$rules[rule.include || rule]); if (rule.noEscape) { - toInsert = toInsert.filter(function(x) { + args = args.filter(function(x) { return !x.next; }); } - stateRules.splice(i, 1); - lang.spliceIntoArray(stateRules, i, toInsert); + stateRules.splice.apply(stateRules, args); } else if (rule.token in tokenMap) { rule.token = tokenMap[rule.token]; } diff --git a/lib/ace/mode/text_highlight_rules.js b/lib/ace/mode/text_highlight_rules.js index 9e304a53..48e016b0 100644 --- a/lib/ace/mode/text_highlight_rules.js +++ b/lib/ace/mode/text_highlight_rules.js @@ -181,10 +181,10 @@ var TextHighlightRules = function() { toInsert = rule; if (toInsert) { + var args = [i, 1].concat(toInsert); if (rule.noEscape) - toInsert = toInsert.filter(function(x) {return !x.next;}); - state.splice(i, 1); - lang.spliceIntoArray(state, i, toInsert); + args = args.filter(function(x) {return !x.next;}); + state.splice.apply(state, args); // skip included rules since they are already processed //i += args.length - 3; i--; diff --git a/lib/ace/snippets.js b/lib/ace/snippets.js index e5d585bb..ee1a5498 100644 --- a/lib/ace/snippets.js +++ b/lib/ace/snippets.js @@ -335,12 +335,12 @@ var SnippetManager = function() { } var ts = tabstops[id]; - var toInsert = typeof ts.value == "string" ? [ts.value] : copyValue(ts.value); - toInsert.push(p); + var arg = typeof ts.value == "string" ? [ts.value] : copyValue(ts.value); + arg.unshift(i + 1, Math.max(0, i1 - i)); + arg.push(p); expanding[id] = p; - tokens.splice(i + 1, Math.max(0, i1 - i)); - lang.spliceIntoArray(tokens, i + 1, toInsert); - + tokens.splice.apply(tokens, arg); + if (ts.indexOf(p) === -1) ts.push(p); }; @@ -755,7 +755,7 @@ var TabstopManager = function(editor) { } var i = this.index; - var toInsert = []; + var arg = [i, 0]; var ranges = this.ranges; var editor = this.editor; tabstops.forEach(function(ts) { @@ -776,12 +776,12 @@ var TabstopManager = function(editor) { } if (!ts.firstNonLinked) ts.hasLinkedRanges = false; - toInsert.push(ts); + arg.push(ts); this.addTabstopMarkers(ts); }, this); // tabstop 0 is the last one - toInsert.push(toInsert.splice(0, 1)[0]); - lang.spliceIntoArray(this.tabstops, this.index, toInsert); + arg.push(arg.splice(2, 1)[0]); + this.tabstops.splice.apply(this.tabstops, arg); }; this.addTabstopMarkers = function(ts) { From 6fe381f6335790f7a0ee6646cdcb9ab442893df5 Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Wed, 8 Jan 2014 22:00:11 -0600 Subject: [PATCH 009/315] Rename insertText back to insert --- lib/ace/anchor_test.js | 2 +- lib/ace/autocomplete.js | 2 +- lib/ace/background_tokenizer_test.js | 2 +- lib/ace/commands/default_commands.js | 4 ++-- lib/ace/document.js | 16 ++++++---------- lib/ace/document_test.js | 8 ++++---- lib/ace/edit_session.js | 14 ++++---------- lib/ace/edit_session_test.js | 4 ++-- lib/ace/editor.js | 20 +++++++------------- lib/ace/editor_change_document_test.js | 2 +- lib/ace/editor_navigation_test.js | 2 +- lib/ace/ext/elastic_tabstops_lite.js | 2 +- lib/ace/ext/whitespace.js | 2 +- lib/ace/keyboard/vim/commands.js | 10 +++++----- lib/ace/keyboard/vim/maps/motions.js | 6 +++--- lib/ace/mode/javascript_test.js | 2 +- lib/ace/mode/text.js | 12 ++++++------ lib/ace/mouse/dragdrop_handler.js | 2 +- lib/ace/multi_select.js | 8 ++++---- lib/ace/occur_test.js | 12 ++++++------ lib/ace/placeholder_test.js | 18 +++++++++--------- 21 files changed, 67 insertions(+), 83 deletions(-) diff --git a/lib/ace/anchor_test.js b/lib/ace/anchor_test.js index 0661765b..d40d459b 100644 --- a/lib/ace/anchor_test.js +++ b/lib/ace/anchor_test.js @@ -54,7 +54,7 @@ module.exports = { var doc = new Document("juhu\nkinners"); var anchor = new Anchor(doc, 1, 4); - doc.insertText({row: 1, column: 1}, "123"); + doc.insert({row: 1, column: 1}, "123"); assert.position(anchor.getPosition(), 1, 7); }, diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index 2344aede..50154c01 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -170,7 +170,7 @@ var Autocomplete = function() { "Ctrl-Down|Ctrl-End": function(editor) { editor.completer.goTo("end"); }, "Esc": function(editor) { editor.completer.detach(); }, - "Space": function(editor) { editor.completer.detach(); editor.insertText(" ");}, + "Space": function(editor) { editor.completer.detach(); editor.insert(" ");}, "Return": function(editor) { editor.completer.insertMatch(); }, "Shift-Return": function(editor) { editor.completer.insertMatch(true); }, "Tab": function(editor) { editor.completer.insertMatch(); }, diff --git a/lib/ace/background_tokenizer_test.js b/lib/ace/background_tokenizer_test.js index 16c63132..7a4cc78c 100644 --- a/lib/ace/background_tokenizer_test.js +++ b/lib/ace/background_tokenizer_test.js @@ -70,7 +70,7 @@ module.exports = { forceTokenize(doc) testStates(doc, ["comment_regex_allowed", "comment_regex_allowed"]) - doc.insertText({row:0, column:2}, "\n*/") + doc.insert({row:0, column:2}, "\n*/") testStates(doc, [undefined, undefined, "comment_regex_allowed"]) forceTokenize(doc) diff --git a/lib/ace/commands/default_commands.js b/lib/ace/commands/default_commands.js index 0fd9686c..e4a8212e 100644 --- a/lib/ace/commands/default_commands.js +++ b/lib/ace/commands/default_commands.js @@ -508,13 +508,13 @@ exports.commands = [{ scrollIntoView: "selectionPart" }, { name: "insertstring", - exec: function(editor, str) { editor.insertText(str); }, + exec: function(editor, str) { editor.insert(str); }, multiSelectAction: "forEach", scrollIntoView: "cursor" }, { name: "inserttext", exec: function(editor, args) { - editor.insertText(lang.stringRepeat(args.text || "", args.times || 1)); + editor.insert(lang.stringRepeat(args.text || "", args.times || 1)); }, multiSelectAction: "forEach" }, { diff --git a/lib/ace/document.js b/lib/ace/document.js index 768182a4..a84d3bcc 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -62,7 +62,7 @@ var Document = function(textOrLines) { } else if (Array.isArray(textOrLines)) { this.insertMergedLines({row: 0, column: 0}, textOrLines); } else { - this.insertText({row: 0, column:0}, textOrLines); + this.insert({row: 0, column:0}, textOrLines); } }; @@ -78,7 +78,7 @@ var Document = function(textOrLines) { this.setValue = function(text) { var len = this.getLength(); this.remove(new Range(0, 0, len, this.getLine(len-1).length)); - this.insertText({row: 0, column:0}, text); + this.insert({row: 0, column:0}, text); }; /** @@ -265,10 +265,6 @@ var Document = function(textOrLines) { }; // Deprecated methods retained for backwards compatibility. - this.insert = function(position, text){ - console.warn('Use of document.insert is deprecated. Use the insertText method instead.'); - return this.insertText(position, text); - }; this.insertLines = function(row, lines) { console.warn('Use of document.insertLines is deprecated. Use the insertFullLines method instead.'); return this.insertFullLines(row, lines); @@ -282,8 +278,8 @@ var Document = function(textOrLines) { return this.insertMergedLines(position, ['', '']); }; this.insertInLine = function(position, text) { - console.warn('Use of document.insertInLine is deprecated. Use insertText instead.'); - return this.insertText(position, text); + console.warn('Use of document.insertInLine is deprecated. Use insert instead.'); + return this.insert(position, text); }; /** @@ -293,7 +289,7 @@ var Document = function(textOrLines) { * @returns {Object} The position ({row, column}) of the last line of `text`. If the length of `text` is 0, this function simply returns `position`. * **/ - this.insertText = function(position, text) { + this.insert = function(position, text) { // Only detect new lines if the document has no line break yet. if (this.getLength() <= 1) @@ -509,7 +505,7 @@ var Document = function(textOrLines) { this.remove(range); var end; if (text) { - end = this.insertText(range.start, text); + end = this.insert(range.start, text); } else { end = range.start; diff --git a/lib/ace/document_test.js b/lib/ace/document_test.js index c29d6133..a91fccf2 100644 --- a/lib/ace/document_test.js +++ b/lib/ace/document_test.js @@ -48,7 +48,7 @@ module.exports = { var deltas = []; doc.on("change", function(e) { deltas.push(e.data); }); - doc.insertText({row: 0, column: 1}, "juhu"); + doc.insert({row: 0, column: 1}, "juhu"); assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n")); var d = deltas.concat(); @@ -126,7 +126,7 @@ module.exports = { var deltas = []; doc.on("change", function(e) { deltas.push(e.data); }); - doc.insertText({row: 0, column: 0}, "aa\nbb\ncc"); + doc.insert({row: 0, column: 0}, "aa\nbb\ncc"); assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n")); var d = deltas.concat(); @@ -143,7 +143,7 @@ module.exports = { var deltas = []; doc.on("change", function(e) { deltas.push(e.data); }); - doc.insertText({row: 1, column: 2}, "aa\nbb\ncc"); + doc.insert({row: 1, column: 2}, "aa\nbb\ncc"); assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n")); var d = deltas.concat(); @@ -160,7 +160,7 @@ module.exports = { var deltas = []; doc.on("change", function(e) { deltas.push(e.data); }); - doc.insertText({row: 0, column: 1}, "aa\nbb\ncc"); + doc.insert({row: 0, column: 1}, "aa\nbb\ncc"); assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n")); var d = deltas.concat(); diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 0d4df080..f140bdac 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1127,12 +1127,6 @@ var EditSession = function(text, mode) { this.getTextRange = function(range) { return this.doc.getTextRange(range || this.selection.getRange()); }; - - // Deprecated method retained for backwards compatibility. - this.insert = function(position, text){ - console.warn('Use of editsession.insert is deprecated. Use the insertText method instead.'); - return this.insertText(position, text); - }; /** * Inserts a block of `text` and the indicated `position`. @@ -1142,8 +1136,8 @@ var EditSession = function(text, mode) { * * **/ - this.insertText = function(position, text) { - return this.doc.insertText(position, text); + this.insert = function(position, text) { + return this.doc.insert(position, text); }; /** @@ -1356,7 +1350,7 @@ var EditSession = function(text, mode) { } } - toRange.end = this.insertText(toRange.start, text); + toRange.end = this.insert(toRange.start, text); if (folds.length) { var oldStart = fromRange.start; var newStart = toRange.start; @@ -1390,7 +1384,7 @@ var EditSession = function(text, mode) { this.indentRows = function(startRow, endRow, indentString) { indentString = indentString.replace(/\t/g, this.getTabString()); for (var row=startRow; row<=endRow; row++) - this.insertText({row: row, column:0}, indentString); + this.insert({row: row, column:0}, indentString); }; /** diff --git a/lib/ace/edit_session_test.js b/lib/ace/edit_session_test.js index fd20259c..75abf468 100644 --- a/lib/ace/edit_session_test.js +++ b/lib/ace/edit_session_test.js @@ -649,7 +649,7 @@ module.exports = { var foldLines = session.$foldData; function insert(row, column, text) { - session.insertText({row: row, column: column}, text); + session.insert({row: row, column: column}, text); // Force the session to store all changes made to the document NOW // on the undoManager's queue. Otherwise we can't undo in separate @@ -748,7 +748,7 @@ module.exports = { undoManager = session.getUndoManager(), foldLines = session.$foldData; function insert(row, column, text) { - session.insertText({row: row, column: column}, text); + session.insert({row: row, column: column}, text); // Force the session to store all changes made to the document NOW // on the undoManager's queue. Otherwise we can't undo in separate // steps later. diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 79f59e68..af991ef1 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -822,19 +822,13 @@ var Editor = function(renderer, session) { if (this.$readOnly) return; this._emit("paste", text); - this.insertText(text); + this.insert(text); }; this.execCommand = function(command, args) { this.commands.exec(command, this, args); }; - - // Deprecated method retained for backwards compatibility. - this.insert = function(text){ - console.warn('Use of editor.insert is deprecated. Use the insertText method instead.'); - return this.insertText(text); - }; /** * Inserts `text` into wherever the cursor is pointing. @@ -842,7 +836,7 @@ var Editor = function(renderer, session) { * * **/ - this.insertText = function(text) { + this.insert = function(text) { var session = this.session; var mode = session.getMode(); var cursor = this.getCursorPosition(); @@ -888,7 +882,7 @@ var Editor = function(renderer, session) { var lineState = session.getState(cursor.row); var line = session.getLine(cursor.row); var shouldOutdent = mode.checkOutdent(lineState, line, text); - var end = session.insertText(cursor, text); + var end = session.insert(cursor, text); if (transform && transform.selection) { if (transform.selection.length == 2) { // Transform relative to the current column @@ -907,7 +901,7 @@ var Editor = function(renderer, session) { if (session.getDocument().isNewLine(text)) { var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString()); - session.insertText({row: cursor.row+1, column: 0}, lineIndent); + session.insert({row: cursor.row+1, column: 0}, lineIndent); } if (shouldOutdent) mode.autoOutdent(lineState, session, cursor.row); @@ -1280,7 +1274,7 @@ var Editor = function(renderer, session) { } var cursor = this.getCursorPosition(); - this.insertText("\n"); + this.insert("\n"); this.moveCursorToPosition(cursor); }; @@ -1379,7 +1373,7 @@ var Editor = function(renderer, session) { this.selection.setSelectionRange(range); indentString = "\t"; } - return this.insertText(indentString); + return this.insert(indentString); }; /** @@ -1531,7 +1525,7 @@ var Editor = function(renderer, session) { doc.duplicateLines(row, row); } else { var point = reverse ? range.start : range.end; - var endPoint = doc.insertText(point, doc.getTextRange(range), false); + var endPoint = doc.insert(point, doc.getTextRange(range), false); range.start = point; range.end = endPoint; diff --git a/lib/ace/editor_change_document_test.js b/lib/ace/editor_change_document_test.js index 83fffeb3..a1fdaad9 100644 --- a/lib/ace/editor_change_document_test.js +++ b/lib/ace/editor_change_document_test.js @@ -172,7 +172,7 @@ module.exports = { self.session1.setMode(new HtmlMode()); // 5. Try to type valid HTML - self.session1.insertText({row: 0, column: 0}, ""); + self.session1.insert({row: 0, column: 0}, ""); setTimeout(function() { assert.equal(Object.keys(self.session1.getAnnotations()).length, 0); diff --git a/lib/ace/editor_navigation_test.js b/lib/ace/editor_navigation_test.js index b60d391d..ab348241 100644 --- a/lib/ace/editor_navigation_test.js +++ b/lib/ace/editor_navigation_test.js @@ -150,7 +150,7 @@ module.exports = { var editor = new Editor(new MockRenderer(), new EditSession(["1234", "1234567890"])); editor.navigateTo(0, 3); - editor.insertText("juhu"); + editor.insert("juhu"); editor.navigateDown(); assert.position(editor.getCursorPosition(), 1, 7); diff --git a/lib/ace/ext/elastic_tabstops_lite.js b/lib/ace/ext/elastic_tabstops_lite.js index 4d3a40d4..a8c3570c 100644 --- a/lib/ace/ext/elastic_tabstops_lite.js +++ b/lib/ace/ext/elastic_tabstops_lite.js @@ -236,7 +236,7 @@ var ElasticTabstopsLite = function(editor) { if (difference > 0) { // put the spaces after the tab and then delete the tab, so any insertion // points behave as expected - this.$editor.session.getDocument().insertText({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t"); + this.$editor.session.getDocument().insert({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t"); this.$editor.session.getDocument().removeInLine(row, it, it + 1); bias += difference; diff --git a/lib/ace/ext/whitespace.js b/lib/ace/ext/whitespace.js index 736e991d..be0cde28 100644 --- a/lib/ace/ext/whitespace.js +++ b/lib/ace/ext/whitespace.js @@ -153,7 +153,7 @@ exports.convertIndentation = function(session, ch, len) { if (toInsert != match) { doc.removeInLine(i, 0, match.length); - doc.insertText({row: i, column: 0}, toInsert); + doc.insert({row: i, column: 0}, toInsert); } } } diff --git a/lib/ace/keyboard/vim/commands.js b/lib/ace/keyboard/vim/commands.js index defca037..dd3357d6 100644 --- a/lib/ace/keyboard/vim/commands.js +++ b/lib/ace/keyboard/vim/commands.js @@ -104,7 +104,7 @@ var actions = exports.actions = { if (param && param.length) { if (param.length > 1) param = param == "return" ? "\n" : param == "tab" ? "\t" : param; - repeat(function() { editor.insertText(param); }, count || 1); + repeat(function() { editor.insert(param); }, count || 1); editor.navigateLeft(); } } @@ -224,12 +224,12 @@ var actions = exports.actions = { var pos = editor.getCursorPosition(); pos.column = editor.session.getLine(pos.row).length; var text = lang.stringRepeat("\n" + defaultReg.text, count || 1); - editor.session.insertText(pos, text); + editor.session.insert(pos, text); editor.moveCursorTo(pos.row + 1, 0); } else { editor.navigateRight(); - editor.insertText(lang.stringRepeat(defaultReg.text, count || 1)); + editor.insert(lang.stringRepeat(defaultReg.text, count || 1)); editor.navigateLeft(); } editor.setOverwrite(true); @@ -245,11 +245,11 @@ var actions = exports.actions = { var pos = editor.getCursorPosition(); pos.column = 0; var text = lang.stringRepeat(defaultReg.text + "\n", count || 1); - editor.session.insertText(pos, text); + editor.session.insert(pos, text); editor.moveCursorToPosition(pos); } else { - editor.insertText(lang.stringRepeat(defaultReg.text, count || 1)); + editor.insert(lang.stringRepeat(defaultReg.text, count || 1)); } editor.setOverwrite(true); editor.selection.clearSelection(); diff --git a/lib/ace/keyboard/vim/maps/motions.js b/lib/ace/keyboard/vim/maps/motions.js index 2bf580b0..91c8b8af 100644 --- a/lib/ace/keyboard/vim/maps/motions.js +++ b/lib/ace/keyboard/vim/maps/motions.js @@ -545,7 +545,7 @@ module.exports = { if (content.length) { editor.navigateLineEnd() - editor.insertText(content); + editor.insert(content); util.insertMode(editor); } } @@ -562,9 +562,9 @@ module.exports = { if(row > 0) { editor.navigateUp(); editor.navigateLineEnd() - editor.insertText(content); + editor.insert(content); } else { - editor.session.insertText({row: 0, column: 0}, content); + editor.session.insert({row: 0, column: 0}, content); editor.navigateUp(); } util.insertMode(editor); diff --git a/lib/ace/mode/javascript_test.js b/lib/ace/mode/javascript_test.js index cc2b22d7..b413765a 100644 --- a/lib/ace/mode/javascript_test.js +++ b/lib/ace/mode/javascript_test.js @@ -131,7 +131,7 @@ module.exports = { this.mode.toggleCommentLines("start", session, 0, 2); assert.equal([" abc", " cde", " fg"].join("\n"), session.toString()); - session.insertText({row: 0, column: 0}, " "); + session.insert({row: 0, column: 0}, " "); this.mode.toggleCommentLines("start", session, 0, 2); assert.equal(["// abc", "// cde", "// fg"].join("\n"), session.toString()); }, diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index 534ac03c..76ba15b5 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -92,8 +92,8 @@ var Mode = function() { if (testRemove(line, i)) return; if (!ignoreBlankLines || /\S/.test(line)) { - doc.insertText({row: i, column: line.length}, lineCommentEnd); - doc.insertText({row: i, column: minIndent}, lineCommentStart); + doc.insert({row: i, column: line.length}, lineCommentEnd); + doc.insert({row: i, column: minIndent}, lineCommentStart); } }; @@ -138,9 +138,9 @@ var Mode = function() { var comment = function(line, i) { if (!ignoreBlankLines || /\S/.test(line)) { if (shouldInsertSpace(line, minIndent, minIndent)) - doc.insertText({row: i, column: minIndent}, commentWithSpace); + doc.insert({row: i, column: minIndent}, commentWithSpace); else - doc.insertText({row: i, column: minIndent}, lineCommentStart); + doc.insert({row: i, column: minIndent}, lineCommentStart); } }; var testRemove = function(line, i) { @@ -244,8 +244,8 @@ var Mode = function() { } else { colDiff = comment.start.length startRow = range.start.row; - session.insertText(range.end, comment.end); - session.insertText(range.start, comment.start); + session.insert(range.end, comment.end); + session.insert(range.start, comment.start); } // todo: selection should have ended up in the right place automatically! if (initialRange.start.row == startRow) diff --git a/lib/ace/mouse/dragdrop_handler.js b/lib/ace/mouse/dragdrop_handler.js index 3ad54bb8..3a4bc188 100644 --- a/lib/ace/mouse/dragdrop_handler.js +++ b/lib/ace/mouse/dragdrop_handler.js @@ -176,7 +176,7 @@ function DragdropHandler(mouseHandler) { var dropData = dataTransfer.getData('Text'); range = { start: dragCursor, - end: editor.session.insertText(dragCursor, dropData) + end: editor.session.insert(dragCursor, dropData) }; editor.focus(); dragOperation = null; diff --git a/lib/ace/multi_select.js b/lib/ace/multi_select.js index 883d9a7c..965cd961 100644 --- a/lib/ace/multi_select.js +++ b/lib/ace/multi_select.js @@ -544,7 +544,7 @@ var Editor = require("./editor").Editor; this._signal("paste", text); if (!this.inMultiSelectMode || this.inVirtualSelectionMode) - return this.insertText(text); + return this.insert(text); var lines = text.split(/\r\n|\r|\n/); var ranges = this.selection.rangeList.ranges; @@ -557,7 +557,7 @@ var Editor = require("./editor").Editor; if (!range.isEmpty()) this.session.remove(range); - this.session.insertText(range.start, lines[i]); + this.session.insert(range.start, lines[i]); } }; @@ -742,7 +742,7 @@ var Editor = require("./editor").Editor; } var lines = this.session.removeFullLines(fr, lr); lines = this.$reAlignText(lines, guessRange); - this.session.insertText({row: fr, column: 0}, lines.join("\n") + "\n"); + this.session.insert({row: fr, column: 0}, lines.join("\n") + "\n"); if (!guessRange) { range.start.column = 0; range.end.column = lines[lines.length - 1].length; @@ -778,7 +778,7 @@ var Editor = require("./editor").Editor; var l = maxCol - p.column; var d = spaceOffsets[i] - minSpace; if (l > d) - session.insertText(p, lang.stringRepeat(" ", l - d)); + session.insert(p, lang.stringRepeat(" ", l - d)); else session.remove(new Range(p.row, p.column, p.row, p.column - l + d)); diff --git a/lib/ace/occur_test.js b/lib/ace/occur_test.js index a9b2c894..59fb8548 100644 --- a/lib/ace/occur_test.js +++ b/lib/ace/occur_test.js @@ -55,7 +55,7 @@ module.exports = { }, "test: find lines matching" : function() { - editor.session.insertText({row: 0, column: 0}, 'abc\ndef\nxyz\nbcxbc'); + editor.session.insert({row: 0, column: 0}, 'abc\ndef\nxyz\nbcxbc'); var result = occur.matchingLines(editor.session, {needle: 'bc'}), expected = [{row: 0, content: 'abc'}, {row: 3, content: 'bcxbc'}]; assert.deepEqual(result, expected); @@ -63,7 +63,7 @@ module.exports = { "test: display occurrences" : function() { var text = 'abc\ndef\nxyz\nbcx\n'; - editor.session.insertText({row: 0, column: 0}, text); + editor.session.insert({row: 0, column: 0}, text); occur.displayOccurContent(editor, {needle: 'bc'}); assert.equal(editor.getValue(), 'abc\nbcx'); occur.displayOriginalContent(editor); @@ -72,7 +72,7 @@ module.exports = { "test: original position from occur doc" : function() { var text = 'abc\ndef\nxyz\nbcx\n'; - editor.session.insertText({row: 0, column: 0}, text); + editor.session.insert({row: 0, column: 0}, text); occur.displayOccurContent(editor, {needle: 'bc'}); assert.equal(editor.getValue(), 'abc\nbcx'); var pos = occur.occurToOriginalPosition(editor.session, {row: 1, column: 2}); @@ -82,7 +82,7 @@ module.exports = { "test: occur command" : function() { // setup var text = 'hel\nlo\n\nwo\nrld\n'; - editor.session.insertText({row: 0, column: 0}, text); + editor.session.insert({row: 0, column: 0}, text); editor.commands.addCommand(occurStartCommand); // run occur for lines including 'o' @@ -106,7 +106,7 @@ module.exports = { "test: occur navigation" : function() { // setup var text = 'hel\nlo\n\nwo\nrld\n'; - editor.session.insertText({row: 0, column: 0}, text); + editor.session.insert({row: 0, column: 0}, text); editor.commands.addCommand(occurStartCommand); editor.moveCursorToPosition({row: 1, column: 1}); @@ -125,7 +125,7 @@ module.exports = { "test: recursive occur" : function() { // setup var text = 'x\nabc1\nx\nabc2\n'; - editor.session.insertText({row: 0, column: 0}, text); + editor.session.insert({row: 0, column: 0}, text); editor.commands.addCommand(occurStartCommand); // orig -> occur1 diff --git a/lib/ace/placeholder_test.js b/lib/ace/placeholder_test.js index dc7e4b23..97e561fd 100644 --- a/lib/ace/placeholder_test.js +++ b/lib/ace/placeholder_test.js @@ -53,9 +53,9 @@ module.exports = { new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]); editor.moveCursorTo(0, 5); - editor.insertText('b'); + editor.insert('b'); assert.equal(session.doc.getValue(), "var ab = 10;\nconsole.log(ab, ab);"); - editor.insertText('cd'); + editor.insert('cd'); assert.equal(session.doc.getValue(), "var abcd = 10;\nconsole.log(abcd, abcd);"); editor.remove('left'); editor.remove('left'); @@ -70,7 +70,7 @@ module.exports = { new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]); editor.moveCursorTo(2, 0); - editor.insertText('b'); + editor.insert('b'); assert.equal(session.doc.getValue(), "var a = 10;\nconsole.log(a, a);\nb"); }, @@ -81,12 +81,12 @@ module.exports = { var p = new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]); editor.moveCursorTo(0, 4); - editor.insertText('$'); + editor.insert('$'); assert.equal(session.doc.getValue(), "var $a = 10;\nconsole.log($a, $a);"); editor.moveCursorTo(0, 4); // Have to put this in a setTimeout because the anchor is only fixed later. setTimeout(function() { - editor.insertText('v'); + editor.insert('v'); assert.equal(session.doc.getValue(), "var v$a = 10;\nconsole.log(v$a, v$a);"); next(); }, 10); @@ -99,10 +99,10 @@ module.exports = { var p = new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]); editor.moveCursorTo(0, 5); - editor.insertText('b'); + editor.insert('b'); assert.equal(session.doc.getValue(), "var ab = 10;\nconsole.log(ab, ab);"); p.detach(); - editor.insertText('cd'); + editor.insert('cd'); assert.equal(session.doc.getValue(), "var abcd = 10;\nconsole.log(ab, ab);"); }, @@ -136,8 +136,8 @@ module.exports = { var p = new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]); editor.moveCursorTo(0, 5); - editor.insertText('b'); - editor.insertText('cd'); + editor.insert('b'); + editor.insert('cd'); editor.remove('left'); assert.equal(session.doc.getValue(), "var abc = 10;\nconsole.log(abc, abc);"); // Wait a little for the changes to enter the undo stack From f2a2e4e1a8ce7870824beea9c956ae2671aadc86 Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Wed, 8 Jan 2014 22:18:05 -0600 Subject: [PATCH 010/315] Rename the 'delete' delta action to 'remove' Matches previous naming convention. --- lib/ace/anchor.js | 2 +- lib/ace/apply_delta.js | 8 ++++---- lib/ace/background_tokenizer.js | 2 +- lib/ace/document.js | 20 ++++++++++---------- lib/ace/edit_session.js | 4 ++-- lib/ace/edit_session/folding.js | 2 +- lib/ace/ext/chromevox.js | 2 +- lib/ace/layer/gutter.js | 2 +- lib/ace/line_widgets.js | 2 +- lib/ace/placeholder.js | 4 ++-- 10 files changed, 24 insertions(+), 24 deletions(-) diff --git a/lib/ace/anchor.js b/lib/ace/anchor.js index affb4f19..fee42bb5 100644 --- a/lib/ace/anchor.js +++ b/lib/ace/anchor.js @@ -133,7 +133,7 @@ var Anchor = exports.Anchor = function(doc, row, column) { } // DELTA ENVELOPS POINT (delete only): Move point to delta start. - if (delta.action != 'delete') + if (delta.action != 'remove') throw 'Delete action expected.'; return { diff --git a/lib/ace/apply_delta.js b/lib/ace/apply_delta.js index 02c0a498..142d5e1c 100644 --- a/lib/ace/apply_delta.js +++ b/lib/ace/apply_delta.js @@ -53,8 +53,8 @@ function throwDeltaError(delta, errorText){ function validateDelta(lines, delta) { // Validate action. - if (delta.action != 'insert' && delta.action != 'delete') - fnThrow('Delta action must be "insert" or "delete".'); + if (delta.action != 'insert' && delta.action != 'remove') + fnThrow('Delta action must be "insert" or "remove".'); // Validate lines. if (!delta.lines instanceof Array) @@ -103,7 +103,7 @@ exports.applyDelta = function(lines, delta) { lines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); break; - case 'delete': + case 'remove': lines[row] = line.substring(0, startColumn) + line.substring(endColumn); break; } @@ -122,7 +122,7 @@ exports.applyDelta = function(lines, delta) { joinLineWithNext(lines, delta.range.end.row); break; - case 'delete': + case 'remove': splitLine(lines, delta.range.end); splitLine(lines, delta.range.start); lines.splice( diff --git a/lib/ace/background_tokenizer.js b/lib/ace/background_tokenizer.js index cb3ffe23..4d3d7034 100644 --- a/lib/ace/background_tokenizer.js +++ b/lib/ace/background_tokenizer.js @@ -183,7 +183,7 @@ var BackgroundTokenizer = function(tokenizer, editor) { if (len === 0) { this.lines[startRow] = null; - } else if (delta.action == "delete") { + } else if (delta.action == 'remove') { this.lines.splice(startRow, len + 1, null); this.states.splice(startRow, len + 1, null); } else { diff --git a/lib/ace/document.js b/lib/ace/document.js index a84d3bcc..de77582e 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -306,7 +306,7 @@ var Document = function(textOrLines) { * * `"insert"` * * `range`: the [[Range]] of the change within the document * * `lines`: the lines being added - * * `"delete"` + * * `"remove"` * * `range`: the [[Range]] of the change within the document * * `lines`: the lines being removed * @@ -395,7 +395,7 @@ var Document = function(textOrLines) { // Apply delta (emits change). range = this.$getClippedRange(range); this.applyDelta({ - action: 'delete', + action: 'remove', range: range, lines: this.getLinesForRange(range), }); @@ -418,7 +418,7 @@ var Document = function(textOrLines) { // Apply delta (emits change). this.applyDelta({ - action: "delete", + action: 'remove', range: range, lines: this.getLinesForRange(range) }); @@ -455,7 +455,7 @@ var Document = function(textOrLines) { // Apply delta (emits change). this.applyDelta({ - action: "delete", + action: 'remove', range: range, lines: this.getLinesForRange(range) }); @@ -474,7 +474,7 @@ var Document = function(textOrLines) { if (row < this.getLength() - 1 && row >= 0) { // Apply delta (emits change). this.applyDelta({ - action: "delete", + action: 'remove', range: new Range(row, this.getLine(row).length, row + 1, 0), lines: ['', ''] }); @@ -516,7 +516,7 @@ var Document = function(textOrLines) { /** * Applies all changes in `deltas` to the document. - * @param {Array} deltas An array of delta objects (can include 'insert' and 'delete' actions) + * @param {Array} deltas An array of delta objects (can include 'insert' and 'remove' actions) **/ this.applyDeltas = function(deltas) { for (var i=0; i=0; i--) { @@ -536,7 +536,7 @@ var Document = function(textOrLines) { /** * Applies `delta` to the document. - * @param {Object} delta A delta object (can include 'insert' and 'delete' actions) + * @param {Object} delta A delta object (can include 'insert' and 'remove' actions) **/ this.applyDelta = function(delta) { applyDelta(this.$lines, delta); @@ -545,12 +545,12 @@ var Document = function(textOrLines) { /** * Reverts `delta` from the document. - * @param {Object} delta A delta object (can include 'insert' and 'delete' actions) + * @param {Object} delta A delta object (can include 'insert' and 'remove' actions) **/ this.revertDelta = function(delta) { this.applyDelta({ - action: (delta.action == 'insert' ? 'delete' : 'insert'), + action: (delta.action == 'insert' ? 'remove' : 'insert'), range: delta.range.clone(), lines: delta.lines.slice() }); diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index f140bdac..7312f23b 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1685,7 +1685,7 @@ var EditSession = function(text, mode) { this.$updating = true; if (len != 0) { - if (action == "delete") { + if (action == 'remove') { this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len); var foldLines = this.$foldData; @@ -1760,7 +1760,7 @@ var EditSession = function(text, mode) { // Realign folds. E.g. if you add some new chars before a fold, the // fold should "move" to the right. len = Math.abs(e.data.range.start.column - e.data.range.end.column); - if (action == "delete") { + if (action == 'remove') { // Get all the folds in the change range and remove them. removedFolds = this.getFoldsInRange(e.data.range); this.removeFolds(removedFolds); diff --git a/lib/ace/edit_session/folding.js b/lib/ace/edit_session/folding.js index 9df35593..583dba0d 100644 --- a/lib/ace/edit_session/folding.js +++ b/lib/ace/edit_session/folding.js @@ -833,7 +833,7 @@ function Folding() { if (len === 0) { this.foldWidgets[firstRow] = null; - } else if (delta.action == "delete") { + } else if (delta.action == 'remove') { this.foldWidgets.splice(firstRow, len + 1, null); } else { var args = Array(len + 1); diff --git a/lib/ace/ext/chromevox.js b/lib/ace/ext/chromevox.js index 20bbb6c7..4abb8278 100644 --- a/lib/ace/ext/chromevox.js +++ b/lib/ace/ext/chromevox.js @@ -581,7 +581,7 @@ var onSelectionChange = function(evt) { var onChange = function(evt) { var data = evt.data; switch (data.action) { - case 'delete': + case 'remove': cvox.Api.speak(data.text, 0, DELETED_PROP); /* Let the future cursor change event know it's from text change. */ changed = true; diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index 82dcf245..235425ab 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -108,7 +108,7 @@ var Gutter = function(parentEl) { var len = range.end.row - firstRow; if (len === 0) { // do nothing - } else if (delta.action == "delete") { + } else if (delta.action == 'remove') { this.$annotations.splice(firstRow, len + 1, null); } else { var args = new Array(len + 1); diff --git a/lib/ace/line_widgets.js b/lib/ace/line_widgets.js index 4023bd55..d0c7581e 100644 --- a/lib/ace/line_widgets.js +++ b/lib/ace/line_widgets.js @@ -123,7 +123,7 @@ function LineWidgets(session) { if (len === 0) { // return - } else if (delta.action == "delete") { + } else if (delta.action == 'remove') { var removed = cells.splice(startRow + 1, len); removed.forEach(function(w) { w && this.removeLineWidget(w); diff --git a/lib/ace/placeholder.js b/lib/ace/placeholder.js index c9a44e50..df0bfa9e 100644 --- a/lib/ace/placeholder.js +++ b/lib/ace/placeholder.js @@ -169,7 +169,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) newPos.column += lengthDiff; this.doc.insertMergedLines(newPos, delta.lines); } - } else if(delta.action === "delete") { + } else if(delta.action === 'remove') { for (var i = this.others.length - 1; i >= 0; i--) { var otherPos = this.others[i]; var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; @@ -191,7 +191,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) } }.bind(this), 0); } - else if(range.start.column === this.pos.column && delta.action === "delete") { + else if(range.start.column === this.pos.column && delta.action === 'remove') { setTimeout(function() { for (var i = 0; i < this.others.length; i++) { var other = this.others[i]; From 3a048cdf611b86151eb28a01af7db666bce39aca Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Wed, 8 Jan 2014 22:51:39 -0600 Subject: [PATCH 011/315] Bring back insertInLine Avoids an extra $split call. --- lib/ace/document.js | 37 +++++++++++++++++++++++++--- lib/ace/ext/elastic_tabstops_lite.js | 2 +- lib/ace/ext/whitespace.js | 2 +- lib/ace/mode/text.js | 4 +-- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index de77582e..6968e8f0 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -277,10 +277,6 @@ var Document = function(textOrLines) { console.warn('Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead.'); return this.insertMergedLines(position, ['', '']); }; - this.insertInLine = function(position, text) { - console.warn('Use of document.insertInLine is deprecated. Use insert instead.'); - return this.insert(position, text); - }; /** * Inserts a block of `text` at the indicated `position`. @@ -298,6 +294,39 @@ var Document = function(textOrLines) { return this.insertMergedLines(position, this.$split(text)); }; + /** + * Inserts `text` into the `position` at the current row. This method also triggers the `'change'` event. + * + * This differs from the `insert` method in two ways: + * 1. This does NOT handle newline characters (single-line text only). + * 2. This is faster than the `insert` method for single-line text insertions. + * + * @param {Object} position The position to insert at; it's an object that looks like `{ row: row, column: column}` + * @param {String} text A chunk of text + * @returns {Object} Returns an object containing the final row and column, like this: + * ``` + * {row: endRow, column: 0} + * ``` + **/ + this.insertInLine = function(position, text) { + + // Calculate insertion range end point. + this.$clipPosition(position); + var endPoint = { + row : position.row, + column : position.column + text.length + }; + + // Apply delta (emits change). + this.applyDelta({ + action: "insert", + range: Range.fromPoints(position, endPoint), + lines: [text] + }); + + return endPoint; + }; + /** * Fires whenever the document changes. * diff --git a/lib/ace/ext/elastic_tabstops_lite.js b/lib/ace/ext/elastic_tabstops_lite.js index a8c3570c..9901c5df 100644 --- a/lib/ace/ext/elastic_tabstops_lite.js +++ b/lib/ace/ext/elastic_tabstops_lite.js @@ -236,7 +236,7 @@ var ElasticTabstopsLite = function(editor) { if (difference > 0) { // put the spaces after the tab and then delete the tab, so any insertion // points behave as expected - this.$editor.session.getDocument().insert({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t"); + this.$editor.session.getDocument().insertInLine({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t"); this.$editor.session.getDocument().removeInLine(row, it, it + 1); bias += difference; diff --git a/lib/ace/ext/whitespace.js b/lib/ace/ext/whitespace.js index be0cde28..83486fb0 100644 --- a/lib/ace/ext/whitespace.js +++ b/lib/ace/ext/whitespace.js @@ -153,7 +153,7 @@ exports.convertIndentation = function(session, ch, len) { if (toInsert != match) { doc.removeInLine(i, 0, match.length); - doc.insert({row: i, column: 0}, toInsert); + doc.insertInLine({row: i, column: 0}, toInsert); } } } diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index 76ba15b5..343fc271 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -92,8 +92,8 @@ var Mode = function() { if (testRemove(line, i)) return; if (!ignoreBlankLines || /\S/.test(line)) { - doc.insert({row: i, column: line.length}, lineCommentEnd); - doc.insert({row: i, column: minIndent}, lineCommentStart); + doc.insertInLine({row: i, column: line.length}, lineCommentEnd); + doc.insertInLine({row: i, column: minIndent}, lineCommentStart); } }; From 08edcdfc988fe8eacc40af4da464fb8ebde8c61c Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Fri, 10 Jan 2014 22:49:17 -0600 Subject: [PATCH 012/315] Stop doing a line-by-line splicing in applyDelta Also brings back the functionality where large deltas are split into smaller deltas so that .splice.apply() calls will work. --- lib/ace/apply_delta.js | 7 ++----- lib/ace/document.js | 30 +++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/lib/ace/apply_delta.js b/lib/ace/apply_delta.js index 142d5e1c..380c3289 100644 --- a/lib/ace/apply_delta.js +++ b/lib/ace/apply_delta.js @@ -79,9 +79,9 @@ function validateDelta(lines, delta) { // TODO: // - Validate that the ending column offset matches the lines. // - Validate the deleted lines match the lines in the document. + // - Vaiidate that an insert delta does not contain more than 65001 entries. } - exports.applyDelta = function(lines, delta) { // Validate delta. @@ -114,10 +114,7 @@ exports.applyDelta = function(lines, delta) { case 'insert': splitLine(lines, delta.range.start); - for (var i = 0; i < delta.lines.length; i++) { - var row = delta.range.start.row + 1 + i; - lines.splice(row, 0, delta.lines[i]); - } + lines.splice.apply(lines, [delta.range.start.row + 1, 0].concat(delta.lines)); joinLineWithNext(lines, delta.range.start.row); joinLineWithNext(lines, delta.range.end.row); break; diff --git a/lib/ace/document.js b/lib/ace/document.js index 6968e8f0..cefaa136 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -568,8 +568,36 @@ var Document = function(textOrLines) { * @param {Object} delta A delta object (can include 'insert' and 'remove' actions) **/ this.applyDelta = function(delta) { + + // Split large insert deltas. This is necessary because: + // 1. We need to support splicing delta lines into the document via $lines.splice.apply(...) + // 2. fn.apply() doesn't work for a large number of params. The mallest threshold is on safari 0xFFFF. + // + // To Do: Ideally we'd be consistent and also split 'delete' deltas. We don't do this now, because delete + // delta handling is too slow. If we make delete delta handling faster we can split all large deltas + // as shown in https://gist.github.com/aldendaniels/8367109#file-document-snippet-js + // If we do this, update validateDelta() to limit the number of lines in a delete delta. + var bIsInsert = delta.action == 'insert'; + while (bIsInsert && delta.lines.length > 65001) + { + // Get split deltas. + var lines = delta.lines.splice(0, 65000); + lines.push(''); + this.applyDelta({ + action: delta.action, + lines: lines, + range: new Range(delta.range.start.row, delta.range.start.column, + delta.range.start.row + 65000, 0) + }); + + // Update remaining delta. + delta.range.start.row += 65000; + delta.range.start.column = 0; + } + + // Apply. applyDelta(this.$lines, delta); - this._emit("change", { data: delta }); + this._emit("change", { data: delta }); }; /** From ef0e8da5223884d4ff041ff59b1711488ca76a4a Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Sat, 11 Jan 2014 11:20:34 -0600 Subject: [PATCH 013/315] Fix / complete validateDelta This uncovered the fact that until now delta.range had not always been a Range object. This inconsistency has been resolved by my changes in mirror.js. --- lib/ace/apply_delta.js | 96 +++++++++++++++++++++------------------- lib/ace/worker/mirror.js | 13 +++++- 2 files changed, 62 insertions(+), 47 deletions(-) diff --git a/lib/ace/apply_delta.js b/lib/ace/apply_delta.js index 380c3289..3d40d614 100644 --- a/lib/ace/apply_delta.js +++ b/lib/ace/apply_delta.js @@ -33,59 +33,63 @@ define(function(require, exports, module) { var Range = require("./range").Range; -function splitLine (lines, point) { - var text = lines[point.row]; - lines[point.row] = text.slice(0, point.column); - lines.splice(point.row + 1, 0, text.slice(point.column)); +function splitLine (docLines, position) { + var text = docLines[position.row]; + docLines[position.row] = text.slice(0, position.column); + docLines.splice(position.row + 1, 0, text.slice(position.column)); } -function joinLineWithNext(lines, row) { - lines[row] += lines[row + 1]; - lines.splice(row + 1, 1); +function joinLineWithNext(docLines, row) { + docLines[row] += docLines[row + 1]; + docLines.splice(row + 1, 1); } function throwDeltaError(delta, errorText){ - errorText = 'Invalid Delta: ' + errorText; - console.log(errorText, delta); - throw errorText; + console.log('Invalid Delta:', delta); + throw 'Invalid Delta: ' + errorText; } -function validateDelta(lines, delta) { +function positionInDocument(docLines, position) +{ + return position.row >= 0 && position.row < docLines.length && + position.column >= 0 && position.column <= docLines[position.row].length; +} - // Validate action. +function validateDelta(docLines, delta) { + + // Validate action string. if (delta.action != 'insert' && delta.action != 'remove') - fnThrow('Delta action must be "insert" or "remove".'); - - // Validate lines. - if (!delta.lines instanceof Array) - fnThrow('Delta lines must be an array'); + throwDeltaError(delta, 'delta.action must be "insert" or "remove"'); + // Validate lines type. + if (!(delta.lines instanceof Array)) + throwDeltaError(delta, 'delta.lines must be an Array'); + // Validate range type. - if (!delta.range instanceof Range) - fnThrow('Range object is not an instance of the Range class'); - - // Validate start point. + if (!(delta.range instanceof Range)) + throwDeltaError(delta, 'delta.range must be an instance of the Range class'); + + // Validate that the start point is contained in the document. var start = delta.range.start; - if (Math.min(Math.max(start.row, 0), lines.length - 1 ) != start.row || - Math.min(Math.max(start.column, 0), lines[start.row].length) != start.column) - { - fnThrow('Range start point not contained in document'); - } + if (!positionInDocument(docLines, delta.range.start)) + throwDeltaError(delta, 'delta.range.start must be contained in document'); - // Validate ending row offset. - if (delta.lines.length - 1 != delta.range.end.row - delta.range.start.row) - fnThrow('Range row offsets does not match delta lines'); + // Validate that the end point is contained in the document (remove deltas only). + var end = delta.range.end; + if (delta.action == 'remove' && !positionInDocument(docLines, end)) + throwDeltaError(delta, 'delta.range.end must contained in document for "remove" actions'); - // TODO: - // - Validate that the ending column offset matches the lines. - // - Validate the deleted lines match the lines in the document. - // - Vaiidate that an insert delta does not contain more than 65001 entries. + // Validate that the .range size matches the .lines size. + var numRangeRows = end.row - start.row; + var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0)); + if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars) + throwDeltaError(delta, 'delta.range must match delta lines'); } -exports.applyDelta = function(lines, delta) { +exports.applyDelta = function(docLines, delta) { // Validate delta. - validateDelta(lines, delta); + validateDelta(docLines, delta); // Apply delta. if (delta.range.start.row == delta.range.end.row) @@ -96,15 +100,15 @@ exports.applyDelta = function(lines, delta) { var row = delta.range.start.row; var startColumn = delta.range.start.column; var endColumn = delta.range.end.column; - var line = lines[row]; + var line = docLines[row]; switch (delta.action) { case 'insert': - lines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); + docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); break; case 'remove': - lines[row] = line.substring(0, startColumn) + line.substring(endColumn); + docLines[row] = line.substring(0, startColumn) + line.substring(endColumn); break; } } else { @@ -113,20 +117,20 @@ exports.applyDelta = function(lines, delta) { switch (delta.action) { case 'insert': - splitLine(lines, delta.range.start); - lines.splice.apply(lines, [delta.range.start.row + 1, 0].concat(delta.lines)); - joinLineWithNext(lines, delta.range.start.row); - joinLineWithNext(lines, delta.range.end.row); + splitLine(docLines, delta.range.start); + docLines.splice.apply(docLines, [delta.range.start.row + 1, 0].concat(delta.lines)); + joinLineWithNext(docLines, delta.range.start.row); + joinLineWithNext(docLines, delta.range.end.row); break; case 'remove': - splitLine(lines, delta.range.end); - splitLine(lines, delta.range.start); - lines.splice( + splitLine(docLines, delta.range.end); + splitLine(docLines, delta.range.start); + docLines.splice( delta.range.start.row + 1, // Where to start deleting delta.range.end.row - delta.range.start.row + 1 // Num lines to delete. ); - joinLineWithNext(lines, delta.range.start.row); + joinLineWithNext(docLines, delta.range.start.row); break; } } diff --git a/lib/ace/worker/mirror.js b/lib/ace/worker/mirror.js index 7a3318fb..d55e84f4 100644 --- a/lib/ace/worker/mirror.js +++ b/lib/ace/worker/mirror.js @@ -1,6 +1,7 @@ define(function(require, exports, module) { "use strict"; +var Range = require("../range").Range; var Document = require("../document").Document; var lang = require("../lib/lang"); @@ -12,7 +13,17 @@ var Mirror = exports.Mirror = function(sender) { var _self = this; sender.on("change", function(e) { - doc.applyDeltas(e.data); + + // Convert delta.range back into a Range instance since + // window.onMessage loses non-primitive data. See http://jsfiddle.net/nqJfw/1/. + var deltas = e.data; + for (var i in deltas) + { + var delta = deltas[i]; + delta.range = Range.fromPoints(delta.range.start, delta.range.end); + } + + doc.applyDeltas(deltas); if (_self.$timeout) return deferredUpdate.schedule(_self.$timeout); _self.onUpdate(); From f59708a5ba7b049271db9846ae8a71e88a9f6625 Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Sat, 11 Jan 2014 12:00:10 -0600 Subject: [PATCH 014/315] Add a doNotValidate param to applyDelta Set it to true in insertInLine/removeInLine. Also sped up indent/dedent by using insertInLine and removeInLine. --- lib/ace/apply_delta.js | 5 +++-- lib/ace/document.js | 12 ++++++------ lib/ace/edit_session.js | 22 +++++++++++----------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/lib/ace/apply_delta.js b/lib/ace/apply_delta.js index 3d40d614..1317ce98 100644 --- a/lib/ace/apply_delta.js +++ b/lib/ace/apply_delta.js @@ -86,10 +86,11 @@ function validateDelta(docLines, delta) { throwDeltaError(delta, 'delta.range must match delta lines'); } -exports.applyDelta = function(docLines, delta) { +exports.applyDelta = function(docLines, delta, doNotValidate) { // Validate delta. - validateDelta(docLines, delta); + if (!doNotValidate) + validateDelta(docLines, delta); // Apply delta. if (delta.range.start.row == delta.range.end.row) diff --git a/lib/ace/document.js b/lib/ace/document.js index cefaa136..c4f8a9eb 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -322,7 +322,7 @@ var Document = function(textOrLines) { action: "insert", range: Range.fromPoints(position, endPoint), lines: [text] - }); + }, true /*doNotValidate*/); return endPoint; }; @@ -449,8 +449,8 @@ var Document = function(textOrLines) { this.applyDelta({ action: 'remove', range: range, - lines: this.getLinesForRange(range) - }); + lines: this.getLinesForRange(range), + }, true /*doNotValidate*/); return range.start; }; @@ -567,7 +567,7 @@ var Document = function(textOrLines) { * Applies `delta` to the document. * @param {Object} delta A delta object (can include 'insert' and 'remove' actions) **/ - this.applyDelta = function(delta) { + this.applyDelta = function(delta, doNotValidate) { // Split large insert deltas. This is necessary because: // 1. We need to support splicing delta lines into the document via $lines.splice.apply(...) @@ -596,8 +596,8 @@ var Document = function(textOrLines) { } // Apply. - applyDelta(this.$lines, delta); - this._emit("change", { data: delta }); + applyDelta(this.$lines, delta, doNotValidate); + this._emit("change", { data: delta }); }; /** diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 7312f23b..414b68c1 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1384,7 +1384,7 @@ var EditSession = function(text, mode) { this.indentRows = function(startRow, endRow, indentString) { indentString = indentString.replace(/\t/g, this.getTabString()); for (var row=startRow; row<=endRow; row++) - this.insert({row: row, column:0}, indentString); + this.doc.insertInLine({row: row, column: 0}, indentString); }; /** @@ -1395,25 +1395,25 @@ var EditSession = function(text, mode) { **/ this.outdentRows = function (range) { var rowRange = range.collapseRows(); - var deleteRange = new Range(0, 0, 0, 0); var size = this.getTabSize(); - + for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) { var line = this.getLine(i); - - deleteRange.start.row = i; - deleteRange.end.row = i; + var row = i; + var startCol = 0; + var endCol = 0; + for (var j = 0; j < size; ++j) if (line.charAt(j) != ' ') break; if (j < size && line.charAt(j) == '\t') { - deleteRange.start.column = j; - deleteRange.end.column = j + 1; + startCol = j; + endCol = j + 1; } else { - deleteRange.start.column = 0; - deleteRange.end.column = j; + startCol = 0; + endCol = j; } - this.remove(deleteRange); + this.doc.removeInLine(row, startCol, endCol); } }; From ddd695ee3f2a1e851c842d4d17851341067d499b Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Sat, 11 Jan 2014 14:43:47 -0600 Subject: [PATCH 015/315] Store single-line deltas as .text instead of .lines in undo history Stores single-line delta content as .text instead of .lines in undo history. This is done without modifying the original delta object in case the caller still retains a handle to the original. --- lib/ace/undomanager.js | 80 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/lib/ace/undomanager.js b/lib/ace/undomanager.js index 304dac23..4d978d46 100644 --- a/lib/ace/undomanager.js +++ b/lib/ace/undomanager.js @@ -61,14 +61,19 @@ var UndoManager = function() { * **/ this.execute = function(options) { - var deltas = options.args[0]; + + // Normalize deltas for storage. + var deltaSets = this.$serializeDeltas(options.args[0]); + + // Add deltas to undo stack. this.$doc = options.args[1]; if (options.merge && this.hasUndo()){ - deltas = this.$undoStack.pop().concat(deltas); + deltaSets = this.$undoStack.pop().concat(deltaSets); } - this.$undoStack.push(deltas); + this.$undoStack.push(deltaSets); + + // Reset redo stack. this.$redoStack = []; - if (this.dirtyCounter < 0) { // The user has made a change after undoing past the last clean state. // We can never get back to a clean state now until markClean() is called. @@ -85,12 +90,11 @@ var UndoManager = function() { * @returns {Range} The range of the undo. **/ this.undo = function(dontSelect) { - var deltas = this.$undoStack.pop(); + var deltaSets = this.$undoStack.pop(); var undoSelectionRange = null; - if (deltas) { - undoSelectionRange = - this.$doc.undoChanges(deltas, dontSelect); - this.$redoStack.push(deltas); + if (deltaSets) { + undoSelectionRange = this.$doc.undoChanges(this.$deserializeDeltas(deltaSets), dontSelect); + this.$redoStack.push(deltaSets); this.dirtyCounter--; } @@ -104,15 +108,14 @@ var UndoManager = function() { * **/ this.redo = function(dontSelect) { - var deltas = this.$redoStack.pop(); + var deltaSets = this.$redoStack.pop(); var redoSelectionRange = null; - if (deltas) { + if (deltaSets) { redoSelectionRange = - this.$doc.redoChanges(deltas, dontSelect); - this.$undoStack.push(deltas); + this.$doc.redoChanges(this.$deserializeDeltas(deltaSets), dontSelect); + this.$undoStack.push(deltaSets); this.dirtyCounter++; } - return redoSelectionRange; }; @@ -160,7 +163,54 @@ var UndoManager = function() { this.isClean = function() { return this.dirtyCounter === 0; }; - + + // Serializes deltaSets to reduce memory usage. + this.$serializeDeltas = function(deltaSets) + { + return this.$cloneDeltaSetsObj(deltaSets, $serializeDelta); + } + function $serializeDelta(delta){ + return { + action: delta.action, + range: delta.range, + lines: (delta.lines.length == 1 ? null : delta.lines), + text: (delta.lines.length == 1 ? delta.lines[0] : null ), + }; + } + + // Deserializes deltaSets to allow application to the document. + this.$deserializeDeltas = function(deltaSets) + { + return this.$cloneDeltaSetsObj(deltaSets, $deserializeDelta); + } + function $deserializeDelta(delta){ + return { + action: delta.action, + range: delta.range, + lines: (delta.text === null ? delta.lines : [delta.text]) + }; + } + + // Helper for delta serialization and deserialization. + this.$cloneDeltaSetsObj = function(deltaSets_old, fnGetModifiedDelta) + { + var deltaSets_new = new Array(deltaSets_old.length); + for (var i in deltaSets_old) + { + var deltaSet_old = deltaSets_old[i]; + var deltaSet_new = { group: deltaSet_old.group, deltas: new Array(deltaSet_old.length)}; + + for (var i_ in deltaSet_old.deltas) + { + var delta_old = deltaSet_old.deltas[i_]; + deltaSet_new.deltas[i_] = fnGetModifiedDelta(delta_old); + } + + deltaSets_new[i] = deltaSet_new; + } + return deltaSets_new; + } + }).call(UndoManager.prototype); exports.UndoManager = UndoManager; From 35a27fd1ba52cccb765f515f3924d9ba579a7eea Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Sat, 11 Jan 2014 14:45:08 -0600 Subject: [PATCH 016/315] Treat deltas with empty ranges as NOOPs --- lib/ace/document.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/ace/document.js b/lib/ace/document.js index c4f8a9eb..e203d77c 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -569,6 +569,10 @@ var Document = function(textOrLines) { **/ this.applyDelta = function(delta, doNotValidate) { + // An empty range is a NOOP. + if (delta.range.isEmpty()) + return; + // Split large insert deltas. This is necessary because: // 1. We need to support splicing delta lines into the document via $lines.splice.apply(...) // 2. fn.apply() doesn't work for a large number of params. The mallest threshold is on safari 0xFFFF. From 6b280bf6bb48aa81fc73582f85877f5626f1eae0 Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Sat, 11 Jan 2014 15:23:20 -0600 Subject: [PATCH 017/315] Code review fixes (mostly formatting) - Fix unconventional '{' formatting - Reformat `UndoManager` changes - Revert change from `insertInLine` to `insert` in text.js --- lib/ace/anchor.js | 7 +++---- lib/ace/apply_delta.js | 6 ++---- lib/ace/document.js | 12 ++++++------ lib/ace/mode/text.js | 4 ++-- lib/ace/placeholder.js | 4 ++-- lib/ace/undomanager.js | 32 ++++++++++++++------------------ lib/ace/worker/mirror.js | 3 +-- 7 files changed, 30 insertions(+), 38 deletions(-) diff --git a/lib/ace/anchor.js b/lib/ace/anchor.js index fee42bb5..5622bf5c 100644 --- a/lib/ace/anchor.js +++ b/lib/ace/anchor.js @@ -101,14 +101,13 @@ var Anchor = exports.Anchor = function(doc, row, column) { **/ this.onChange = function(e) { - function _pointsInOrder(point1, point2, equalPointsInOrder) - { + function _pointsInOrder(point1, point2, equalPointsInOrder) { var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column; return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter); } - function getTransformedPoint(delta, point, moveIfEqual) - { + function getTransformedPoint(delta, point, moveIfEqual) { + // Get delta info. var deltaIsInsert = (delta.action == 'insert') var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.range.end.row - delta.range.start.row); diff --git a/lib/ace/apply_delta.js b/lib/ace/apply_delta.js index 1317ce98..86bc89c6 100644 --- a/lib/ace/apply_delta.js +++ b/lib/ace/apply_delta.js @@ -49,8 +49,7 @@ function throwDeltaError(delta, errorText){ throw 'Invalid Delta: ' + errorText; } -function positionInDocument(docLines, position) -{ +function positionInDocument(docLines, position) { return position.row >= 0 && position.row < docLines.length && position.column >= 0 && position.column <= docLines[position.row].length; } @@ -93,8 +92,7 @@ exports.applyDelta = function(docLines, delta, doNotValidate) { validateDelta(docLines, delta); // Apply delta. - if (delta.range.start.row == delta.range.end.row) - { + if (delta.range.start.row == delta.range.end.row) { // Apply single-line delta. // Note: The multi-line code below correctly handle single-line // deltas too, but we need to short-circuit for speed. diff --git a/lib/ace/document.js b/lib/ace/document.js index e203d77c..97d69968 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -108,14 +108,15 @@ var Document = function(textOrLines) { **/ // check for IE split bug - if ("aaa".split(/a/).length === 0) + if ("aaa".split(/a/).length === 0) { this.$split = function(text) { return text.replace(/\r\n|\r/g, "\n").split("\n"); }; - else + } else { this.$split = function(text) { return text.split(/\r\n|\r|\n/); }; + } this.$detectNewLine = function(text) { @@ -582,8 +583,8 @@ var Document = function(textOrLines) { // as shown in https://gist.github.com/aldendaniels/8367109#file-document-snippet-js // If we do this, update validateDelta() to limit the number of lines in a delete delta. var bIsInsert = delta.action == 'insert'; - while (bIsInsert && delta.lines.length > 65001) - { + while (bIsInsert && delta.lines.length > 65001) { + // Get split deltas. var lines = delta.lines.splice(0, 65000); lines.push(''); @@ -608,8 +609,7 @@ var Document = function(textOrLines) { * Reverts `delta` from the document. * @param {Object} delta A delta object (can include 'insert' and 'remove' actions) **/ - this.revertDelta = function(delta) - { + this.revertDelta = function(delta) { this.applyDelta({ action: (delta.action == 'insert' ? 'remove' : 'insert'), range: delta.range.clone(), diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index 343fc271..d04fed78 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -138,9 +138,9 @@ var Mode = function() { var comment = function(line, i) { if (!ignoreBlankLines || /\S/.test(line)) { if (shouldInsertSpace(line, minIndent, minIndent)) - doc.insert({row: i, column: minIndent}, commentWithSpace); + doc.insertInLine({row: i, column: minIndent}, commentWithSpace); else - doc.insert({row: i, column: minIndent}, lineCommentStart); + doc.insertInLine({row: i, column: minIndent}, lineCommentStart); } }; var testRemove = function(line, i) { diff --git a/lib/ace/placeholder.js b/lib/ace/placeholder.js index df0bfa9e..1d345a24 100644 --- a/lib/ace/placeholder.js +++ b/lib/ace/placeholder.js @@ -161,7 +161,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) var distanceFromStart = range.start.column - this.pos.column; this.length += lengthDiff; if(!this.session.$fromUndo) { - if(delta.action === "insert") { + if(delta.action === 'insert') { for (var i = this.others.length - 1; i >= 0; i--) { var otherPos = this.others[i]; var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; @@ -179,7 +179,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) } } // Special case: insert in beginning - if(range.start.column === this.pos.column && delta.action === "insert") { + if(range.start.column === this.pos.column && delta.action === 'insert') { setTimeout(function() { this.pos.setPosition(this.pos.row, this.pos.column - lengthDiff); for (var i = 0; i < this.others.length; i++) { diff --git a/lib/ace/undomanager.js b/lib/ace/undomanager.js index 4d978d46..209cf3db 100644 --- a/lib/ace/undomanager.js +++ b/lib/ace/undomanager.js @@ -165,10 +165,15 @@ var UndoManager = function() { }; // Serializes deltaSets to reduce memory usage. - this.$serializeDeltas = function(deltaSets) - { - return this.$cloneDeltaSetsObj(deltaSets, $serializeDelta); - } + this.$serializeDeltas = function(deltaSets) { + return cloneDeltaSetsObj(deltaSets, $serializeDelta); + }; + + // Deserializes deltaSets to allow application to the document. + this.$deserializeDeltas = function(deltaSets) { + return cloneDeltaSetsObj(deltaSets, $deserializeDelta); + }; + function $serializeDelta(delta){ return { action: delta.action, @@ -177,13 +182,8 @@ var UndoManager = function() { text: (delta.lines.length == 1 ? delta.lines[0] : null ), }; } - - // Deserializes deltaSets to allow application to the document. - this.$deserializeDeltas = function(deltaSets) - { - return this.$cloneDeltaSetsObj(deltaSets, $deserializeDelta); - } - function $deserializeDelta(delta){ + + function $deserializeDelta(delta) { return { action: delta.action, range: delta.range, @@ -191,17 +191,13 @@ var UndoManager = function() { }; } - // Helper for delta serialization and deserialization. - this.$cloneDeltaSetsObj = function(deltaSets_old, fnGetModifiedDelta) - { + function cloneDeltaSetsObj(deltaSets_old, fnGetModifiedDelta) { var deltaSets_new = new Array(deltaSets_old.length); - for (var i in deltaSets_old) - { + for (var i in deltaSets_old) { var deltaSet_old = deltaSets_old[i]; var deltaSet_new = { group: deltaSet_old.group, deltas: new Array(deltaSet_old.length)}; - for (var i_ in deltaSet_old.deltas) - { + for (var i_ in deltaSet_old.deltas) { var delta_old = deltaSet_old.deltas[i_]; deltaSet_new.deltas[i_] = fnGetModifiedDelta(delta_old); } diff --git a/lib/ace/worker/mirror.js b/lib/ace/worker/mirror.js index d55e84f4..2f33fea6 100644 --- a/lib/ace/worker/mirror.js +++ b/lib/ace/worker/mirror.js @@ -17,8 +17,7 @@ var Mirror = exports.Mirror = function(sender) { // Convert delta.range back into a Range instance since // window.onMessage loses non-primitive data. See http://jsfiddle.net/nqJfw/1/. var deltas = e.data; - for (var i in deltas) - { + for (var i in deltas) { var delta = deltas[i]; delta.range = Range.fromPoints(delta.range.start, delta.range.end); } From 7f1bc7af2fcc431241c2e8812588164394444df9 Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Sat, 11 Jan 2014 15:48:38 -0600 Subject: [PATCH 018/315] Break out Anchor.onChange helper functions This should be faster since we don't have to re-initialize the helper functions each time Anchor.onChange is fired. --- lib/ace/anchor.js | 78 +++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/lib/ace/anchor.js b/lib/ace/anchor.js index 5622bf5c..c9c27dfe 100644 --- a/lib/ace/anchor.js +++ b/lib/ace/anchor.js @@ -100,50 +100,50 @@ var Anchor = exports.Anchor = function(doc, row, column) { * **/ this.onChange = function(e) { + var delta = e.data; + var point = this.$getTransformedPoint(delta, {row: this.row, column: this.column}); + this.setPosition(point.row, point.column, true); + }; + + function $pointsInOrder(point1, point2, equalPointsInOrder) { + var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column; + return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter); + } + + this.$getTransformedPoint = function (delta, point) { - function _pointsInOrder(point1, point2, equalPointsInOrder) { - var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column; - return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter); - } - - function getTransformedPoint(delta, point, moveIfEqual) { - - // Get delta info. - var deltaIsInsert = (delta.action == 'insert') - var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.range.end.row - delta.range.start.row); - var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.range.end.column - delta.range.start.column); - var deltaStart = delta.range.start; - var deltaEnd = (deltaIsInsert ? deltaStart : delta.range.end); // Collapse insert range. - - // DELTA AFTER POINT: No change needed. - if (_pointsInOrder(point, deltaStart, moveIfEqual)) { - return { - row: point.row, - column: point.column - }; - } - - // DELTA BEFORE POINT: Move point by delta shift. - if (_pointsInOrder(deltaEnd, point, !moveIfEqual)) { - return { - row: point.row + deltaRowShift, - column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0) - }; - } - - // DELTA ENVELOPS POINT (delete only): Move point to delta start. - if (delta.action != 'remove') - throw 'Delete action expected.'; - + // Get delta info. + var moveIfEqual = this.$insertRight; + var deltaIsInsert = (delta.action == 'insert') + var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.range.end.row - delta.range.start.row); + var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.range.end.column - delta.range.start.column); + var deltaStart = delta.range.start; + var deltaEnd = (deltaIsInsert ? deltaStart : delta.range.end); // Collapse insert range. + + // DELTA AFTER POINT: No change needed. + if ($pointsInOrder(point, deltaStart, moveIfEqual)) { return { - row: deltaStart.row, - column: deltaStart.column + row: point.row, + column: point.column }; } - var delta = e.data; - var point = getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight); - this.setPosition(point.row, point.column, true); + // DELTA BEFORE POINT: Move point by delta shift. + if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) { + return { + row: point.row + deltaRowShift, + column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0) + }; + } + + // DELTA ENVELOPS POINT (delete only): Move point to delta start. + if (delta.action != 'remove') + throw 'Delete action expected.'; + + return { + row: deltaStart.row, + column: deltaStart.column + }; }; /** From 4299db01bdb4b6a578e8ed678fe82c32457d7601 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 18 Jan 2014 17:24:11 +0400 Subject: [PATCH 019/315] remove delta.range --- lib/ace/anchor.js | 17 ++-- lib/ace/apply_delta.js | 65 ++++++++------- lib/ace/background_tokenizer.js | 7 +- lib/ace/commands/command_manager.js | 4 +- lib/ace/document.js | 107 ++++++++++++------------- lib/ace/edit_session.js | 33 ++++---- lib/ace/edit_session/folding.js | 5 +- lib/ace/editor.js | 7 +- lib/ace/ext/elastic_tabstops_lite.js | 2 +- lib/ace/keyboard/vim/maps/operators.js | 2 - lib/ace/layer/gutter.js | 5 +- lib/ace/lib/lang.js | 1 - lib/ace/line_widgets.js | 5 +- lib/ace/undomanager.js | 20 ++--- lib/ace/worker/mirror.js | 11 +-- 15 files changed, 136 insertions(+), 155 deletions(-) diff --git a/lib/ace/anchor.js b/lib/ace/anchor.js index 421f9e5f..4511a4ce 100644 --- a/lib/ace/anchor.js +++ b/lib/ace/anchor.js @@ -111,14 +111,13 @@ var Anchor = exports.Anchor = function(doc, row, column) { } this.$getTransformedPoint = function (delta, point) { - // Get delta info. var moveIfEqual = this.$insertRight; - var deltaIsInsert = (delta.action == 'insert') - var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.range.end.row - delta.range.start.row); - var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.range.end.column - delta.range.start.column); - var deltaStart = delta.range.start; - var deltaEnd = (deltaIsInsert ? deltaStart : delta.range.end); // Collapse insert range. + var deltaIsInsert = (delta.action == "insert") + var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row); + var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column); + var deltaStart = delta.start; + var deltaEnd = (deltaIsInsert ? deltaStart : delta.end); // Collapse insert range. // DELTA AFTER POINT: No change needed. if ($pointsInOrder(point, deltaStart, moveIfEqual)) { @@ -137,8 +136,8 @@ var Anchor = exports.Anchor = function(doc, row, column) { } // DELTA ENVELOPS POINT (delete only): Move point to delta start. - if (delta.action != 'remove') - throw 'Delete action expected.'; + if (delta.action != "remove") + throw "Delete action expected."; return { row: deltaStart.row, @@ -181,7 +180,7 @@ var Anchor = exports.Anchor = function(doc, row, column) { }; /** - * When called, the `'change'` event listener is removed. + * When called, the `"change"` event listener is removed. * **/ this.detach = function() { diff --git a/lib/ace/apply_delta.js b/lib/ace/apply_delta.js index 86bc89c6..3996920c 100644 --- a/lib/ace/apply_delta.js +++ b/lib/ace/apply_delta.js @@ -41,12 +41,12 @@ function splitLine (docLines, position) { function joinLineWithNext(docLines, row) { docLines[row] += docLines[row + 1]; - docLines.splice(row + 1, 1); + docLines.splice(row + 1, 1); } function throwDeltaError(delta, errorText){ - console.log('Invalid Delta:', delta); - throw 'Invalid Delta: ' + errorText; + console.log("Invalid Delta:", delta); + throw "Invalid Delta: " + errorText; } function positionInDocument(docLines, position) { @@ -57,32 +57,32 @@ function positionInDocument(docLines, position) { function validateDelta(docLines, delta) { // Validate action string. - if (delta.action != 'insert' && delta.action != 'remove') - throwDeltaError(delta, 'delta.action must be "insert" or "remove"'); + if (delta.action != "insert" && delta.action != "remove") + throwDeltaError(delta, "delta.action must be 'insert' or 'remove'"); // Validate lines type. if (!(delta.lines instanceof Array)) - throwDeltaError(delta, 'delta.lines must be an Array'); + throwDeltaError(delta, "delta.lines must be an Array"); // Validate range type. - if (!(delta.range instanceof Range)) - throwDeltaError(delta, 'delta.range must be an instance of the Range class'); + if (!delta.start || !delta.end) + throwDeltaError(delta, "delta.start/end must be an present"); // Validate that the start point is contained in the document. - var start = delta.range.start; - if (!positionInDocument(docLines, delta.range.start)) - throwDeltaError(delta, 'delta.range.start must be contained in document'); + var start = delta.start; + if (!positionInDocument(docLines, delta.start)) + throwDeltaError(delta, "delta.start must be contained in document"); // Validate that the end point is contained in the document (remove deltas only). - var end = delta.range.end; - if (delta.action == 'remove' && !positionInDocument(docLines, end)) - throwDeltaError(delta, 'delta.range.end must contained in document for "remove" actions'); + var end = delta.end; + if (delta.action == "remove" && !positionInDocument(docLines, end)) + throwDeltaError(delta, "delta.end must contained in document for 'remove' actions"); // Validate that the .range size matches the .lines size. var numRangeRows = end.row - start.row; var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0)); if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars) - throwDeltaError(delta, 'delta.range must match delta lines'); + throwDeltaError(delta, "delta.range must match delta lines"); } exports.applyDelta = function(docLines, delta, doNotValidate) { @@ -92,21 +92,21 @@ exports.applyDelta = function(docLines, delta, doNotValidate) { validateDelta(docLines, delta); // Apply delta. - if (delta.range.start.row == delta.range.end.row) { + if (delta.start.row == delta.end.row) { // Apply single-line delta. // Note: The multi-line code below correctly handle single-line // deltas too, but we need to short-circuit for speed. - var row = delta.range.start.row; - var startColumn = delta.range.start.column; - var endColumn = delta.range.end.column; + var row = delta.start.row; + var startColumn = delta.start.column; + var endColumn = delta.end.column; var line = docLines[row]; switch (delta.action) { - case 'insert': + case "insert": docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); break; - case 'remove': + case "remove": docLines[row] = line.substring(0, startColumn) + line.substring(endColumn); break; } @@ -114,22 +114,21 @@ exports.applyDelta = function(docLines, delta, doNotValidate) { // Apply multi-line delta. switch (delta.action) { - - case 'insert': - splitLine(docLines, delta.range.start); - docLines.splice.apply(docLines, [delta.range.start.row + 1, 0].concat(delta.lines)); - joinLineWithNext(docLines, delta.range.start.row); - joinLineWithNext(docLines, delta.range.end.row); + case "insert": + splitLine(docLines, delta.start); + docLines.splice.apply(docLines, [delta.start.row + 1, 0].concat(delta.lines)); + joinLineWithNext(docLines, delta.start.row); + joinLineWithNext(docLines, delta.end.row); break; - case 'remove': - splitLine(docLines, delta.range.end); - splitLine(docLines, delta.range.start); + case "remove": + splitLine(docLines, delta.end); + splitLine(docLines, delta.start); docLines.splice( - delta.range.start.row + 1, // Where to start deleting - delta.range.end.row - delta.range.start.row + 1 // Num lines to delete. + delta.start.row + 1, // Where to start deleting + delta.end.row - delta.start.row + 1 // Num lines to delete. ); - joinLineWithNext(docLines, delta.range.start.row); + joinLineWithNext(docLines, delta.start.row); break; } } diff --git a/lib/ace/background_tokenizer.js b/lib/ace/background_tokenizer.js index 81ea4a0f..07862188 100644 --- a/lib/ace/background_tokenizer.js +++ b/lib/ace/background_tokenizer.js @@ -177,13 +177,12 @@ var BackgroundTokenizer = function(tokenizer, editor) { } this.$updateOnChange = function(delta) { - var range = delta.range; - var startRow = range.start.row; - var len = range.end.row - startRow; + var startRow = delta.start.row; + var len = delta.end.row - startRow; if (len === 0) { this.lines[startRow] = null; - } else if (delta.action == 'remove') { + } else if (delta.action == "remove") { this.lines.splice(startRow, len + 1, null); this.states.splice(startRow, len + 1, null); } else { diff --git a/lib/ace/commands/command_manager.js b/lib/ace/commands/command_manager.js index 72a9942d..537942ab 100644 --- a/lib/ace/commands/command_manager.js +++ b/lib/ace/commands/command_manager.js @@ -13,7 +13,7 @@ var EventEmitter = require("../lib/event_emitter").EventEmitter; /** * new CommandManager(platform, commands) - * @param {String} platform Identifier for the platform; must be either `'mac'` or `'win'` + * @param {String} platform Identifier for the platform; must be either `"mac"` or `"win"` * @param {Array} commands A list of commands * **/ @@ -33,7 +33,7 @@ oop.inherits(CommandManager, HashHandler); oop.implement(this, EventEmitter); this.exec = function(command, editor, args) { - if (typeof command === 'string') + if (typeof command === "string") command = this.commands[command]; if (!command) diff --git a/lib/ace/document.js b/lib/ace/document.js index 97d69968..43d1a73c 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -53,7 +53,7 @@ var Anchor = require("./anchor").Anchor; **/ var Document = function(textOrLines) { - this.$lines = ['']; + this.$lines = [""]; // There has to be one line at least in the document. If you pass an empty // string to the insert function, nothing will happen. Workaround. @@ -99,7 +99,7 @@ var Document = function(textOrLines) { }; /** - * Splits a string of text on any newline (`\n`) or carriage-return ('\r') characters. + * Splits a string of text on any newline (`\n`) or carriage-return (`\r`) characters. * * @method $split * @param {String} text The text to work with @@ -225,12 +225,9 @@ var Document = function(textOrLines) { this.getLinesForRange = function(range) { var lines; if (range.start.row == range.end.row) { - // Handle a single-line range. - lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)]; - + lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)]; } else { - // Handle a multi-line range. lines = this.getLines(range.start.row, range.end.row); lines[0] = (lines[0] || "").substring(range.start.column); @@ -254,7 +251,6 @@ var Document = function(textOrLines) { }; this.$getClippedRange = function(range) { - // Get Range object. if (!range instanceof Range) range = Range.fromPoints(range.start, range.end); @@ -267,16 +263,16 @@ var Document = function(textOrLines) { // Deprecated methods retained for backwards compatibility. this.insertLines = function(row, lines) { - console.warn('Use of document.insertLines is deprecated. Use the insertFullLines method instead.'); + console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."); return this.insertFullLines(row, lines); }; this.removeLines = function(firstRow, lastRow) { - console.warn('Use of document.removeLines is deprecated. Use the removeFullLines method instead.'); + console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."); return this.removeFullLines(firstRow, lastRow); }; this.insertNewLine = function(position) { - console.warn('Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead.'); - return this.insertMergedLines(position, ['', '']); + console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead."); + return this.insertMergedLines(position, ["", ""]); }; /** @@ -287,7 +283,6 @@ var Document = function(textOrLines) { * **/ this.insert = function(position, text) { - // Only detect new lines if the document has no line break yet. if (this.getLength() <= 1) this.$detectNewLine(text); @@ -296,7 +291,7 @@ var Document = function(textOrLines) { }; /** - * Inserts `text` into the `position` at the current row. This method also triggers the `'change'` event. + * Inserts `text` into the `position` at the current row. This method also triggers the `"change"` event. * * This differs from the `insert` method in two ways: * 1. This does NOT handle newline characters (single-line text only). @@ -310,7 +305,6 @@ var Document = function(textOrLines) { * ``` **/ this.insertInLine = function(position, text) { - // Calculate insertion range end point. this.$clipPosition(position); var endPoint = { @@ -318,10 +312,12 @@ var Document = function(textOrLines) { column : position.column + text.length }; + var range = Range.fromPoints(position, endPoint); // Apply delta (emits change). this.applyDelta({ action: "insert", - range: Range.fromPoints(position, endPoint), + start: range.start, + end: range.end, lines: [text] }, true /*doNotValidate*/); @@ -346,7 +342,7 @@ var Document = function(textOrLines) { **/ /** - * Inserts the elements in `lines` into the document as full lines (does not merge with existing line), starting at the row index given by `row`. This method also triggers the `'change'` event. + * Inserts the elements in `lines` into the document as full lines (does not merge with existing line), starting at the row index given by `row`. This method also triggers the `"change"` event. * @param {Number} row The index of the row to insert at * @param {Array} lines An array of strings * @returns {Object} Contains the final row and column, like this: @@ -368,11 +364,11 @@ var Document = function(textOrLines) { var column = 0; if (row < this.getLength()) { // Insert before the specified row. - lines = lines.concat(['']); + lines = lines.concat([""]); column = 0; } else { // Insert after the last row in the document. - lines = [''].concat(lines); + lines = [""].concat(lines); row--; column = this.$lines[row].length; } @@ -382,7 +378,7 @@ var Document = function(textOrLines) { }; /** - * Inserts the elements in `lines` into the document, starting at the position index given by `row`. This method also triggers the `'change'` event. + * Inserts the elements in `lines` into the document, starting at the position index given by `row`. This method also triggers the `"change"` event. * @param {Number} row The index of the row to insert at * @param {Array} lines An array of strings * @returns {Object} Contains the final row and column, like this: @@ -396,7 +392,6 @@ var Document = function(textOrLines) { * **/ this.insertMergedLines = function(position, lines) { - // Calculate insertion range end point. this.$clipPosition(position); var endPoint = { @@ -407,7 +402,8 @@ var Document = function(textOrLines) { // Apply delta (emits change). this.applyDelta({ action: "insert", - range: Range.fromPoints(position, endPoint), + start: position, + end: endPoint, lines: lines }); @@ -421,19 +417,19 @@ var Document = function(textOrLines) { * **/ this.remove = function(range) { - // Apply delta (emits change). range = this.$getClippedRange(range); this.applyDelta({ - action: 'remove', - range: range, + action: "remove", + start: range.start, + end: range.end, lines: this.getLinesForRange(range), }); - return range.start; + return range.start; }; /** - * Removes the specified columns from the `row`. This method also triggers the `'change'` event. + * Removes the specified columns from the `row`. This method also triggers the `"change"` event. * @param {Number} row The row to remove from * @param {Number} startColumn The column to start removing at * @param {Number} endColumn The column to stop removing at @@ -441,15 +437,15 @@ var Document = function(textOrLines) { * **/ this.removeInLine = function(row, startColumn, endColumn) { - // Calculate deleteion range. var range = new Range(row, startColumn, row, endColumn); range = this.$getClippedRange(range); // Apply delta (emits change). this.applyDelta({ - action: 'remove', - range: range, + action: "remove", + start: range.start, + end: range.end, lines: this.getLinesForRange(range), }, true /*doNotValidate*/); @@ -457,14 +453,13 @@ var Document = function(textOrLines) { }; /** - * Removes a range of full lines. This method also triggers the `'change'` event. + * Removes a range of full lines. This method also triggers the `"change"` event. * @param {Number} firstRow The first row to be removed * @param {Number} lastRow The last row to be removed * @returns {[String]} Returns all the removed lines. * **/ this.removeFullLines = function(firstRow, lastRow) { - // Clip to document. firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1); lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1); @@ -485,8 +480,9 @@ var Document = function(textOrLines) { // Apply delta (emits change). this.applyDelta({ - action: 'remove', - range: range, + action: "remove", + start: range.start, + end: range.end, lines: this.getLinesForRange(range) }); @@ -495,18 +491,19 @@ var Document = function(textOrLines) { }; /** - * Removes the new line between `row` and the row immediately following it. This method also triggers the `'change'` event. + * Removes the new line between `row` and the row immediately following it. This method also triggers the `"change"` event. * @param {Number} row The row to check * **/ this.removeNewLine = function(row) { - if (row < this.getLength() - 1 && row >= 0) { + var range = new Range(row, this.getLine(row).length, row + 1, 0); // Apply delta (emits change). this.applyDelta({ - action: 'remove', - range: new Range(row, this.getLine(row).length, row + 1, 0), - lines: ['', ''] + action: "remove", + start: range.start, + end: range.end, + lines: ["", ""] }); } }; @@ -546,7 +543,7 @@ var Document = function(textOrLines) { /** * Applies all changes in `deltas` to the document. - * @param {Array} deltas An array of delta objects (can include 'insert' and 'remove' actions) + * @param {Array} deltas An array of delta objects (can include "insert" and "remove" actions) **/ this.applyDeltas = function(deltas) { for (var i=0; i=0; i--) { @@ -566,12 +563,11 @@ var Document = function(textOrLines) { /** * Applies `delta` to the document. - * @param {Object} delta A delta object (can include 'insert' and 'remove' actions) + * @param {Object} delta A delta object (can include "insert" and "remove" actions) **/ this.applyDelta = function(delta, doNotValidate) { - // An empty range is a NOOP. - if (delta.range.isEmpty()) + if (!Range.comparePoints(delta.start, delta.end)) return; // Split large insert deltas. This is necessary because: @@ -582,37 +578,40 @@ var Document = function(textOrLines) { // delta handling is too slow. If we make delete delta handling faster we can split all large deltas // as shown in https://gist.github.com/aldendaniels/8367109#file-document-snippet-js // If we do this, update validateDelta() to limit the number of lines in a delete delta. - var bIsInsert = delta.action == 'insert'; + var bIsInsert = delta.action == "insert"; while (bIsInsert && delta.lines.length > 65001) { - // Get split deltas. var lines = delta.lines.splice(0, 65000); - lines.push(''); + lines.push(""); + var range = new Range(delta.start.row, delta.start.column, + delta.start.row + 65000, 0) this.applyDelta({ action: delta.action, lines: lines, - range: new Range(delta.range.start.row, delta.range.start.column, - delta.range.start.row + 65000, 0) + start: range.start, + end: range.end, }); // Update remaining delta. - delta.range.start.row += 65000; - delta.range.start.column = 0; + delta.start.row += 65000; + delta.start.column = 0; } // Apply. applyDelta(this.$lines, delta, doNotValidate); - this._emit("change", { data: delta }); + this._emit("change", { data: delta }); }; /** * Reverts `delta` from the document. - * @param {Object} delta A delta object (can include 'insert' and 'remove' actions) + * @param {Object} delta A delta object (can include "insert" and "remove" actions) **/ this.revertDelta = function(delta) { + var range = Range.fromPoints(delta.start, delta.end); this.applyDelta({ - action: (delta.action == 'insert' ? 'remove' : 'insert'), - range: delta.range.clone(), + action: (delta.action == "insert" ? "remove" : "insert"), + start: range.start, + end: range.end, lines: delta.lines.slice() }); }; diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 7cfa344c..4baa525f 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -253,7 +253,7 @@ var EditSession = function(text, mode) { var delta = e.data; this.$modified = true; - this.$resetRowCache(delta.range.start.row); + this.$resetRowCache(delta.start.row); var removedFolds = this.$updateInternalDataOnChange(e); if (!this.$fromUndo && this.$undoManager && !delta.ignore) { @@ -1247,30 +1247,29 @@ var EditSession = function(text, mode) { var range, point; var lastDeltaIsInsert = false; if (isInsert(delta)) { - range = Range.fromPoints(delta.range.start, delta.range.end); + range = Range.fromPoints(delta.start, delta.end); lastDeltaIsInsert = true; } else { - range = Range.fromPoints(delta.range.start, delta.range.start); + range = Range.fromPoints(delta.start, delta.start); lastDeltaIsInsert = false; } for (var i = 1; i < deltas.length; i++) { delta = deltas[i]; if (isInsert(delta)) { - point = delta.range.start; + point = delta.start; if (range.compare(point.row, point.column) == -1) { - range.setStart(delta.range.start); + range.setStart(point); } - point = delta.range.end; + point = delta.end; if (range.compare(point.row, point.column) == 1) { - range.setEnd(delta.range.end); + range.setEnd(point); } lastDeltaIsInsert = true; } else { - point = delta.range.start; + point = delta.start; if (range.compare(point.row, point.column) == -1) { - range = - Range.fromPoints(delta.range.start, delta.range.start); + range = Range.fromPoints(delta.start, delta.start); } lastDeltaIsInsert = false; } @@ -1676,8 +1675,8 @@ var EditSession = function(text, mode) { this.$updateInternalDataOnChange = function(e) { var useWrapMode = this.$useWrapMode; var action = e.data.action; - var start = e.data.range.start; - var end = e.data.range.end; + var start = e.data.start; + var end = e.data.end; var firstRow = start.row; var lastRow = end.row; var len = lastRow - firstRow; @@ -1685,11 +1684,11 @@ var EditSession = function(text, mode) { this.$updating = true; if (len != 0) { - if (action == 'remove') { + if (action == "remove") { this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len); var foldLines = this.$foldData; - removedFolds = this.getFoldsInRange(e.data.range); + removedFolds = this.getFoldsInRange(e.data); this.removeFolds(removedFolds); var foldLine = this.getFoldLine(end.row); @@ -1759,10 +1758,10 @@ var EditSession = function(text, mode) { } else { // Realign folds. E.g. if you add some new chars before a fold, the // fold should "move" to the right. - len = Math.abs(e.data.range.start.column - e.data.range.end.column); - if (action == 'remove') { + len = Math.abs(e.data.start.column - e.data.end.column); + if (action == "remove") { // Get all the folds in the change range and remove them. - removedFolds = this.getFoldsInRange(e.data.range); + removedFolds = this.getFoldsInRange(e.data); this.removeFolds(removedFolds); len = -len; diff --git a/lib/ace/edit_session/folding.js b/lib/ace/edit_session/folding.js index 25adc909..857382d8 100644 --- a/lib/ace/edit_session/folding.js +++ b/lib/ace/edit_session/folding.js @@ -830,9 +830,8 @@ function Folding() { this.updateFoldWidgets = function(e) { var delta = e.data; - var range = delta.range; - var firstRow = range.start.row; - var len = range.end.row - firstRow; + var firstRow = delta.start.row; + var len = delta.end.row - firstRow; if (len === 0) { this.foldWidgets[firstRow] = null; diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 6b046a89..16d79785 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -607,11 +607,10 @@ var Editor = function(renderer, session) { * **/ this.onDocumentChange = function(e) { - // Rerender and emit "change" event. - var range = e.data.range; - var lastRow = (range.start.row == range.end.row ? range.end.row : Infinity); - this.renderer.updateLines(range.start.row, lastRow); + var delta = e.data; + var lastRow = (delta.start.row == delta.end.row ? delta.end.row : Infinity); + this.renderer.updateLines(delta.start.row, lastRow); this._signal("change", e); // Update cursor because tab characters can influence the cursor position. diff --git a/lib/ace/ext/elastic_tabstops_lite.js b/lib/ace/ext/elastic_tabstops_lite.js index 9901c5df..ce5e55f9 100644 --- a/lib/ace/ext/elastic_tabstops_lite.js +++ b/lib/ace/ext/elastic_tabstops_lite.js @@ -45,7 +45,7 @@ var ElasticTabstopsLite = function(editor) { recordChanges = true; }; this.onChange = function(e) { - var range = e.data.range + var range = e.data; if (recordChanges) { if (changedRows.indexOf(range.start.row) == -1) changedRows.push(range.start.row); diff --git a/lib/ace/keyboard/vim/maps/operators.js b/lib/ace/keyboard/vim/maps/operators.js index 067562a0..73c6922e 100644 --- a/lib/ace/keyboard/vim/maps/operators.js +++ b/lib/ace/keyboard/vim/maps/operators.js @@ -94,11 +94,9 @@ module.exports = { editor.removeLines(); util.insertMode(editor); } - break; default: if (range) { - // range.end.column ++; editor.session.remove(range); util.insertMode(editor); diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index 45c34565..59aa35fd 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -103,9 +103,8 @@ var Gutter = function(parentEl) { if (!this.$annotations.length) return; var delta = e.data; - var range = delta.range; - var firstRow = range.start.row; - var len = range.end.row - firstRow; + var firstRow = delta.start.row; + var len = delta.end.row - firstRow; if (len === 0) { // do nothing } else if (delta.action == 'remove') { diff --git a/lib/ace/lib/lang.js b/lib/ace/lib/lang.js index d6a98149..863bbb55 100644 --- a/lib/ace/lib/lang.js +++ b/lib/ace/lib/lang.js @@ -150,7 +150,6 @@ exports.getMatchOffsets = function(string, regExp) { /* deprecated */ exports.deferredCall = function(fcn) { - var timer = null; var callback = function() { timer = null; diff --git a/lib/ace/line_widgets.js b/lib/ace/line_widgets.js index 651f038d..185f6de4 100644 --- a/lib/ace/line_widgets.js +++ b/lib/ace/line_widgets.js @@ -119,9 +119,8 @@ function LineWidgets(session) { if (!lineWidgets) return; var delta = e.data; - var range = delta.range; - var startRow = range.start.row; - var len = range.end.row - startRow; + var startRow = delta.start.row; + var len = delta.end.row - startRow; if (len === 0) { // return diff --git a/lib/ace/undomanager.js b/lib/ace/undomanager.js index bd95bae9..71b4ba65 100644 --- a/lib/ace/undomanager.js +++ b/lib/ace/undomanager.js @@ -178,29 +178,31 @@ var UndoManager = function() { function $serializeDelta(delta){ return { action: delta.action, - range: delta.range, - lines: (delta.lines.length == 1 ? null : delta.lines), - text: (delta.lines.length == 1 ? delta.lines[0] : null ), + start: delta.start, + end: delta.end, + lines: delta.lines.length == 1 ? null : delta.lines, + text: delta.lines.length == 1 ? delta.lines[0] : null, }; } function $deserializeDelta(delta) { return { action: delta.action, - range: delta.range, - lines: (delta.text === null ? delta.lines : [delta.text]) + start: delta.start, + end: delta.end, + lines: delta.lines || [delta.text] }; } function cloneDeltaSetsObj(deltaSets_old, fnGetModifiedDelta) { var deltaSets_new = new Array(deltaSets_old.length); - for (var i in deltaSets_old) { + for (var i = 0; i < deltaSets_old.length; i++) { var deltaSet_old = deltaSets_old[i]; var deltaSet_new = { group: deltaSet_old.group, deltas: new Array(deltaSet_old.length)}; - for (var i_ in deltaSet_old.deltas) { - var delta_old = deltaSet_old.deltas[i_]; - deltaSet_new.deltas[i_] = fnGetModifiedDelta(delta_old); + for (var j = 0; j < deltaSet_old.deltas.length; j++) { + var delta_old = deltaSet_old.deltas[j]; + deltaSet_new.deltas[j] = fnGetModifiedDelta(delta_old); } deltaSets_new[i] = deltaSet_new; diff --git a/lib/ace/worker/mirror.js b/lib/ace/worker/mirror.js index 2f33fea6..8254f205 100644 --- a/lib/ace/worker/mirror.js +++ b/lib/ace/worker/mirror.js @@ -13,16 +13,7 @@ var Mirror = exports.Mirror = function(sender) { var _self = this; sender.on("change", function(e) { - - // Convert delta.range back into a Range instance since - // window.onMessage loses non-primitive data. See http://jsfiddle.net/nqJfw/1/. - var deltas = e.data; - for (var i in deltas) { - var delta = deltas[i]; - delta.range = Range.fromPoints(delta.range.start, delta.range.end); - } - - doc.applyDeltas(deltas); + doc.applyDeltas(e.data); if (_self.$timeout) return deferredUpdate.schedule(_self.$timeout); _self.onUpdate(); From c8d1df203ed8772805369c331f7c160f04af4bfc Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 19 Jan 2014 04:26:02 +0400 Subject: [PATCH 020/315] restore single line delta optimization in anchor.js --- lib/ace/anchor.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/ace/anchor.js b/lib/ace/anchor.js index 4511a4ce..3431b3c4 100644 --- a/lib/ace/anchor.js +++ b/lib/ace/anchor.js @@ -101,6 +101,12 @@ var Anchor = exports.Anchor = function(doc, row, column) { **/ this.onChange = function(e) { var delta = e.data; + if (delta.start.row == delta.end.row && delta.start.row != this.row) + return; + + if (delta.start.row > this.row) + return; + var point = this.$getTransformedPoint(delta, {row: this.row, column: this.column}); this.setPosition(point.row, point.column, true); }; From 46f3d77068efbf8d1bfc3e0b3fb840c0bb90630d Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 19 Jan 2014 04:27:07 +0400 Subject: [PATCH 021/315] simplify apply_delta.js --- lib/ace/apply_delta.js | 45 +++++++++++++----------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/lib/ace/apply_delta.js b/lib/ace/apply_delta.js index 3996920c..ed019ccb 100644 --- a/lib/ace/apply_delta.js +++ b/lib/ace/apply_delta.js @@ -31,19 +31,6 @@ define(function(require, exports, module) { "use strict"; -var Range = require("./range").Range; - -function splitLine (docLines, position) { - var text = docLines[position.row]; - docLines[position.row] = text.slice(0, position.column); - docLines.splice(position.row + 1, 0, text.slice(position.column)); -} - -function joinLineWithNext(docLines, row) { - docLines[row] += docLines[row + 1]; - docLines.splice(row + 1, 1); -} - function throwDeltaError(delta, errorText){ console.log("Invalid Delta:", delta); throw "Invalid Delta: " + errorText; @@ -91,44 +78,40 @@ exports.applyDelta = function(docLines, delta, doNotValidate) { if (!doNotValidate) validateDelta(docLines, delta); + var row = delta.start.row; + var startColumn = delta.start.column; + var line = docLines[row]; // Apply delta. - if (delta.start.row == delta.end.row) { + if (row == delta.end.row) { // Apply single-line delta. // Note: The multi-line code below correctly handle single-line // deltas too, but we need to short-circuit for speed. - var row = delta.start.row; - var startColumn = delta.start.column; - var endColumn = delta.end.column; - var line = docLines[row]; + var endColumn = delta.end.column; switch (delta.action) { - case "insert": docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); break; - case "remove": docLines[row] = line.substring(0, startColumn) + line.substring(endColumn); break; } } else { - // Apply multi-line delta. switch (delta.action) { case "insert": - splitLine(docLines, delta.start); - docLines.splice.apply(docLines, [delta.start.row + 1, 0].concat(delta.lines)); - joinLineWithNext(docLines, delta.start.row); - joinLineWithNext(docLines, delta.end.row); + var line = docLines[row]; + var args = [row, 1].concat(delta.lines); + docLines.splice.apply(docLines, args); + docLines[row] = line.substring(0, startColumn) + docLines[row]; + docLines[row + delta.lines.length - 1] += line.substring(startColumn); break; - case "remove": - splitLine(docLines, delta.end); - splitLine(docLines, delta.start); + var endRow docLines.splice( - delta.start.row + 1, // Where to start deleting - delta.end.row - delta.start.row + 1 // Num lines to delete. + row, // Where to start deleting + delta.end.row - delta.start.row + 1, // Num lines to delete. + line.substring(0, startColumn) + docLines[delta.end.row].substring(delta.end.column) ); - joinLineWithNext(docLines, delta.start.row); break; } } From 6b60bcbbd672aef1211ddcb58ca21225b3dba369 Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 14 Feb 2014 22:35:22 +0400 Subject: [PATCH 022/315] continue refactoring --- lib/ace/apply_delta.js | 45 ++++------ lib/ace/document.js | 155 ++++++++++++++++---------------- lib/ace/edit_session.js | 24 ++--- lib/ace/range_list.js | 12 +-- lib/ace/undomanager.js | 7 +- lib/ace/worker/mirror.js | 14 ++- lib/ace/worker/worker_client.js | 12 ++- 7 files changed, 135 insertions(+), 134 deletions(-) diff --git a/lib/ace/apply_delta.js b/lib/ace/apply_delta.js index ed019ccb..98a1a857 100644 --- a/lib/ace/apply_delta.js +++ b/lib/ace/apply_delta.js @@ -42,7 +42,6 @@ function positionInDocument(docLines, position) { } function validateDelta(docLines, delta) { - // Validate action string. if (delta.action != "insert" && delta.action != "remove") throwDeltaError(delta, "delta.action must be 'insert' or 'remove'"); @@ -73,47 +72,37 @@ function validateDelta(docLines, delta) { } exports.applyDelta = function(docLines, delta, doNotValidate) { - - // Validate delta. if (!doNotValidate) validateDelta(docLines, delta); var row = delta.start.row; var startColumn = delta.start.column; var line = docLines[row]; - // Apply delta. - if (row == delta.end.row) { - // Apply single-line delta. - // Note: The multi-line code below correctly handle single-line - // deltas too, but we need to short-circuit for speed. - var endColumn = delta.end.column; - switch (delta.action) { - case "insert": + switch (delta.action) { + case "insert": + var lines = delta.lines; + if (lines.length === 1) { docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); - break; - case "remove": - docLines[row] = line.substring(0, startColumn) + line.substring(endColumn); - break; - } - } else { - // Apply multi-line delta. - switch (delta.action) { - case "insert": + } else { var line = docLines[row]; var args = [row, 1].concat(delta.lines); docLines.splice.apply(docLines, args); docLines[row] = line.substring(0, startColumn) + docLines[row]; docLines[row + delta.lines.length - 1] += line.substring(startColumn); - break; - case "remove": - var endRow + } + break; + case "remove": + var endColumn = delta.end.column; + var endRow = delta.end.row; + if (row === endRow) { + docLines[row] = line.substring(0, startColumn) + line.substring(endColumn); + } else { docLines.splice( - row, // Where to start deleting - delta.end.row - delta.start.row + 1, // Num lines to delete. - line.substring(0, startColumn) + docLines[delta.end.row].substring(delta.end.column) + row, endRow - row + 1, + line.substring(0, startColumn) + docLines[endRow].substring(endColumn) ); - break; - } + } + break; } } }); diff --git a/lib/ace/document.js b/lib/ace/document.js index 43d1a73c..1abb95a2 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -39,13 +39,12 @@ var Anchor = require("./anchor").Anchor; /** * Contains the text of the document. Document can be attached to several [[EditSession `EditSession`]]s. - * * At its core, `Document`s are just an array of strings, with each row in the document matching up to the array index. * * @class Document **/ - /** +/** * * Creates a new `Document`. If `text` is included, the `Document` contains those strings; otherwise, it's empty. * @param {String | Array} text The starting text @@ -76,9 +75,9 @@ var Document = function(textOrLines) { * @param {String} text The text to use **/ this.setValue = function(text) { - var len = this.getLength(); - this.remove(new Range(0, 0, len, this.getLine(len-1).length)); - this.insert({row: 0, column:0}, text); + var len = this.getLength() - 1; + this.remove(new Range(0, 0, len, this.getLine(len).length)); + this.insert({row: 0, column: 0}, text); }; /** @@ -224,7 +223,7 @@ var Document = function(textOrLines) { **/ this.getLinesForRange = function(range) { var lines; - if (range.start.row == range.end.row) { + if (range.start.row === range.end.row) { // Handle a single-line range. lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)]; } else { @@ -238,29 +237,6 @@ var Document = function(textOrLines) { return lines; }; - this.$clipPosition = function(position) { - var length = this.getLength(); - if (position.row >= length) { - position.row = Math.max(0, length - 1); - position.column = this.getLine(length - 1).length; - } else { - position.row = Math.max(0, position.row); - position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length); - } - return position; - }; - - this.$getClippedRange = function(range) { - // Get Range object. - if (!range instanceof Range) - range = Range.fromPoints(range.start, range.end); - - // Return clipped range. - this.$clipPosition(range.start); - this.$clipPosition(range.end); - return range; - }; - // Deprecated methods retained for backwards compatibility. this.insertLines = function(row, lines) { console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."); @@ -305,25 +281,54 @@ var Document = function(textOrLines) { * ``` **/ this.insertInLine = function(position, text) { - // Calculate insertion range end point. - this.$clipPosition(position); - var endPoint = { - row : position.row, - column : position.column + text.length - }; + var start = this.clippedPos(position.row, position.column); + var end = this.pos(position.row, position.column + text.length); - var range = Range.fromPoints(position, endPoint); - // Apply delta (emits change). this.applyDelta({ action: "insert", - start: range.start, - end: range.end, + start: start, + end: end, lines: [text] - }, true /*doNotValidate*/); + }, true); - return endPoint; + return this.clonePos(end); }; + this.clippedPos = function(row, column) { + var length = this.getLength(); + if (row === undefined) { + row = length; + } else if (row < 0) { + row = 0; + } else if (row >= length) { + row = length - 1; + column = undefined + } + var line = this.getLine(row); + column = Math.min(Math.max(column, 0), line.length); + return {row: row, column: column}; + }; + + this.clonePos = function(pos) { + return {row: pos.row, column: pos.column}; + }; + + this.pos = function(row, column) { + return {row: row, column: column}; + }; + + this.$clipPosition = function(position) { + var length = this.getLength(); + if (position.row >= length) { + position.row = Math.max(0, length - 1); + position.column = this.getLine(length - 1).length; + } else { + position.row = Math.max(0, position.row); + position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length); + } + return position; + }; + /** * Fires whenever the document changes. * @@ -392,14 +397,12 @@ var Document = function(textOrLines) { * **/ this.insertMergedLines = function(position, lines) { - // Calculate insertion range end point. this.$clipPosition(position); var endPoint = { row : position.row + lines.length - 1, column : (lines.length == 1 ? position.column : 0) + lines[lines.length - 1].length }; - // Apply delta (emits change). this.applyDelta({ action: "insert", start: position, @@ -417,15 +420,14 @@ var Document = function(textOrLines) { * **/ this.remove = function(range) { - // Apply delta (emits change). - range = this.$getClippedRange(range); + var start = this.clippedPos(range.start.row, range.start.column); this.applyDelta({ action: "remove", - start: range.start, - end: range.end, + start: start, + end: this.clippedPos(range.end.row, range.end.column), lines: this.getLinesForRange(range), }); - return range.start; + return this.clonePos(start); }; /** @@ -437,19 +439,16 @@ var Document = function(textOrLines) { * **/ this.removeInLine = function(row, startColumn, endColumn) { - // Calculate deleteion range. - var range = new Range(row, startColumn, row, endColumn); - range = this.$getClippedRange(range); + var start = this.clippedPos(row, startColumn); - // Apply delta (emits change). this.applyDelta({ action: "remove", - start: range.start, - end: range.end, + start: start, + end: this.clippedPos(row, endColumn), lines: this.getLinesForRange(range), - }, true /*doNotValidate*/); + }, true); - return range.start; + return this.clonePos(start); }; /** @@ -478,7 +477,6 @@ var Document = function(textOrLines) { // Store delelted lines with bounding newlines ommitted (maintains previous behavior). var deletedLines = this.$lines.slice(firstRow, lastRow + 1); - // Apply delta (emits change). this.applyDelta({ action: "remove", start: range.start, @@ -496,13 +494,11 @@ var Document = function(textOrLines) { * **/ this.removeNewLine = function(row) { - if (row < this.getLength() - 1 && row >= 0) { - var range = new Range(row, this.getLine(row).length, row + 1, 0); - // Apply delta (emits change). + if (row < this.getLength() - 1 && row >= 0) { this.applyDelta({ action: "remove", - start: range.start, - end: range.end, + start: this.pos(row, this.getLine(row).length), + end: this.pos(row + 1, 0), lines: ["", ""] }); } @@ -566,10 +562,21 @@ var Document = function(textOrLines) { * @param {Object} delta A delta object (can include "insert" and "remove" actions) **/ this.applyDelta = function(delta, doNotValidate) { + var isInsert = delta.action == "insert"; // An empty range is a NOOP. - if (!Range.comparePoints(delta.start, delta.end)) + if (isInsert ? !delta.lines.length + : !Range.comparePoints(delta.start, delta.end)) return; + if (isInsert && delta.lines.length > 0xFFFF) + this.$splitAndapplyLargeDelta(delta); + + // Apply. + applyDelta(this.$lines, delta, doNotValidate); + this._signal("change", {data: delta}); + }; + + this.$splitAndapplyLargeDelta = function(delta) { // Split large insert deltas. This is necessary because: // 1. We need to support splicing delta lines into the document via $lines.splice.apply(...) // 2. fn.apply() doesn't work for a large number of params. The mallest threshold is on safari 0xFFFF. @@ -578,28 +585,18 @@ var Document = function(textOrLines) { // delta handling is too slow. If we make delete delta handling faster we can split all large deltas // as shown in https://gist.github.com/aldendaniels/8367109#file-document-snippet-js // If we do this, update validateDelta() to limit the number of lines in a delete delta. - var bIsInsert = delta.action == "insert"; - while (bIsInsert && delta.lines.length > 65001) { + while (delta.lines.length > 0xFFFF) { // Get split deltas. - var lines = delta.lines.splice(0, 65000); + var lines = delta.lines.splice(0, 0xFFFF); lines.push(""); - var range = new Range(delta.start.row, delta.start.column, - delta.start.row + 65000, 0) + var start = delta.start; this.applyDelta({ action: delta.action, lines: lines, - start: range.start, - end: range.end, - }); - - // Update remaining delta. - delta.start.row += 65000; - delta.start.column = 0; + start: this.pos(start.row, start.column), + end: this.pos(start.row += 0xFFFF, start.column = 0) // Updates remaining delta. + }, true); } - - // Apply. - applyDelta(this.$lines, delta, doNotValidate); - this._emit("change", { data: delta }); }; /** diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 4baa525f..c9759fb1 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1394,25 +1394,25 @@ var EditSession = function(text, mode) { **/ this.outdentRows = function (range) { var rowRange = range.collapseRows(); + var deleteRange = new Range(0, 0, 0, 0); var size = this.getTabSize(); - + for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) { var line = this.getLine(i); - var row = i; - var startCol = 0; - var endCol = 0; - + + deleteRange.start.row = i; + deleteRange.end.row = i; for (var j = 0; j < size; ++j) if (line.charAt(j) != ' ') break; if (j < size && line.charAt(j) == '\t') { - startCol = j; - endCol = j + 1; + deleteRange.start.column = j; + deleteRange.end.column = j + 1; } else { - startCol = 0; - endCol = j; + deleteRange.start.column = 0; + deleteRange.end.column = j; } - this.doc.removeInLine(row, startCol, endCol); + this.remove(deleteRange); } }; @@ -1684,7 +1684,7 @@ var EditSession = function(text, mode) { this.$updating = true; if (len != 0) { - if (action == "remove") { + if (action === "remove") { this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len); var foldLines = this.$foldData; @@ -1759,7 +1759,7 @@ var EditSession = function(text, mode) { // Realign folds. E.g. if you add some new chars before a fold, the // fold should "move" to the right. len = Math.abs(e.data.start.column - e.data.end.column); - if (action == "remove") { + if (action === "remove") { // Get all the folds in the change range and remove them. removedFolds = this.getFoldsInRange(e.data); this.removeFolds(removedFolds); diff --git a/lib/ace/range_list.js b/lib/ace/range_list.js index 0cbcc394..a112139a 100644 --- a/lib/ace/range_list.js +++ b/lib/ace/range_list.js @@ -181,13 +181,13 @@ var RangeList = function() { }; this.$onChange = function(e) { - var changeRange = e.data.range; - if (e.data.action[0] == "i"){ - var start = changeRange.start; - var end = changeRange.end; + var delta = e.data; + if (delta.action == "insert"){ + var start = delta.start; + var end = delta.end; } else { - var end = changeRange.start; - var start = changeRange.end; + var end = delta.start; + var start = delta.end; } var startRow = start.row; var endRow = end.row; diff --git a/lib/ace/undomanager.js b/lib/ace/undomanager.js index 71b4ba65..6da50a8b 100644 --- a/lib/ace/undomanager.js +++ b/lib/ace/undomanager.js @@ -61,10 +61,9 @@ var UndoManager = function() { * **/ this.execute = function(options) { - // Normalize deltas for storage. - var deltaSets = this.$serializeDeltas(options.args[0]); - + // var deltaSets = this.$serializeDeltas(options.args[0]); + var deltaSets = options.args[0]; // Add deltas to undo stack. this.$doc = options.args[1]; if (options.merge && this.hasUndo()){ @@ -207,7 +206,7 @@ var UndoManager = function() { deltaSets_new[i] = deltaSet_new; } - return deltaSets_new; + return deltaSets_new; } }).call(UndoManager.prototype); diff --git a/lib/ace/worker/mirror.js b/lib/ace/worker/mirror.js index 8254f205..514d377f 100644 --- a/lib/ace/worker/mirror.js +++ b/lib/ace/worker/mirror.js @@ -13,7 +13,19 @@ var Mirror = exports.Mirror = function(sender) { var _self = this; sender.on("change", function(e) { - doc.applyDeltas(e.data); + var data = e.data; + if (data[0].start) { + doc.applyDeltas(data); + } else { + for (var i = 0; i < data.length; i += 2) { + if (Array.isArray(data[i+1])) + var d = {action: "insert", start: data[i], lines: data[i+1]}; + else + var d = {action: "remove", start: data[i],end: data[i+1]}; + + doc.applyDelta(d, true); + } + } if (_self.$timeout) return deferredUpdate.schedule(_self.$timeout); _self.onUpdate(); diff --git a/lib/ace/worker/worker_client.js b/lib/ace/worker/worker_client.js index cb18998f..f5902f90 100644 --- a/lib/ace/worker/worker_client.js +++ b/lib/ace/worker/worker_client.js @@ -162,17 +162,21 @@ var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) { this.changeListener = function(e) { if (!this.deltaQueue) { - this.deltaQueue = [e.data]; + this.deltaQueue = []; setTimeout(this.$sendDeltaQueue, 0); - } else - this.deltaQueue.push(e.data); + } + var delta = e.data; + if (delta.action == "insert") + this.deltaQueue.push(delta.start, delta.lines); + else + this.deltaQueue.push(delta.start, delta.end); }; this.$sendDeltaQueue = function() { var q = this.deltaQueue; if (!q) return; this.deltaQueue = null; - if (q.length > 20 && q.length > this.$doc.getLength() >> 1) { + if (q.length > 50 && q.length > this.$doc.getLength() >> 1) { this.call("setValue", [this.$doc.getValue()]); } else this.emit("change", {data: q}); From 27b6d6dcd38557b2836a71d3933db8270ee7a343 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 15 Feb 2014 00:01:30 +0400 Subject: [PATCH 023/315] apply arguments max length also includes actual call stack --- lib/ace/document.js | 45 +++++++++++++++++++++++------------------- lib/ace/placeholder.js | 2 +- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index 1abb95a2..99b7bb2d 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -302,9 +302,11 @@ var Document = function(textOrLines) { row = 0; } else if (row >= length) { row = length - 1; - column = undefined - } + column = undefined; + } var line = this.getLine(row); + if (column == undefined) + column = line.length; column = Math.min(Math.max(column, 0), line.length); return {row: row, column: column}; }; @@ -421,31 +423,33 @@ var Document = function(textOrLines) { **/ this.remove = function(range) { var start = this.clippedPos(range.start.row, range.start.column); + var end = this.clippedPos(range.end.row, range.end.column); this.applyDelta({ action: "remove", start: start, - end: this.clippedPos(range.end.row, range.end.column), - lines: this.getLinesForRange(range), + end: end, + lines: this.getLinesForRange({start: start, end: end}), }); return this.clonePos(start); }; /** - * Removes the specified columns from the `row`. This method also triggers the `"change"` event. - * @param {Number} row The row to remove from - * @param {Number} startColumn The column to start removing at - * @param {Number} endColumn The column to stop removing at - * @returns {Object} Returns an object containing `startRow` and `startColumn`, indicating the new row and column values.
If `startColumn` is equal to `endColumn`, this function returns nothing. - * - **/ + * Removes the specified columns from the `row`. This method also triggers a `"change"` event. + * @param {Number} row The row to remove from + * @param {Number} startColumn The column to start removing at + * @param {Number} endColumn The column to stop removing at + * @returns {Object} Returns an object containing `startRow` and `startColumn`, indicating the new row and column values.
If `startColumn` is equal to `endColumn`, this function returns nothing. + * + **/ this.removeInLine = function(row, startColumn, endColumn) { - var start = this.clippedPos(row, startColumn); + var start = this.clippedPos(row, startColumn); + var end = this.clippedPos(row, endColumn); this.applyDelta({ action: "remove", start: start, - end: this.clippedPos(row, endColumn), - lines: this.getLinesForRange(range), + end: end, + lines: this.getLinesForRange({start: start, end: end}), }, true); return this.clonePos(start); @@ -568,7 +572,7 @@ var Document = function(textOrLines) { : !Range.comparePoints(delta.start, delta.end)) return; - if (isInsert && delta.lines.length > 0xFFFF) + if (isInsert && delta.lines.length > 0xF000) this.$splitAndapplyLargeDelta(delta); // Apply. @@ -579,22 +583,23 @@ var Document = function(textOrLines) { this.$splitAndapplyLargeDelta = function(delta) { // Split large insert deltas. This is necessary because: // 1. We need to support splicing delta lines into the document via $lines.splice.apply(...) - // 2. fn.apply() doesn't work for a large number of params. The mallest threshold is on safari 0xFFFF. + // 2. fn.apply() doesn't work for a large number of params. The smallest threshold is on safari 0xFFFF. + // we use 0xF000 to leave some space for actual stack // // To Do: Ideally we'd be consistent and also split 'delete' deltas. We don't do this now, because delete // delta handling is too slow. If we make delete delta handling faster we can split all large deltas // as shown in https://gist.github.com/aldendaniels/8367109#file-document-snippet-js // If we do this, update validateDelta() to limit the number of lines in a delete delta. - while (delta.lines.length > 0xFFFF) { + while (delta.lines.length > 0xF000) { // Get split deltas. - var lines = delta.lines.splice(0, 0xFFFF); + var lines = delta.lines.splice(0, 0xF000); lines.push(""); var start = delta.start; this.applyDelta({ action: delta.action, lines: lines, - start: this.pos(start.row, start.column), - end: this.pos(start.row += 0xFFFF, start.column = 0) // Updates remaining delta. + start: this.pos(start.row, start.column), + end: this.pos(start.row += 0xF000, start.column = 0) // Updates remaining delta. }, true); } }; diff --git a/lib/ace/placeholder.js b/lib/ace/placeholder.js index 1d345a24..d7a2d6e9 100644 --- a/lib/ace/placeholder.js +++ b/lib/ace/placeholder.js @@ -150,7 +150,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) **/ this.onUpdate = function(event) { var delta = event.data; - var range = delta.range; + var range = delta; if(range.start.row !== range.end.row) return; if(range.start.row !== this.pos.row) return; if (this.$updating) return; From ad54d2c46cb8b161295ec215d4495c4b69adb661 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 2 Jul 2014 22:00:51 +0400 Subject: [PATCH 024/315] disabled validateDelta since it breaks autocompletion popup --- lib/ace/apply_delta.js | 10 +++++----- lib/ace/autocomplete/popup.js | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/ace/apply_delta.js b/lib/ace/apply_delta.js index 98a1a857..98bfe148 100644 --- a/lib/ace/apply_delta.js +++ b/lib/ace/apply_delta.js @@ -52,7 +52,7 @@ function validateDelta(docLines, delta) { // Validate range type. if (!delta.start || !delta.end) - throwDeltaError(delta, "delta.start/end must be an present"); + throwDeltaError(delta, "delta.start/end must be an present"); // Validate that the start point is contained in the document. var start = delta.start; @@ -72,19 +72,19 @@ function validateDelta(docLines, delta) { } exports.applyDelta = function(docLines, delta, doNotValidate) { - if (!doNotValidate) - validateDelta(docLines, delta); + // disabled validation since it breaks autocompletion popup + // if (!doNotValidate) + // validateDelta(docLines, delta); var row = delta.start.row; var startColumn = delta.start.column; - var line = docLines[row]; + var line = docLines[row] || ""; switch (delta.action) { case "insert": var lines = delta.lines; if (lines.length === 1) { docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); } else { - var line = docLines[row]; var args = [row, 1].concat(delta.lines); docLines.splice.apply(docLines, args); docLines[row] = line.substring(0, startColumn) + docLines[row]; diff --git a/lib/ace/autocomplete/popup.js b/lib/ace/autocomplete/popup.js index a0ab7604..471cdb90 100644 --- a/lib/ace/autocomplete/popup.js +++ b/lib/ace/autocomplete/popup.js @@ -213,8 +213,8 @@ var AcePopup = function(parentNode) { popup.data = []; popup.setData = function(list) { - popup.data = list || []; popup.setValue(lang.stringRepeat("\n", list.length), -1); + popup.data = list || []; popup.setRow(0); }; popup.getData = function(row) { From 60367772a9fc18e68ae7a3e8303cb863579967f9 Mon Sep 17 00:00:00 2001 From: DanyaPostfactum Date: Sun, 12 Oct 2014 01:56:19 +1000 Subject: [PATCH 025/315] Add wrap indent --- lib/ace/edit_session.js | 60 +++++++++++++++++++++++++++++++++++------ lib/ace/layer/marker.js | 3 ++- lib/ace/layer/text.js | 2 ++ 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 71cda95c..8ab76597 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1840,7 +1840,7 @@ var EditSession = function(text, mode) { TAB_SPACE = 12; - this.$computeWrapSplits = function(tokens, wrapLimit) { + this.$computeWrapSplits = function(tokens, wrapLimit, tabSize) { if (tokens.length == 0) { return []; } @@ -1851,6 +1851,32 @@ var EditSession = function(text, mode) { var isCode = this.$wrapAsCode; + var indentSubsequentLines = true; + + var maxIndent = wrapLimit > 8 ? Math.floor(wrapLimit / 2) : 0; + + function getIndentation() { + var indentation = 0; + if (maxIndent === 0) + return indentation; + if (indentSubsequentLines) { + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (token == SPACE) + indentation += 1; + else if (token == TAB) + indentation += tabSize; + else if (token == TAB_SPACE) + continue; + else + break; + } + } + if (isCode) + indentation += tabSize; + return Math.min(indentation, maxIndent); + } + function addSplit(screenPos) { var displayed = tokens.slice(lastSplit, screenPos); @@ -1867,14 +1893,18 @@ var EditSession = function(text, mode) { len -= 1; }); + if (splits.length === 0) { + indent = getIndentation(); + splits.indent = indent; + } lastDocSplit += len; splits.push(lastDocSplit); lastSplit = screenPos; } - - while (displayLength - lastSplit > wrapLimit) { + var indent = 0; + while (displayLength - lastSplit > wrapLimit - indent) { // This is, where the split should be. - var split = lastSplit + wrapLimit; + var split = lastSplit + wrapLimit - indent; // If there is a space or tab at this split position, then making // a split is simple. @@ -1962,7 +1992,7 @@ var EditSession = function(text, mode) { // around -> force a split. if (tokens[split] == CHAR_EXT) split--; - addSplit(split); + addSplit(split - indent); } return splits; }; @@ -2069,6 +2099,17 @@ var EditSession = function(text, mode) { } }; + this.getRowWrapIndent = function(screenRow) { + if (!this.$useWrapMode) { + return 0; + } else { + var row = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE).row; + var splits = this.$wrapData[row]; + var splitIndex = Math.floor(screenRow - row); + return splits.length && splitIndex > 0 ? splits.indent : 0; + } + } + /** * Returns the position (on screen) for the last character in the provided screen row. * @param {Number} screenRow The screen row to check @@ -2206,20 +2247,21 @@ var EditSession = function(text, mode) { line = this.getLine(docRow); foldLine = null; } - + var wrapIndent = 0; if (this.$useWrapMode) { var splits = this.$wrapData[docRow]; if (splits) { var splitIndex = Math.floor(screenRow - row); column = splits[splitIndex]; if(splitIndex > 0 && splits.length) { + wrapIndent = splits.indent; docColumn = splits[splitIndex - 1] || splits[splits.length - 1]; line = line.substring(docColumn); } } } - docColumn += this.$getStringScreenWidth(line, screenColumn)[1]; + docColumn += this.$getStringScreenWidth(line, screenColumn - wrapIndent)[1]; // We remove one character at the end so that the docColumn // position returned is not associated to the next row on the screen. @@ -2311,6 +2353,7 @@ var EditSession = function(text, mode) { textLine = this.getLine(docRow).substring(0, docColumn); foldStartRow = docRow; } + var wrapIndent = 0; // Clamp textLine if in wrapMode. if (this.$useWrapMode) { var wrapRow = this.$wrapData[foldStartRow]; @@ -2323,12 +2366,13 @@ var EditSession = function(text, mode) { textLine = textLine.substring( wrapRow[screenRowOffset - 1] || 0, textLine.length ); + wrapIndent = screenRowOffset > 0 ? wrapRow.indent : 0; } } return { row: screenRow, - column: this.$getStringScreenWidth(textLine)[0] + column: wrapIndent + this.$getStringScreenWidth(textLine)[0] }; }; diff --git a/lib/ace/layer/marker.js b/lib/ace/layer/marker.js index 37e038b5..60329d7b 100644 --- a/lib/ace/layer/marker.js +++ b/lib/ace/layer/marker.js @@ -113,11 +113,12 @@ var Marker = function(parentEl) { // selection end row = range.end.row; - lineRange = new Range(row, 0, row, range.end.column); + lineRange = new Range(row, this.session.getRowWrapIndent(row), row, range.end.column); this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, extraStyle); for (row = range.start.row + 1; row < range.end.row; row++) { lineRange.start.row = row; + lineRange.start.column = this.session.getRowWrapIndent(row); lineRange.end.row = row; lineRange.end.column = this.session.getScreenLastRowColumn(row); this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, extraStyle); diff --git a/lib/ace/layer/text.js b/lib/ace/layer/text.js index aeb74f1c..5080112f 100644 --- a/lib/ace/layer/text.js +++ b/lib/ace/layer/text.js @@ -420,6 +420,8 @@ var Text = function(parentEl) { ); } + stringBuilder.push(lang.stringRepeat("\xa0", splits.indent)); + split ++; screenColumn = 0; splitChars = splits[split] || Number.MAX_VALUE; From f625dfeea3bf2b7828c4cbccfbe0de9f4e5f92a3 Mon Sep 17 00:00:00 2001 From: DanyaPostfactum Date: Sun, 12 Oct 2014 18:37:20 +1000 Subject: [PATCH 026/315] Add indentSubsequentLines to options --- lib/ace/edit_session.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 8ab76597..c7260158 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -1851,7 +1851,7 @@ var EditSession = function(text, mode) { var isCode = this.$wrapAsCode; - var indentSubsequentLines = true; + var indentSubsequentLines = this.$indentSubsequentLines; var maxIndent = wrapLimit > 8 ? Math.floor(wrapLimit / 2) : 0; @@ -2552,6 +2552,7 @@ config.defineOptions(EditSession.prototype, "session", { }, initialValue: "auto" }, + indentSubsequentLines: {initialValue: true}, firstLineNumber: { set: function() {this._signal("changeBreakpoint");}, initialValue: 1 From 6502a3d2cb35c7131e70831b95c9b006a38ee31d Mon Sep 17 00:00:00 2001 From: DanyaPostfactum Date: Sun, 12 Oct 2014 18:37:52 +1000 Subject: [PATCH 027/315] Update tests for wrap indent --- lib/ace/edit_session_test.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/ace/edit_session_test.js b/lib/ace/edit_session_test.js index 87cc9567..bc4226f9 100644 --- a/lib/ace/edit_session_test.js +++ b/lib/ace/edit_session_test.js @@ -280,7 +280,7 @@ module.exports = { session.setUseWrapMode(true); session.setWrapLimitRange(12, 12); session.adjustWrapLimit(80); - + session.setOption("wrapMethod", "text"); assert.position(session.documentToScreenPosition(0, 11), 0, 11); assert.position(session.documentToScreenPosition(0, 12), 1, 0); }, @@ -388,26 +388,27 @@ module.exports = { } EditSession.prototype.$wrapAsCode = true; + EditSession.prototype.$indentSubsequentLines = false; // Basic splitting. computeAndAssert("foo bar foo bar", [ 12 ]); computeAndAssert("foo bar f bar", [ 12 ]); computeAndAssert("foo bar f r", [ 12 ]); // 14 if we enable - computeAndAssert("foo bar foo bar foo bara foo", [12, 25]); + computeAndAssert("foo bar foo bar foo bara foo", [12, 20]); // Don't split if there is only whitespaces/tabs at the end of the line. computeAndAssert("foo foo foo \t \t", [ ]); // If there is no space to split, force split. computeAndAssert("foooooooooooooo", [ 12 ]); - computeAndAssert("fooooooooooooooooooooooooooo", [12, 24]); - computeAndAssert("foo bar fooooooooooobooooooo", [8, 20]); + computeAndAssert("fooooooooooooooooooooooooooo", [12, 20]); + computeAndAssert("foo bar fooooooooooobooooooo", [8, 16, 24]); // Basic splitting + tabs. computeAndAssert("foo \t\tbar", [ 6 ]); computeAndAssert("foo \t \tbar", [ 7 ]); // Ignore spaces/tabs at beginning of split. - computeAndAssert("foo \t \t \t \t bar", [ 7 ]); // 14 + computeAndAssert("foo \t \t \t \t bar", [7, 13]); // 14 // Test wrapping for asian characters. computeAndAssert("ぁぁ", [1], 2); From 525fe1ffe306a6258578c238b17114a00f71888a Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 18 Oct 2014 00:56:13 +0400 Subject: [PATCH 028/315] do not wrap change events in additional e.data --- lib/ace/anchor.js | 4 ++-- lib/ace/document.js | 2 +- lib/ace/document_test.js | 24 ++++++++++++------------ lib/ace/edit_session.js | 21 ++++++++++----------- lib/ace/edit_session/folding.js | 3 +-- lib/ace/editor.js | 5 ++--- lib/ace/ext/chromevox.js | 3 +-- lib/ace/ext/elastic_tabstops_lite.js | 11 +++++------ lib/ace/layer/gutter.js | 3 +-- lib/ace/line_widgets.js | 5 ++--- lib/ace/placeholder.js | 3 +-- lib/ace/range_list.js | 3 +-- lib/ace/snippets.js | 10 +++++----- lib/ace/worker/worker_client.js | 3 +-- 14 files changed, 45 insertions(+), 55 deletions(-) diff --git a/lib/ace/anchor.js b/lib/ace/anchor.js index f3a60277..ff85c13b 100644 --- a/lib/ace/anchor.js +++ b/lib/ace/anchor.js @@ -70,6 +70,7 @@ var Anchor = exports.Anchor = function(doc, row, column) { * @returns {Object} **/ this.getPosition = function() { + //process.exit(2) return this.$clipPositionToDocument(this.row, this.column); }; @@ -99,8 +100,7 @@ var Anchor = exports.Anchor = function(doc, row, column) { * - `value`: An object describing the new Anchor position * **/ - this.onChange = function(e) { - var delta = e.data; + this.onChange = function(delta) { if (delta.start.row == delta.end.row && delta.start.row != this.row) return; diff --git a/lib/ace/document.js b/lib/ace/document.js index 51f6fe8d..c5ccb71b 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -579,7 +579,7 @@ var Document = function(textOrLines) { // Apply. applyDelta(this.$lines, delta, doNotValidate); - this._signal("change", {data: delta}); + this._signal("change", delta); }; this.$splitAndapplyLargeDelta = function(delta) { diff --git a/lib/ace/document_test.js b/lib/ace/document_test.js index a91fccf2..ee27f00b 100644 --- a/lib/ace/document_test.js +++ b/lib/ace/document_test.js @@ -46,7 +46,7 @@ module.exports = { var doc = new Document(["12", "34"]); var deltas = []; - doc.on("change", function(e) { deltas.push(e.data); }); + doc.on("change", function(e) { deltas.push(e); }); doc.insert({row: 0, column: 1}, "juhu"); assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n")); @@ -63,7 +63,7 @@ module.exports = { var doc = new Document(["12", "34"]); var deltas = []; - doc.on("change", function(e) { deltas.push(e.data); }); + doc.on("change", function(e) { deltas.push(e); }); doc.insertMergedLines({row: 0, column: 1}, ['', '']); assert.equal(doc.getValue(), ["1", "2", "34"].join("\n")); @@ -80,7 +80,7 @@ module.exports = { var doc = new Document(["12", "34"]); var deltas = []; - doc.on("change", function(e) { deltas.push(e.data); }); + doc.on("change", function(e) { deltas.push(e); }); doc.insertFullLines(0, ["aa", "bb"]); assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n")); @@ -97,7 +97,7 @@ module.exports = { var doc = new Document(["12", "34"]); var deltas = []; - doc.on("change", function(e) { deltas.push(e.data); }); + doc.on("change", function(e) { deltas.push(e); }); doc.insertFullLines(2, ["aa", "bb"]); assert.equal(doc.getValue(), ["12", "34", "aa", "bb"].join("\n")); @@ -107,7 +107,7 @@ module.exports = { var doc = new Document(["12", "34"]); var deltas = []; - doc.on("change", function(e) { deltas.push(e.data); }); + doc.on("change", function(e) { deltas.push(e); }); doc.insertFullLines(1, ["aa", "bb"]); assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n")); @@ -124,7 +124,7 @@ module.exports = { var doc = new Document(["12", "34"]); var deltas = []; - doc.on("change", function(e) { deltas.push(e.data); }); + doc.on("change", function(e) { deltas.push(e); }); doc.insert({row: 0, column: 0}, "aa\nbb\ncc"); assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n")); @@ -141,7 +141,7 @@ module.exports = { var doc = new Document(["12", "34"]); var deltas = []; - doc.on("change", function(e) { deltas.push(e.data); }); + doc.on("change", function(e) { deltas.push(e); }); doc.insert({row: 1, column: 2}, "aa\nbb\ncc"); assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n")); @@ -158,7 +158,7 @@ module.exports = { var doc = new Document(["12", "34"]); var deltas = []; - doc.on("change", function(e) { deltas.push(e.data); }); + doc.on("change", function(e) { deltas.push(e); }); doc.insert({row: 0, column: 1}, "aa\nbb\ncc"); assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n")); @@ -175,7 +175,7 @@ module.exports = { var doc = new Document(["1234", "5678"]); var deltas = []; - doc.on("change", function(e) { deltas.push(e.data); }); + doc.on("change", function(e) { deltas.push(e); }); doc.remove(new Range(0, 1, 0, 3)); assert.equal(doc.getValue(), ["14", "5678"].join("\n")); @@ -192,7 +192,7 @@ module.exports = { var doc = new Document(["1234", "5678"]); var deltas = []; - doc.on("change", function(e) { deltas.push(e.data); }); + doc.on("change", function(e) { deltas.push(e); }); doc.remove(new Range(0, 4, 1, 0)); assert.equal(doc.getValue(), ["12345678"].join("\n")); @@ -209,7 +209,7 @@ module.exports = { var doc = new Document(["1234", "5678", "abcd"]); var deltas = []; - doc.on("change", function(e) { deltas.push(e.data); }); + doc.on("change", function(e) { deltas.push(e); }); doc.remove(new Range(0, 2, 2, 2)); assert.equal(doc.getValue(), ["12cd"].join("\n")); @@ -226,7 +226,7 @@ module.exports = { var doc = new Document(["1234", "5678", "abcd"]); var deltas = []; - doc.on("change", function(e) { deltas.push(e.data); }); + doc.on("change", function(e) { deltas.push(e); }); doc.remove(new Range(1, 0, 3, 0)); assert.equal(doc.getValue(), ["1234", ""].join("\n")); diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 53e98baa..377df45b 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -249,13 +249,12 @@ var EditSession = function(text, mode) { this.$resetRowCache(fold.start.row); }; - this.onChange = function(e) { - var delta = e.data; + this.onChange = function(delta) { this.$modified = true; this.$resetRowCache(delta.start.row); - var removedFolds = this.$updateInternalDataOnChange(e); + var removedFolds = this.$updateInternalDataOnChange(delta); if (!this.$fromUndo && this.$undoManager && !delta.ignore) { this.$deltasDoc.push(delta); if (removedFolds && removedFolds.length != 0) { @@ -269,7 +268,7 @@ var EditSession = function(text, mode) { } this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta); - this._signal("change", e); + this._signal("change", delta); }; /** @@ -1667,11 +1666,11 @@ var EditSession = function(text, mode) { }; }; - this.$updateInternalDataOnChange = function(e) { + this.$updateInternalDataOnChange = function(delta) { var useWrapMode = this.$useWrapMode; - var action = e.data.action; - var start = e.data.start; - var end = e.data.end; + var action = delta.action; + var start = delta.start; + var end = delta.end; var firstRow = start.row; var lastRow = end.row; var len = lastRow - firstRow; @@ -1683,7 +1682,7 @@ var EditSession = function(text, mode) { this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len); var foldLines = this.$foldData; - removedFolds = this.getFoldsInRange(e.data); + removedFolds = this.getFoldsInRange(delta); this.removeFolds(removedFolds); var foldLine = this.getFoldLine(end.row); @@ -1748,10 +1747,10 @@ var EditSession = function(text, mode) { } else { // Realign folds. E.g. if you add some new chars before a fold, the // fold should "move" to the right. - len = Math.abs(e.data.start.column - e.data.end.column); + len = Math.abs(delta.start.column - delta.end.column); if (action === "remove") { // Get all the folds in the change range and remove them. - removedFolds = this.getFoldsInRange(e.data); + removedFolds = this.getFoldsInRange(delta); this.removeFolds(removedFolds); len = -len; diff --git a/lib/ace/edit_session/folding.js b/lib/ace/edit_session/folding.js index d5052266..0c1914ce 100644 --- a/lib/ace/edit_session/folding.js +++ b/lib/ace/edit_session/folding.js @@ -827,8 +827,7 @@ function Folding() { } }; - this.updateFoldWidgets = function(e) { - var delta = e.data; + this.updateFoldWidgets = function(delta) { var firstRow = delta.start.row; var len = delta.end.row - firstRow; diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 97c4a8e6..9574d703 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -674,14 +674,13 @@ var Editor = function(renderer, session) { * * **/ - this.onDocumentChange = function(e) { + this.onDocumentChange = function(delta) { // Rerender and emit "change" event. - var delta = e.data; var wrap = this.session.$useWrapMode; var lastRow = (delta.start.row == delta.end.row ? delta.end.row : Infinity); this.renderer.updateLines(delta.start.row, lastRow, wrap); - this._signal("change", e); + this._signal("change", delta); // Update cursor because tab characters can influence the cursor position. this.$cursorChange(); diff --git a/lib/ace/ext/chromevox.js b/lib/ace/ext/chromevox.js index 4abb8278..52a180d4 100644 --- a/lib/ace/ext/chromevox.js +++ b/lib/ace/ext/chromevox.js @@ -578,8 +578,7 @@ var onSelectionChange = function(evt) { * and deleting text. * @param {!Event} evt The event. */ -var onChange = function(evt) { - var data = evt.data; +var onChange = function(delta) { switch (data.action) { case 'remove': cvox.Api.speak(data.text, 0, DELETED_PROP); diff --git a/lib/ace/ext/elastic_tabstops_lite.js b/lib/ace/ext/elastic_tabstops_lite.js index ce5e55f9..0f89423a 100644 --- a/lib/ace/ext/elastic_tabstops_lite.js +++ b/lib/ace/ext/elastic_tabstops_lite.js @@ -44,13 +44,12 @@ var ElasticTabstopsLite = function(editor) { this.onExec = function() { recordChanges = true; }; - this.onChange = function(e) { - var range = e.data; + this.onChange = function(delta) { if (recordChanges) { - if (changedRows.indexOf(range.start.row) == -1) - changedRows.push(range.start.row); - if (range.end.row != range.start.row) - changedRows.push(range.end.row); + if (changedRows.indexOf(delta.start.row) == -1) + changedRows.push(delta.start.row); + if (delta.end.row != delta.start.row) + changedRows.push(delta.end.row); } }; }; diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index 9608868c..dc1055c2 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -100,10 +100,9 @@ var Gutter = function(parentEl) { } }; - this.$updateAnnotations = function (e) { + this.$updateAnnotations = function (delta) { if (!this.$annotations.length) return; - var delta = e.data; var firstRow = delta.start.row; var len = delta.end.row - firstRow; if (len === 0) { diff --git a/lib/ace/line_widgets.js b/lib/ace/line_widgets.js index 4e5ae39d..ba87d857 100644 --- a/lib/ace/line_widgets.js +++ b/lib/ace/line_widgets.js @@ -113,11 +113,10 @@ function LineWidgets(session) { }); }; - this.updateOnChange = function(e) { + this.updateOnChange = function(delta) { var lineWidgets = this.session.lineWidgets; if (!lineWidgets) return; - - var delta = e.data; + var startRow = delta.start.row; var len = delta.end.row - startRow; diff --git a/lib/ace/placeholder.js b/lib/ace/placeholder.js index d3bf1969..0e299594 100644 --- a/lib/ace/placeholder.js +++ b/lib/ace/placeholder.js @@ -150,8 +150,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) * Emitted when the place holder updates. * **/ - this.onUpdate = function(event) { - var delta = event.data; + this.onUpdate = function(delta) { var range = delta; if(range.start.row !== range.end.row) return; if(range.start.row !== this.pos.row) return; diff --git a/lib/ace/range_list.js b/lib/ace/range_list.js index a112139a..326bc41b 100644 --- a/lib/ace/range_list.js +++ b/lib/ace/range_list.js @@ -180,8 +180,7 @@ var RangeList = function() { this.session = null; }; - this.$onChange = function(e) { - var delta = e.data; + this.$onChange = function(delta) { if (delta.action == "insert"){ var start = delta.start; var end = delta.end; diff --git a/lib/ace/snippets.js b/lib/ace/snippets.js index 10c34bf0..699cd6e9 100644 --- a/lib/ace/snippets.js +++ b/lib/ace/snippets.js @@ -667,11 +667,11 @@ var TabstopManager = function(editor) { this.editor = null; }; - this.onChange = function(e) { - var changeRange = e.data.range; - var isRemove = e.data.action[0] == "r"; - var start = changeRange.start; - var end = changeRange.end; + this.onChange = function(delta) { + var changeRange = delta; + var isRemove = delta.action[0] == "r"; + var start = delta.start; + var end = delta.end; var startRow = start.row; var endRow = end.row; var lineDif = endRow - startRow; diff --git a/lib/ace/worker/worker_client.js b/lib/ace/worker/worker_client.js index 255a2cea..ba4f20a0 100644 --- a/lib/ace/worker/worker_client.js +++ b/lib/ace/worker/worker_client.js @@ -162,12 +162,11 @@ var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) { doc.on("change", this.changeListener); }; - this.changeListener = function(e) { + this.changeListener = function(delta) { if (!this.deltaQueue) { this.deltaQueue = []; setTimeout(this.$sendDeltaQueue, 0); } - var delta = e.data; if (delta.action == "insert") this.deltaQueue.push(delta.start, delta.lines); else From 22de93672735cb6ad39cd131727cb49ca13f2c24 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 5 Nov 2014 23:15:45 +0400 Subject: [PATCH 029/315] fix bracket pairing for multiple selections --- lib/ace/mode/behaviour/behaviour_test.js | 133 +++++++++++++++++++++++ lib/ace/mode/behaviour/cstyle.js | 4 +- lib/ace/multi_select_test.js | 28 ++--- lib/ace/test/all_browser.js | 1 + 4 files changed, 147 insertions(+), 19 deletions(-) create mode 100644 lib/ace/mode/behaviour/behaviour_test.js diff --git a/lib/ace/mode/behaviour/behaviour_test.js b/lib/ace/mode/behaviour/behaviour_test.js new file mode 100644 index 00000000..33a09c83 --- /dev/null +++ b/lib/ace/mode/behaviour/behaviour_test.js @@ -0,0 +1,133 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +if (typeof process !== "undefined") { + require("amd-loader"); +} + +define(function(require, exports, module) { +"use strict"; + +require("../../multi_select"); +var assert = require("../../test/assertions"); +var Range = require("../../range").Range; +var Editor = require("../../editor").Editor; +var EditSession = require("../../edit_session").EditSession; +var MockRenderer = require("../../test/mockrenderer").MockRenderer; +var JavaScriptMode = require("../javascript").Mode; +var editor; +var exec = function(name, times, args) { + do { + editor.commands.exec(name, editor, args); + } while(times --> 1); +}; +var testRanges = function(str) { + assert.equal(editor.selection.getAllRanges() + "", str + ""); +}; + +module.exports = { + + name: "ACE multi_select.js", + + "test: cstyle": function() { + function testValue(line) { + assert.equal(editor.getValue(), Array(4).join(line + "\n")); + } + function testSelection(line, col, inc) { + editor.selection.rangeList.ranges.forEach(function(r) { + assert.range(r, line, col, line, col); + line += (inc || 1); + }); + } + var doc = new EditSession([ + "", + "", + "", + "" + ], new JavaScriptMode()); + editor = new Editor(new MockRenderer(), doc); + editor.setOption("behavioursEnabled", true); + + editor.navigateFileStart(); + exec("addCursorBelow", 2); + + exec("insertstring", 1, "if "); + + // pairing ( + exec("insertstring", 1, "("); + testValue("if ()"); + testSelection(0, 4); + exec("insertstring", 1, ")"); + testValue("if ()"); + testSelection(0, 5); + + // pairing [ + exec("gotoleft", 1); + exec("insertstring", 1, "["); + testValue("if ([])"); + testSelection(0, 5); + + exec("insertstring", 1, "]"); + testValue("if ([])"); + testSelection(0, 6); + + // test deletion + exec("gotoleft", 1); + exec("backspace", 1); + testValue("if ()"); + testSelection(0, 4); + + exec("gotolineend", 1); + exec("insertstring", 1, "{"); + testValue("if (){}"); + testSelection(0, 6); + + exec("insertstring", 1, "}"); + testValue("if (){}"); + testSelection(0, 7); + + exec("gotolinestart", 1); + exec("insertstring", 1, "("); + testValue("(if (){}"); + exec("backspace", 1); + + editor.setValue(""); + exec("insertstring", 1, "{"); + assert.equal(editor.getValue(), "{") + exec("insertstring", 1, "\n"); + assert.equal(editor.getValue(), "{\n \n}") + } +}; + +}); + +if (typeof module !== "undefined" && module === require.main) { + require("asyncjs").test.testcase(module.exports).exec(); +} diff --git a/lib/ace/mode/behaviour/cstyle.js b/lib/ace/mode/behaviour/cstyle.js index 2709168e..a8a18e72 100644 --- a/lib/ace/mode/behaviour/cstyle.js +++ b/lib/ace/mode/behaviour/cstyle.js @@ -42,11 +42,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/ace/multi_select_test.js b/lib/ace/multi_select_test.js index 45ab4965..2e71aefa 100644 --- a/lib/ace/multi_select_test.js +++ b/lib/ace/multi_select_test.js @@ -35,22 +35,22 @@ if (typeof process !== "undefined") { define(function(require, exports, module) { "use strict"; -var EditSession = require("./edit_session").EditSession; -var Editor = require("./editor").Editor; -var MockRenderer = require("./test/mockrenderer").MockRenderer; -var Range = require("./range").Range; +require("./multi_select"); var assert = require("./test/assertions"); -var MultiSelect = require("./multi_select").MultiSelect; +var Range = require("./range").Range; +var Editor = require("./editor").Editor; +var EditSession = require("./edit_session").EditSession; +var MockRenderer = require("./test/mockrenderer").MockRenderer; var editor; var exec = function(name, times, args) { do { editor.commands.exec(name, editor, args); - } while(times --> 1) + } while(times --> 1); }; var testRanges = function(str) { assert.equal(editor.selection.getAllRanges() + "", str + ""); -} +}; module.exports = { @@ -63,7 +63,6 @@ module.exports = { " wtt.w" ]); editor = new Editor(new MockRenderer(), doc); - MultiSelect(editor); editor.navigateFileEnd(); exec("selectMoreBefore", 3); @@ -90,7 +89,6 @@ module.exports = { " wtt.we" ]); editor = new Editor(new MockRenderer(), doc); - MultiSelect(editor); editor.selectMoreLines(1); testRanges("Range: [0/0] -> [0/0],Range: [1/0] -> [1/0]"); @@ -113,9 +111,8 @@ module.exports = { " wtt.w" ]); editor = new Editor(new MockRenderer(), doc); - MultiSelect(editor); - editor.selectMoreLines(1) + editor.selectMoreLines(1); testRanges("Range: [0/0] -> [0/0],Range: [1/0] -> [1/0]"); assert.ok(editor.inMultiSelectMode); @@ -134,7 +131,6 @@ module.exports = { " wtt.w" ]); editor = new Editor(new MockRenderer(), doc); - MultiSelect(editor); var selection = editor.selection; var range1 = new Range(0, 2, 0, 4); @@ -158,7 +154,6 @@ module.exports = { "test: onPaste in command with multiselect": function() { var doc = new EditSession(["l1", "l2"]); editor = new Editor(new MockRenderer(), doc); - MultiSelect(editor); editor.commands.addCommand({ name: 'insertfoo', exec: function(ed) { ed.onPaste('foo'); }, @@ -167,7 +162,7 @@ module.exports = { var selection = editor.selection; var range1 = new Range(0,2,0,2); var range2 = new Range(1,2,1,2); - selection.fromOrientedRange(range1) + selection.fromOrientedRange(range1); selection.addRange(range2); editor.execCommand('insertfoo'); assert.equal('l1foo\nl2foo', editor.getValue()); @@ -176,14 +171,13 @@ module.exports = { "test multiselect fromJSON/toJSON": function() { var doc = new EditSession(["l1", "l2"]); editor = new Editor(new MockRenderer(), doc); - MultiSelect(editor); var selection = editor.selection; var before = selection.toJSON(); var range1 = new Range(0,2,0,2); var range2 = new Range(1,2,1,2); - selection.fromOrientedRange(range1) + selection.fromOrientedRange(range1); selection.addRange(range2); var after = selection.toJSON(); @@ -201,5 +195,5 @@ module.exports = { }); if (typeof module !== "undefined" && module === require.main) { - require("asyncjs").test.testcase(module.exports).exec() + require("asyncjs").test.testcase(module.exports).exec(); } diff --git a/lib/ace/test/all_browser.js b/lib/ace/test/all_browser.js index 3b7bf5d9..9b5742dd 100644 --- a/lib/ace/test/all_browser.js +++ b/lib/ace/test/all_browser.js @@ -43,6 +43,7 @@ var testNames = [ "ace/mode/folding/pythonic_test", "ace/mode/folding/xml_test", "ace/mode/folding/coffee_test", + "ace/mode/behaviour/behaviour_test", "ace/multi_select_test", "ace/mouse/mouse_handler_test", "ace/occur_test", From 9ccf68dbb297429d5c28ee19483b879effbc08d2 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 5 Nov 2014 23:17:59 +0400 Subject: [PATCH 030/315] make sure missing emmet can't break tab key --- lib/ace/ext/emmet.js | 49 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/lib/ace/ext/emmet.js b/lib/ace/ext/emmet.js index 75eefa3f..ceb155ef 100644 --- a/lib/ace/ext/emmet.js +++ b/lib/ace/ext/emmet.js @@ -342,29 +342,29 @@ var keymap = { var editorProxy = new AceEmmetEditor(); exports.commands = new HashHandler(); exports.runEmmetCommand = function(editor) { - editorProxy.setupContext(editor); - if (editorProxy.getSyntax() == "php") - return false; - var actions = emmet.require("actions"); - - if (this.action == "expand_abbreviation_with_tab") { - if (!editor.selection.isEmpty()) - return false; - } - - if (this.action == "wrap_with_abbreviation") { - // without setTimeout prompt doesn't work on firefox - return setTimeout(function() { - actions.run("wrap_with_abbreviation", editorProxy); - }, 0); - } - - var pos = editor.selection.lead; - var token = editor.session.getTokenAt(pos.row, pos.column); - if (token && /\btag\b/.test(token.type)) - return false; - try { + editorProxy.setupContext(editor); + if (editorProxy.getSyntax() == "php") + return false; + var actions = emmet.require("actions"); + + if (this.action == "expand_abbreviation_with_tab") { + if (!editor.selection.isEmpty()) + return false; + } + + if (this.action == "wrap_with_abbreviation") { + // without setTimeout prompt doesn't work on firefox + return setTimeout(function() { + actions.run("wrap_with_abbreviation", editorProxy); + }, 0); + } + + var pos = editor.selection.lead; + var token = editor.session.getTokenAt(pos.row, pos.column); + if (token && /\btag\b/.test(token.type)) + return false; + var result = actions.run(this.action, editorProxy); } catch(e) { editor._signal("changeStatus", typeof e == "string" ? e : e.message); @@ -393,7 +393,7 @@ exports.updateCommands = function(editor, enabled) { }; exports.isSupportedMode = function(modeId) { - return modeId && /css|less|scss|sass|stylus|html|php|twig/.test(modeId); + return modeId && /css|less|scss|sass|stylus|html|php|twig|ejs/.test(modeId); }; var onChangeMode = function(e, target) { @@ -406,9 +406,8 @@ var onChangeMode = function(e, target) { if (enabled) { if (typeof emmetPath == "string") { require("ace/config").loadModule(emmetPath, function() { - + emmetPath = null; }); - emmetPath = null; } } exports.updateCommands(editor, enabled); From 7bb5b305be6d35b8f2322ae53de95152cd77eb62 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Tue, 4 Nov 2014 13:01:08 -0800 Subject: [PATCH 031/315] isearch: add regexp support --- lib/ace/incremental_search.js | 56 ++++++++++++++++++++++++++++-- lib/ace/incremental_search_test.js | 21 +++++++---- 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/lib/ace/incremental_search.js b/lib/ace/incremental_search.js index 88615006..4e7f7bf3 100644 --- a/lib/ace/incremental_search.js +++ b/lib/ace/incremental_search.js @@ -64,6 +64,34 @@ function IncrementalSearch() { oop.inherits(IncrementalSearch, Search); +// regexp handling + +function isRegExp(obj) { + return obj instanceof RegExp; +} + +function regExpToObject(re) { + var string = String(re), + start = string.indexOf('/'), + flagStart = string.lastIndexOf('/'); + return { + expression: string.slice(start+1, flagStart), + flags: string.slice(flagStart+1) + } +} + +function stringToRegExp(string, flags) { + try { + return new RegExp(string, flags); + } catch (e) { return string; } +} + +function objectToRegExp(obj) { + return stringToRegExp(obj.expression, obj.flags); +} + +// iSearch class + ;(function() { this.activate = function(ed, backwards) { @@ -140,7 +168,9 @@ oop.inherits(IncrementalSearch, Search); // try to find the next occurence and enable highlighting marker options.start = this.$currentPos; var session = this.$editor.session, - found = this.find(session); + found = this.find(session), + shouldSelect = this.$editor.emacsMark ? + !!this.$editor.emacsMark() : !this.$editor.selection.isEmpty(); if (found) { if (options.backwards) found = Range.fromPoints(found.end, found.start); this.$editor.moveCursorToPosition(found.end); @@ -156,13 +186,21 @@ oop.inherits(IncrementalSearch, Search); this.addString = function(s) { return this.highlightAndFindWithNeedle(false, function(needle) { - return needle + s; + if (!isRegExp(needle)) + return needle + s; + var reObj = regExpToObject(needle); + reObj.expression += s; + return objectToRegExp(reObj); }); } this.removeChar = function(c) { return this.highlightAndFindWithNeedle(false, function(needle) { - return needle.length > 0 ? needle.substring(0, needle.length-1) : needle; + if (!isRegExp(needle)) + return needle.substring(0, needle.length-1); + var reObj = regExpToObject(needle); + reObj.expression = reObj.expression.substring(0, reObj.expression.length-1); + return objectToRegExp(reObj); }); } @@ -189,6 +227,18 @@ oop.inherits(IncrementalSearch, Search); this.addString(text); } + this.convertNeedleToRegExp = function() { + return this.highlightAndFindWithNeedle(false, function(needle) { + return isRegExp(needle) ? needle : stringToRegExp(needle, 'ig'); + }); + } + + this.convertNeedleToString = function() { + return this.highlightAndFindWithNeedle(false, function(needle) { + return isRegExp(needle) ? regExpToObject(needle).expression : needle; + }); + } + this.statusMessage = function(found) { var options = this.$options, msg = ''; msg += options.backwards ? 'reverse-' : ''; diff --git a/lib/ace/incremental_search_test.js b/lib/ace/incremental_search_test.js index 262e09a7..c99e9382 100644 --- a/lib/ace/incremental_search_test.js +++ b/lib/ace/incremental_search_test.js @@ -35,10 +35,12 @@ if (typeof process !== "undefined") { define(function(require, exports, module) { "use strict"; +var config = require("./config"); var EditSession = require("./edit_session").EditSession; var Editor = require("./editor").Editor; var MockRenderer = require("./test/mockrenderer").MockRenderer; var Range = require("./range").Range; +var MultiSelect = require("./multi_select").MultiSelect; var assert = require("./test/assertions"); var IncrementalSearch = require("./incremental_search").IncrementalSearch; @@ -69,6 +71,7 @@ module.exports = { setUp: function() { var session = new EditSession(["abc123", "xyz124"]); editor = new Editor(new MockRenderer(), session); + new MultiSelect(editor); iSearch = new IncrementalSearch(); }, @@ -190,13 +193,17 @@ module.exports = { testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); }, - "test: extend selection in emacs mark mode" : function() { - var emacs = require('./keyboard/emacs'); - editor.keyBinding.addKeyboardHandler(emacs.handler); - emacs.handler.commands.setMark.exec(editor); - iSearch.activate(editor); - iSearch.addString('1'); iSearch.addString('2');; - testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); + "test: extend selection in emacs mark mode" : function(next) { + config.loadModule("ace/keyboard/emacs", function(emacs) { + // var emacs = require('./keyboard/emacs'); + editor.keyBinding.addKeyboardHandler(emacs.handler); + emacs.handler.commands.setMark.exec(editor); + iSearch.activate(editor); + iSearch.addString('1'); iSearch.addString('2'); + + testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); + next(); + }); } }; From a93646d2f704f15d759adc8fe0d20be39fc86528 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Tue, 4 Nov 2014 13:01:29 -0800 Subject: [PATCH 032/315] isearch: commands searchAsRegExp and selectAllMatches --- .../commands/incremental_search_commands.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/ace/commands/incremental_search_commands.js b/lib/ace/commands/incremental_search_commands.js index 8ef80303..a0a0fe5f 100644 --- a/lib/ace/commands/incremental_search_commands.js +++ b/lib/ace/commands/incremental_search_commands.js @@ -162,6 +162,28 @@ exports.iSearchCommands = [{ exec: function(iSearch) { iSearch.$editor.execCommand('recenterTopBottom'); }, readOnly: true, isIncrementalSearchCommand: true +}, { + name: 'selectAllMatches', + bindKey: 'Ctrl-space', + exec: function(iSearch) { + var ed = iSearch.$editor, + hl = ed.session.$isearchHighlight, + ranges = hl && hl.cache ? hl.cache + .reduce(function(ranges, ea) { + return ranges.concat(ea ? ea : []); }, []) : []; + iSearch.deactivate(false); + ranges.forEach(ed.selection.addRange.bind(ed.selection)); + }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: 'searchAsRegExp', + bindKey: 'Alt-r', + exec: function(iSearch) { + iSearch.convertNeedleToRegExp(); + }, + readOnly: true, + isIncrementalSearchCommand: true }]; function IncrementalSearchKeyboardHandler(iSearch) { From 775cdedefb1baeb94410bb5449f5f121c4437ed4 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Tue, 4 Nov 2014 16:00:48 -0800 Subject: [PATCH 033/315] isearch test fix --- lib/ace/incremental_search_test.js | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/lib/ace/incremental_search_test.js b/lib/ace/incremental_search_test.js index c99e9382..991291c5 100644 --- a/lib/ace/incremental_search_test.js +++ b/lib/ace/incremental_search_test.js @@ -35,7 +35,7 @@ if (typeof process !== "undefined") { define(function(require, exports, module) { "use strict"; -var config = require("./config"); +var emacs = require('./keyboard/emacs'); var EditSession = require("./edit_session").EditSession; var Editor = require("./editor").Editor; var MockRenderer = require("./test/mockrenderer").MockRenderer; @@ -193,17 +193,14 @@ module.exports = { testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); }, - "test: extend selection in emacs mark mode" : function(next) { - config.loadModule("ace/keyboard/emacs", function(emacs) { - // var emacs = require('./keyboard/emacs'); - editor.keyBinding.addKeyboardHandler(emacs.handler); - emacs.handler.commands.setMark.exec(editor); - iSearch.activate(editor); - iSearch.addString('1'); iSearch.addString('2'); - - testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); - next(); - }); + "test: extend selection in emacs mark mode" : function() { + var emacs = require('./keyboard/emacs'); + editor.keyBinding.addKeyboardHandler(emacs.handler); + emacs.handler.commands.setMark.exec(editor); + iSearch.activate(editor); + iSearch.addString('1'); iSearch.addString('2'); + + testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); } }; From 072dcb1c11aee9775966d5c85d510a89e8439c05 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 6 Nov 2014 20:41:25 +0400 Subject: [PATCH 034/315] fix tripple brace highlighting in handlebars mode --- demo/kitchen-sink/docs/handlebars.hbs | 2 +- lib/ace/mode/_test/tokens_cirru.json | 267 +++++++++++++++++++++ lib/ace/mode/_test/tokens_elixir.json | 196 +++++++++++++++ lib/ace/mode/_test/tokens_handlebars.json | 4 +- lib/ace/mode/handlebars.js | 2 +- lib/ace/mode/handlebars_highlight_rules.js | 18 +- lib/ace/snippets/elixir.js | 7 + lib/ace/snippets/elixir.snippets | 0 8 files changed, 483 insertions(+), 13 deletions(-) create mode 100644 lib/ace/mode/_test/tokens_cirru.json create mode 100644 lib/ace/mode/_test/tokens_elixir.json create mode 100644 lib/ace/snippets/elixir.js create mode 100644 lib/ace/snippets/elixir.snippets diff --git a/demo/kitchen-sink/docs/handlebars.hbs b/demo/kitchen-sink/docs/handlebars.hbs index 1cdf786e..bb096a1a 100644 --- a/demo/kitchen-sink/docs/handlebars.hbs +++ b/demo/kitchen-sink/docs/handlebars.hbs @@ -3,6 +3,6 @@
{{#each comments}}

{{title}}

-
{{body}}
+
{{{body}}}
{{/each}}
diff --git a/lib/ace/mode/_test/tokens_cirru.json b/lib/ace/mode/_test/tokens_cirru.json new file mode 100644 index 00000000..de4852e6 --- /dev/null +++ b/lib/ace/mode/_test/tokens_cirru.json @@ -0,0 +1,267 @@ +[[ + "start", + ["comment.line.double-dash","-- https://github.com/Cirru/cirru-gopher/blob/master/code/scope.cr,"] +],[ + "start" +],[ + "line", + ["support.function","set"], + ["text"," "], + ["variable.parameter","a"], + ["text"," "], + ["storage.modifier","("], + ["support.function","int"], + ["text"," "], + ["constant.numeric","2"], + ["storage.modifier",")"] +],[ + "start" +],[ + "line", + ["support.function","print"], + ["text"," "], + ["storage.modifier","("], + ["support.function","self"], + ["storage.modifier",")"] +],[ + "start" +],[ + "line", + ["support.function","set"], + ["text"," "], + ["variable.parameter","c"], + ["text"," "], + ["storage.modifier","("], + ["support.function","child"], + ["storage.modifier",")"] +],[ + "start" +],[ + "line", + ["support.function","under"], + ["text"," "], + ["variable.parameter","c"] +],[ + "line", + ["markup.raw"," "], + ["support.function","under"], + ["text"," "], + ["variable.parameter","parent"] +],[ + "line", + ["markup.raw"," "], + ["support.function","print"], + ["text"," "], + ["variable.parameter","a"] +],[ + "start" +],[ + "line", + ["support.function","print"], + ["text"," "], + ["storage.modifier","$"], + ["text"," "], + ["support.function","get"], + ["text"," "], + ["variable.parameter","c"], + ["text"," "], + ["variable.parameter","a"] +],[ + "start" +],[ + "line", + ["support.function","set"], + ["text"," "], + ["variable.parameter","c"], + ["text"," "], + ["variable.parameter","x"], + ["text"," "], + ["storage.modifier","("], + ["support.function","int"], + ["text"," "], + ["constant.numeric","3"], + ["storage.modifier",")"] +],[ + "line", + ["support.function","print"], + ["text"," "], + ["storage.modifier","$"], + ["text"," "], + ["support.function","get"], + ["text"," "], + ["variable.parameter","c"], + ["text"," "], + ["variable.parameter","x"] +],[ + "start" +],[ + "line", + ["support.function","set"], + ["text"," "], + ["variable.parameter","just-print"], + ["text"," "], + ["storage.modifier","$"], + ["text"," "], + ["support.function","code"] +],[ + "line", + ["markup.raw"," "], + ["support.function","print"], + ["text"," "], + ["variable.parameter","a"] +],[ + "start" +],[ + "line", + ["support.function","print"], + ["text"," "], + ["variable.parameter","just-print"] +],[ + "start" +],[ + "line", + ["support.function","eval"], + ["text"," "], + ["storage.modifier","("], + ["support.function","self"], + ["storage.modifier",")"], + ["text"," "], + ["variable.parameter","just-print"] +],[ + "line", + ["support.function","eval"], + ["text"," "], + ["variable.parameter","just-print"] +],[ + "start" +],[ + "line", + ["support.function","print"], + ["text"," "], + ["storage.modifier","("], + ["support.function","string"], + ["text"," "], + ["string.quoted.double","\"string with space\""], + ["storage.modifier",")"] +],[ + "line", + ["support.function","print"], + ["text"," "], + ["storage.modifier","("], + ["support.function","string"], + ["text"," "], + ["string.quoted.double","\"escapes "], + ["constant.character.escape","\\n"], + ["string.quoted.double"," "], + ["constant.character.escape","\\\"\\\\"], + ["string.quoted.double","\""], + ["storage.modifier",")"] +],[ + "start" +],[ + "start", + ["support.function","brackets"], + ["text"," "], + ["storage.modifier","((((()))))"] +],[ + "start" +],[ + "line", + ["string.quoted.double","\"eval\""], + ["text"," "], + ["storage.modifier","$"], + ["text"," "], + ["support.function","string"], + ["text"," "], + ["string.quoted.double","\"eval\""] +],[ + "start" +],[ + "line", + ["support.function","print"], + ["text"," "], + ["storage.modifier","("], + ["support.function","add"], + ["text"," "], + ["storage.modifier","$"], + ["text"," "], + ["storage.modifier","("], + ["support.function","int"], + ["text"," "], + ["constant.numeric","1"], + ["storage.modifier",")"], + ["text"," "], + ["storage.modifier","("], + ["support.function","int"], + ["text"," "], + ["constant.numeric","2"], + ["storage.modifier","))"] +],[ + "start" +],[ + "start", + ["support.function","print"], + ["text"," "], + ["storage.modifier","$"], + ["text"," "], + ["support.function","unwrap"], + ["text"," "], + ["storage.modifier","$"] +],[ + "line", + ["text"," "], + ["support.function","map"], + ["text"," "], + ["storage.modifier","("], + ["support.function","a"], + ["text"," "], + ["storage.modifier","$"], + ["text"," "], + ["support.function","int"], + ["text"," "], + ["constant.numeric","1"], + ["storage.modifier",")"], + ["text"," "], + ["storage.modifier","("], + ["support.function","b"], + ["text"," "], + ["storage.modifier","$"], + ["text"," "], + ["support.function","int"], + ["text"," "], + ["constant.numeric","2"], + ["storage.modifier",")"] +],[ + "start" +],[ + "line", + ["support.function","print"], + ["text"," "], + ["variable.parameter","a"] +],[ + "line", + ["markup.raw"," "], + ["support.function","int"], + ["text"," "], + ["constant.numeric","1"] +],[ + "line", + ["markup.raw"," "], + ["storage.modifier",","], + ["text"," "], + ["variable.parameter","b"], + ["text"," "], + ["variable.parameter","c"] +],[ + "line", + ["markup.raw"," "], + ["support.function","int"], + ["text"," "], + ["constant.numeric","2"] +],[ + "line", + ["markup.raw"," "], + ["storage.modifier",","], + ["text"," "], + ["variable.parameter","d"] +]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_elixir.json b/lib/ace/mode/_test/tokens_elixir.json new file mode 100644 index 00000000..cbbe1fee --- /dev/null +++ b/lib/ace/mode/_test/tokens_elixir.json @@ -0,0 +1,196 @@ +[[ + "start", + ["keyword.control.module.elixir","defmodule"], + ["meta.module.elixir"," "], + ["entity.name.type.module.elixir","HelloModule"], + ["text"," "], + ["keyword.control.elixir","do"] +],[ + "comment.documentation.heredoc", + ["text"," "], + ["comment.documentation.heredoc","@moduledoc \"\"\""] +],[ + "comment.documentation.heredoc", + ["comment.documentation.heredoc"," This is supposed to be `markdown`."] +],[ + "comment.documentation.heredoc", + ["comment.documentation.heredoc"," __Yes__ this is [mark](http://down.format)"] +],[ + "comment.documentation.heredoc" +],[ + "comment.documentation.heredoc", + ["comment.documentation.heredoc"," # Truly"] +],[ + "comment.documentation.heredoc" +],[ + "comment.documentation.heredoc", + ["comment.documentation.heredoc"," ## marked"] +],[ + "comment.documentation.heredoc" +],[ + "comment.documentation.heredoc", + ["comment.documentation.heredoc"," * with lists"] +],[ + "comment.documentation.heredoc", + ["comment.documentation.heredoc"," * more"] +],[ + "comment.documentation.heredoc", + ["comment.documentation.heredoc"," * and more"] +],[ + "comment.documentation.heredoc" +],[ + "comment.documentation.heredoc", + ["comment.documentation.heredoc"," Even.with(code)"] +],[ + "comment.documentation.heredoc", + ["comment.documentation.heredoc"," blocks |> with |> samples"] +],[ + "comment.documentation.heredoc" +],[ + "comment.documentation.heredoc", + ["comment.documentation.heredoc"," _Docs are first class citizens in Elixir_ (Jose Valim)"] +],[ + "start", + ["comment.documentation.heredoc"," \"\"\""] +],[ + "start", + ["text"," "] +],[ + "start", + ["text"," "], + ["punctuation.definition.comment.elixir","#"], + ["comment.line.number-sign.elixir"," A \"Hello world\" function"] +],[ + "start", + ["text"," "], + ["keyword.control.elixir","def"], + ["text"," some_fun "], + ["keyword.control.elixir","do"] +],[ + "start", + ["text"," "], + ["variable.other.constant.elixir","IO"], + ["punctuation.separator.method.elixir","."], + ["text","puts "], + ["punctuation.definition.string.begin.elixir","\""], + ["string.quoted.double.elixir","Juhu Kinners!"], + ["punctuation.definition.string.end.elixir","\""] +],[ + "start", + ["text"," "], + ["keyword.control.elixir","end"] +],[ + "start", + ["text"," "], + ["punctuation.definition.comment.elixir","#"], + ["comment.line.number-sign.elixir"," A private function"] +],[ + "start", + ["text"," "], + ["keyword.control.elixir","defp"], + ["text"," priv "], + ["keyword.control.elixir","do"] +],[ + "punctuation.definition.string.begin.elixir7", + ["text"," is_regex "], + ["punctuation.definition.string.begin.elixir","~r\"\"\""] +],[ + "punctuation.definition.string.begin.elixir7", + ["string.quoted.double.heredoc.elixir"," This is a regex"] +],[ + "punctuation.definition.string.begin.elixir7", + ["string.quoted.double.heredoc.elixir"," spanning several"] +],[ + "punctuation.definition.string.begin.elixir7", + ["string.quoted.double.heredoc.elixir"," lines."] +],[ + "start", + ["punctuation.definition.string.end.elixir"," \"\"\""] +],[ + "start", + ["text"," x "], + ["keyword.operator.assignment.elixir","="], + ["text"," elem"], + ["punctuation.section.function.elixir","("], + ["punctuation.section.scope.elixir","{"], + ["text"," "], + ["punctuation.definition.constant.elixir",":"], + ["constant.other.symbol.elixir","a"], + ["punctuation.separator.object.elixir",","], + ["text"," "], + ["punctuation.definition.constant.elixir",":"], + ["constant.other.symbol.elixir","b"], + ["punctuation.separator.object.elixir",","], + ["text"," "], + ["punctuation.definition.constant.elixir",":"], + ["constant.other.symbol.elixir","c"], + ["text"," "], + ["punctuation.section.scope.elixir","}"], + ["punctuation.separator.object.elixir",","], + ["text"," "], + ["constant.numeric.elixir","0"], + ["punctuation.section.function.elixir",")"], + ["text"," "], + ["punctuation.definition.comment.elixir","#"], + ["comment.line.number-sign.elixir","=> :a"] +],[ + "start", + ["text"," "], + ["keyword.control.elixir","end"] +],[ + "start", + ["keyword.control.elixir","end"] +],[ + "start" +],[ + "start", + ["text","test_fun "], + ["keyword.operator.assignment.elixir","="], + ["text"," "], + ["keyword.control.elixir","fn"], + ["punctuation.section.function.elixir","("], + ["text","x"], + ["punctuation.section.function.elixir",")"], + ["text"," "], + ["keyword.operator.arithmetic.elixir","-"], + ["keyword.operator.comparison.elixir",">"] +],[ + "start", + ["text"," "], + ["keyword.control.elixir","cond"], + ["text"," "], + ["keyword.control.elixir","do"] +],[ + "start", + ["text"," x "], + ["keyword.operator.comparison.elixir",">"], + ["text"," "], + ["constant.numeric.elixir","10"], + ["text"," "], + ["keyword.operator.arithmetic.elixir","-"], + ["keyword.operator.comparison.elixir",">"] +],[ + "start", + ["text"," "], + ["punctuation.definition.constant.elixir",":"], + ["constant.other.symbol.elixir","greater_than_ten"] +],[ + "start", + ["text"," "], + ["constant.language.elixir","true"], + ["text"," "], + ["keyword.operator.arithmetic.elixir","-"], + ["keyword.operator.comparison.elixir",">"] +],[ + "start", + ["text"," "], + ["punctuation.definition.constant.elixir",":"], + ["constant.other.symbol.elixir","maybe_ten"] +],[ + "start", + ["text"," "], + ["keyword.control.elixir","end"] +],[ + "start", + ["keyword.control.elixir","end"] +]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_handlebars.json b/lib/ace/mode/_test/tokens_handlebars.json index ef8cb82a..1ec79139 100644 --- a/lib/ace/mode/_test/tokens_handlebars.json +++ b/lib/ace/mode/_test/tokens_handlebars.json @@ -59,9 +59,9 @@ ["meta.tag.punctuation.tag-open.xml","<"], ["meta.tag.tag-name.xml","div"], ["meta.tag.punctuation.tag-close.xml",">"], - ["storage.type.start","{{"], + ["support.function","{{{"], ["variable.parameter","body"], - ["storage.type.end","}}"], + ["support.function","}}}"], ["meta.tag.punctuation.end-tag-open.xml",""] diff --git a/lib/ace/mode/handlebars.js b/lib/ace/mode/handlebars.js index 38af7e5c..3f2e7179 100644 --- a/lib/ace/mode/handlebars.js +++ b/lib/ace/mode/handlebars.js @@ -21,7 +21,7 @@ var Mode = function() { oop.inherits(Mode, HtmlMode); (function() { - + this.blockComment = {start: "{!--", end: "--}"}; this.$id = "ace/mode/handlebars"; }).call(Mode.prototype); diff --git a/lib/ace/mode/handlebars_highlight_rules.js b/lib/ace/mode/handlebars_highlight_rules.js index c264afc1..f91a48ec 100644 --- a/lib/ace/mode/handlebars_highlight_rules.js +++ b/lib/ace/mode/handlebars_highlight_rules.js @@ -15,7 +15,7 @@ var HandlebarsHighlightRules = function() { var hbs = { regex : "(?={{)", push : "handlebars" - } + }; for (var key in this.$rules) { this.$rules[key].unshift(hbs); } @@ -40,22 +40,22 @@ var HandlebarsHighlightRules = function() { defaultToken : "comment" }] }, { - token : "storage.type.start", // begin section - regex : "{{[#\\^/&]?", + token : "support.function", // unescaped variable + regex : "{{{", push : [{ - token : "storage.type.end", - regex : "}}", + token : "support.function", + regex : "}}}", next : pop2 }, { token : "variable.parameter", regex : "[a-zA-Z_$][a-zA-Z0-9_$]*" }] }, { - token : "support.function", // unescaped variable - regex : "{{{", + token : "storage.type.start", // begin section + regex : "{{[#\\^/&]?", push : [{ - token : "support.function", - regex : "}}}", + token : "storage.type.end", + regex : "}}", next : pop2 }, { token : "variable.parameter", diff --git a/lib/ace/snippets/elixir.js b/lib/ace/snippets/elixir.js new file mode 100644 index 00000000..359d9103 --- /dev/null +++ b/lib/ace/snippets/elixir.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./.snippets"); +exports.scope = ""; + +}); diff --git a/lib/ace/snippets/elixir.snippets b/lib/ace/snippets/elixir.snippets new file mode 100644 index 00000000..e69de29b From a4d831f47410e62dd2183054170a6d054f4c5380 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 8 Nov 2014 20:56:18 +0400 Subject: [PATCH 035/315] add more users --- doc/site/images/lws-logo.png | Bin 17695 -> 0 bytes index.html | 145 +++++++++++++++++++++++++++++------ 2 files changed, 120 insertions(+), 25 deletions(-) delete mode 100644 doc/site/images/lws-logo.png diff --git a/doc/site/images/lws-logo.png b/doc/site/images/lws-logo.png deleted file mode 100644 index 402b332cc7b95cb778809ef2bf8f4cebbed6d8f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17695 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 ePvQsn`2PW~6(s>*BWVx-0000RStudio
  • - - Application Craft + + Zed
  • - - StackEdit + + Tedit
  • @@ -796,8 +795,9 @@ if (match) { Plunker
  • - - Zed + + Application Craft
  • Ideone.com
  • - - Pixie +
    + + Lively Web
  • Evaluzio
  • - +
    CodeHelper
  • @@ -949,15 +954,13 @@ if (match) { Slim Text
  • - Decor
  • - - Divshot + + Papeeria
  • - + @@ -96,6 +96,7 @@ diff --git a/lib/ace/keyboard/vim2.js b/lib/ace/keyboard/vim2.js new file mode 100644 index 00000000..27f18c6e --- /dev/null +++ b/lib/ace/keyboard/vim2.js @@ -0,0 +1,4841 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +/** + * Supported keybindings: + * + * Motion: + * h, j, k, l + * gj, gk + * e, E, w, W, b, B, ge, gE + * f, F, t, T + * $, ^, 0, -, +, _ + * gg, G + * % + * ', ` + * + * Operator: + * d, y, c + * dd, yy, cc + * g~, g~g~ + * >, <, >>, << + * + * Operator-Motion: + * x, X, D, Y, C, ~ + * + * Action: + * a, i, s, A, I, S, o, O + * zz, z., z, zt, zb, z- + * J + * u, Ctrl-r + * m + * r + * + * Modes: + * ESC - leave insert mode, visual mode, and clear input state. + * Ctrl-[, Ctrl-c - same as ESC. + * + * Registers: unnamed, -, a-z, A-Z, 0-9 + * (Does not respect the special case for number registers when delete + * operator is made with these commands: %, (, ), , /, ?, n, N, {, } ) + * TODO: Implement the remaining registers. + * Marks: a-z, A-Z, and 0-9 + * TODO: Implement the remaining special marks. They have more complex + * behavior. + * + * Events: + * 'vim-mode-change' - raised on the editor anytime the current mode changes, + * Event object: {mode: "visual", subMode: "linewise"} + * + * Code structure: + * 1. Default keymap + * 2. Variable declarations and short basic helpers + * 3. Instance (External API) implementation + * 4. Internal state tracking objects (input state, counter) implementation + * and instanstiation + * 5. Key handler (the main command dispatcher) implementation + * 6. Motion, operator, and action implementations + * 7. Helper functions for the key handler, motions, operators, and actions + * 8. Set up Vim to work as a keymap for CodeMirror. + */ + +define(function(require, exports, module) { + 'use strict'; + + var defaultKeymap = [ + // Key to key mapping. This goes first to make it possible to override + // existing mappings. + { keys: '', type: 'keyToKey', toKeys: 'h' }, + { keys: '', type: 'keyToKey', toKeys: 'l' }, + { keys: '', type: 'keyToKey', toKeys: 'k' }, + { keys: '', type: 'keyToKey', toKeys: 'j' }, + { keys: '', type: 'keyToKey', toKeys: 'l' }, + { keys: '', type: 'keyToKey', toKeys: 'h' }, + { keys: '', type: 'keyToKey', toKeys: 'W' }, + { keys: '', type: 'keyToKey', toKeys: 'B' }, + { keys: '', type: 'keyToKey', toKeys: 'w' }, + { keys: '', type: 'keyToKey', toKeys: 'b' }, + { keys: '', type: 'keyToKey', toKeys: 'j' }, + { keys: '', type: 'keyToKey', toKeys: 'k' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, + { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, + { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' }, + { keys: 's', type: 'keyToKey', toKeys: 'xi', context: 'visual'}, + { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' }, + { keys: 'S', type: 'keyToKey', toKeys: 'dcc', context: 'visual' }, + { keys: '', type: 'keyToKey', toKeys: '0' }, + { keys: '', type: 'keyToKey', toKeys: '$' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' }, + // Motions + { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }}, + { keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true }}, + { keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true }}, + { keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true }}, + { keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true }}, + { keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false }}, + { keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false }}, + { keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true }}, + { keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true }}, + { keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }}, + { keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }}, + { keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true }}, + { keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true }}, + { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }}, + { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }}, + { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }}, + { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }}, + { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }}, + { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }}, + { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }}, + { keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }}, + { keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }}, + { keys: '0', type: 'motion', motion: 'moveToStartOfLine' }, + { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true }}, + { keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar:true }}, + { keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }}, + { keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true }}, + { keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true }}, + { keys: 'f', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true , inclusive: true }}, + { keys: 'F', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false }}, + { keys: 't', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true }}, + { keys: 'T', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false }}, + { keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true }}, + { keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false }}, + { keys: '\'', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true, linewise: true}}, + { keys: '`', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true}}, + { keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } }, + { keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } }, + { keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } }, + { keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } }, + // the next two aren't motions but must come before more general motion declarations + { keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}}, + { keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}}, + { keys: ']', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true}}, + { keys: '[', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true}}, + { keys: '|', type: 'motion', motion: 'moveToColumn'}, + { keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context:'visual'}, + { keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'}, + // Operators + { keys: 'd', type: 'operator', operator: 'delete' }, + { keys: 'y', type: 'operator', operator: 'yank' }, + { keys: 'c', type: 'operator', operator: 'change' }, + { keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true }}, + { keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false }}, + { keys: 'g~', type: 'operator', operator: 'changeCase' }, + { keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, isEdit: true }, + { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true }, + { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }}, + { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }}, + // Operator-Motion dual commands + { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }}, + { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }}, + { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, operatorMotionArgs: { visualLine: true }}, + { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, operatorMotionArgs: { visualLine: true }}, + { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, operatorMotionArgs: { visualLine: true }}, + { keys: '~', type: 'operatorMotion', operator: 'changeCase', operatorArgs: { shouldMoveCursor: true }, motion: 'moveByCharacters', motionArgs: { forward: true }}, + { keys: '', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' }, + // Actions + { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }}, + { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }}, + { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }}, + { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }}, + { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' }, + { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, + { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, + { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' }, + { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank' }}, + { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' }, + { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, + { keys: 'v', type: 'action', action: 'toggleVisualMode' }, + { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }}, + { keys: '', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, + { keys: 'gv', type: 'action', action: 'reselectLastSelection' }, + { keys: 'J', type: 'action', action: 'joinLines', isEdit: true }, + { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }}, + { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }}, + { keys: 'r', type: 'action', action: 'replace', isEdit: true }, + { keys: '@', type: 'action', action: 'replayMacro' }, + { keys: 'q', type: 'action', action: 'enterMacroRecordMode' }, + // Handle Replace-mode as a special case of insert mode. + { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }}, + { keys: 'u', type: 'action', action: 'undo', context: 'normal' }, + { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true }, + { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true }, + { keys: '', type: 'action', action: 'redo' }, + { keys: 'm', type: 'action', action: 'setMark' }, + { keys: '"', type: 'action', action: 'setRegister' }, + { keys: 'zz', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }}, + { keys: 'z.', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: 'zt', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }}, + { keys: 'z', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: 'z-', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }}, + { keys: 'zb', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: '.', type: 'action', action: 'repeatLastEdit' }, + { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}}, + { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}}, + // Text object motions + { keys: 'a', type: 'motion', motion: 'textObjectManipulation' }, + { keys: 'i', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }}, + // Search + { keys: '/', type: 'search', searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }}, + { keys: '?', type: 'search', searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }}, + { keys: '*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, + { keys: '#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, + { keys: 'g*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }}, + { keys: 'g#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }}, + // Ex command + { keys: ':', type: 'ex' } + ]; + + var Pos = CodeMirror.Pos; + + var modifierCodes = [16, 17, 18, 91]; + var specialKey = {Enter:'CR',Backspace:'BS',Delete:'Del'}; + var mac = /Mac/.test(navigator.platform); + var Vim = function() { return vimApi; } //{ + function lookupKey(e) { + var keyCode = e.keyCode; + if (modifierCodes.indexOf(keyCode) != -1) { return; } + var hasModifier = e.ctrlKey || e.metaKey; + var key = CodeMirror.keyNames[keyCode]; + key = specialKey[key] || key; + var name = ''; + if (e.ctrlKey) { name += 'C-'; } + if (e.altKey) { name += 'A-'; } + if (mac && e.metaKey || (!hasModifier && e.shiftKey) && key.length < 2) { + // Shift key bindings can only specified for special characters. + return; + } else if (e.shiftKey && !/^[A-Za-z]$/.test(key)) { + name += 'S-'; + } + if (key.length == 1) { key = key.toLowerCase(); } + name += key; + if (name.length > 1) { name = '<' + name + '>'; } + return name; + } + // Keys with modifiers are handled using keydown due to limitations of + // keypress event. + function handleKeyDown(cm, e) { + var name = lookupKey(e); + if (!name) { return; } + + CodeMirror.signal(cm, 'vim-keypress', name); + if (CodeMirror.Vim.handleKey(cm, name, 'user')) { + CodeMirror.e_stop(e); + } + } + // Keys without modifiers are handled using keypress to work best with + // non-standard keyboard layouts. + function handleKeyPress(cm, e) { + var code = e.charCode || e.keyCode; + if (e.ctrlKey || e.metaKey || e.altKey || + e.shiftKey && code < 32) { return; } + var name = String.fromCharCode(code); + + CodeMirror.signal(cm, 'vim-keypress', name); + if (CodeMirror.Vim.handleKey(cm, name, 'user')) { + CodeMirror.e_stop(e); + } + } + + function enterVimMode(cm) { + cm.setOption('disableInput', true); + cm.setOption('showCursorWhenSelecting', false); + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + cm.on('cursorActivity', onCursorActivity); + maybeInitVimState(cm); + CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); + cm.on('keypress', handleKeyPress); + cm.on('keydown', handleKeyDown); + CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); + } + + function leaveVimMode(cm) { + cm.setOption('disableInput', false); + cm.off('cursorActivity', onCursorActivity); + CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); + cm.state.vim = null; + cm.off('keypress', handleKeyPress); + cm.off('keydown', handleKeyDown); + } + + function detachVimMap(cm, next) { + if (this == CodeMirror.keyMap.vim) + CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor"); + + if (!next || next.attach != attachVimMap) + leaveVimMode(cm, false); + } + function attachVimMap(cm, prev) { + if (this == CodeMirror.keyMap.vim) + CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); + + if (!prev || prev.attach != attachVimMap) + enterVimMode(cm); + } + + // Deprecated, simply setting the keymap works again. + CodeMirror.defineOption('vimMode', false, function(cm, val, prev) { + if (val && cm.getOption("keyMap") != "vim") + cm.setOption("keyMap", "vim"); + else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap"))) + cm.setOption("keyMap", "default"); + }); + function getOnPasteFn(cm) { + var vim = cm.state.vim; + if (!vim.onPasteFn) { + vim.onPasteFn = function() { + if (!vim.insertMode) { + cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); + actions.enterInsertMode(cm, {}, vim); + } + }; + } + return vim.onPasteFn; + } + + var numberRegex = /[\d]/; + var wordRegexp = [(/\w/), (/[^\w\s]/)], bigWordRegexp = [(/\S/)]; + function makeKeyRange(start, size) { + var keys = []; + for (var i = start; i < start + size; i++) { + keys.push(String.fromCharCode(i)); + } + return keys; + } + var upperCaseAlphabet = makeKeyRange(65, 26); + var lowerCaseAlphabet = makeKeyRange(97, 26); + var numbers = makeKeyRange(48, 10); + var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']); + var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']); + + function isLine(cm, line) { + return line >= cm.firstLine() && line <= cm.lastLine(); + } + function isLowerCase(k) { + return (/^[a-z]$/).test(k); + } + function isMatchableSymbol(k) { + return '()[]{}'.indexOf(k) != -1; + } + function isNumber(k) { + return numberRegex.test(k); + } + function isUpperCase(k) { + return (/^[A-Z]$/).test(k); + } + function isWhiteSpaceString(k) { + return (/^\s*$/).test(k); + } + function inArray(val, arr) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] == val) { + return true; + } + } + return false; + } + + var options = {}; + function defineOption(name, defaultValue, type) { + if (defaultValue === undefined) { throw Error('defaultValue is required'); } + if (!type) { type = 'string'; } + options[name] = { + type: type, + defaultValue: defaultValue + }; + setOption(name, defaultValue); + } + + function setOption(name, value) { + var option = options[name]; + if (!option) { + throw Error('Unknown option: ' + name); + } + if (option.type == 'boolean') { + if (value && value !== true) { + throw Error('Invalid argument: ' + name + '=' + value); + } else if (value !== false) { + // Boolean options are set to true if value is not defined. + value = true; + } + } + option.value = option.type == 'boolean' ? !!value : value; + } + + function getOption(name) { + var option = options[name]; + if (!option) { + throw Error('Unknown option: ' + name); + } + return option.value; + } + + var createCircularJumpList = function() { + var size = 100; + var pointer = -1; + var head = 0; + var tail = 0; + var buffer = new Array(size); + function add(cm, oldCur, newCur) { + var current = pointer % size; + var curMark = buffer[current]; + function useNextSlot(cursor) { + var next = ++pointer % size; + var trashMark = buffer[next]; + if (trashMark) { + trashMark.clear(); + } + buffer[next] = cm.setBookmark(cursor); + } + if (curMark) { + var markPos = curMark.find(); + // avoid recording redundant cursor position + if (markPos && !cursorEqual(markPos, oldCur)) { + useNextSlot(oldCur); + } + } else { + useNextSlot(oldCur); + } + useNextSlot(newCur); + head = pointer; + tail = pointer - size + 1; + if (tail < 0) { + tail = 0; + } + } + function move(cm, offset) { + pointer += offset; + if (pointer > head) { + pointer = head; + } else if (pointer < tail) { + pointer = tail; + } + var mark = buffer[(size + pointer) % size]; + // skip marks that are temporarily removed from text buffer + if (mark && !mark.find()) { + var inc = offset > 0 ? 1 : -1; + var newCur; + var oldCur = cm.getCursor(); + do { + pointer += inc; + mark = buffer[(size + pointer) % size]; + // skip marks that are the same as current position + if (mark && + (newCur = mark.find()) && + !cursorEqual(oldCur, newCur)) { + break; + } + } while (pointer < head && pointer > tail); + } + return mark; + } + return { + cachedCursor: undefined, //used for # and * jumps + add: add, + move: move + }; + }; + + // Returns an object to track the changes associated insert mode. It + // clones the object that is passed in, or creates an empty object one if + // none is provided. + var createInsertModeChanges = function(c) { + if (c) { + // Copy construction + return { + changes: c.changes, + expectCursorActivityForChange: c.expectCursorActivityForChange + }; + } + return { + // Change list + changes: [], + // Set to true on change, false on cursorActivity. + expectCursorActivityForChange: false + }; + }; + + function MacroModeState() { + this.latestRegister = undefined; + this.isPlaying = false; + this.isRecording = false; + this.replaySearchQueries = []; + this.onRecordingDone = undefined; + this.lastInsertModeChanges = createInsertModeChanges(); + } + MacroModeState.prototype = { + exitMacroRecordMode: function() { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.onRecordingDone) { + macroModeState.onRecordingDone(); // close dialog + } + macroModeState.onRecordingDone = undefined; + macroModeState.isRecording = false; + }, + enterMacroRecordMode: function(cm, registerName) { + var register = + vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.clear(); + this.latestRegister = registerName; + if (cm.openDialog) { + this.onRecordingDone = cm.openDialog( + '(recording)['+registerName+']', null, {bottom:true}); + } + this.isRecording = true; + } + } + }; + + function maybeInitVimState(cm) { + if (!cm.state.vim) { + // Store instance state in the CodeMirror object. + cm.state.vim = { + inputState: new InputState(), + // Vim's input state that triggered the last edit, used to repeat + // motions and operators with '.'. + lastEditInputState: undefined, + // Vim's action command before the last edit, used to repeat actions + // with '.' and insert mode repeat. + lastEditActionCommand: undefined, + // When using jk for navigation, if you move from a longer line to a + // shorter line, the cursor may clip to the end of the shorter line. + // If j is pressed again and cursor goes to the next line, the + // cursor should go back to its horizontal position on the longer + // line if it can. This is to keep track of the horizontal position. + lastHPos: -1, + // Doing the same with screen-position for gj/gk + lastHSPos: -1, + // The last motion command run. Cleared if a non-motion command gets + // executed in between. + lastMotion: null, + marks: {}, + // Mark for rendering fake cursor for visual mode. + fakeCursor: null, + insertMode: false, + // Repeat count for changes made in insert mode, triggered by key + // sequences like 3,i. Only exists when insertMode is true. + insertModeRepeat: undefined, + visualMode: false, + // If we are in visual line mode. No effect if visualMode is false. + visualLine: false, + visualBlock: false, + lastSelection: null, + lastPastedText: null + }; + } + return cm.state.vim; + } + var vimGlobalState; + function resetVimGlobalState() { + vimGlobalState = { + // The current search query. + searchQuery: null, + // Whether we are searching backwards. + searchIsReversed: false, + // Replace part of the last substituted pattern + lastSubstituteReplacePart: undefined, + jumpList: createCircularJumpList(), + macroModeState: new MacroModeState, + // Recording latest f, t, F or T motion command. + lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''}, + registerController: new RegisterController({}), + // search history buffer + searchHistoryController: new HistoryController({}), + // ex Command history buffer + exCommandHistoryController : new HistoryController({}) + }; + for (var optionName in options) { + var option = options[optionName]; + option.value = option.defaultValue; + } + } + + var lastInsertModeKeyTimer; + var vimApi= { + buildKeyMap: function() { + // TODO: Convert keymap into dictionary format for fast lookup. + }, + // Testing hook, though it might be useful to expose the register + // controller anyways. + getRegisterController: function() { + return vimGlobalState.registerController; + }, + // Testing hook. + resetVimGlobalState_: resetVimGlobalState, + + // Testing hook. + getVimGlobalState_: function() { + return vimGlobalState; + }, + + // Testing hook. + maybeInitVimState_: maybeInitVimState, + + InsertModeKey: InsertModeKey, + map: function(lhs, rhs, ctx) { + // Add user defined key bindings. + exCommandDispatcher.map(lhs, rhs, ctx); + }, + setOption: setOption, + getOption: getOption, + defineOption: defineOption, + defineEx: function(name, prefix, func){ + if (name.indexOf(prefix) !== 0) { + throw new Error('(Vim.defineEx) "'+prefix+'" is not a prefix of "'+name+'", command not registered'); + } + exCommands[name]=func; + exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'}; + }, + // This is the outermost function called by CodeMirror, after keys have + // been mapped to their Vim equivalents. + handleKey: function(cm, key, origin) { + var vim = maybeInitVimState(cm); + function handleMacroRecording() { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isRecording) { + if (key == 'q') { + macroModeState.exitMacroRecordMode(); + clearInputState(cm); + return true; + } + if (origin != 'mapping') { + logKey(macroModeState, key); + } + } + } + function handleEsc() { + if (key == '') { + // Clear input state and get back to normal mode. + clearInputState(cm); + if (vim.visualMode) { + exitVisualMode(cm); + } else if (vim.insertMode) { + exitInsertMode(cm); + } + return true; + } + } + function doKeyToKey(keys) { + // TODO: prevent infinite recursion. + var match; + while (keys) { + // Pull off one command key, which is either a single character + // or a special sequence wrapped in '<' and '>', e.g. ''. + match = (/<\w+-.+?>|<\w+>|./).exec(keys); + key = match[0]; + keys = keys.substring(match.index + key.length); + CodeMirror.Vim.handleKey(cm, key, 'mapping'); + } + } + + function handleKeyInsertMode() { + if (handleEsc()) { return true; } + var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; + var keysAreChars = key.length == 1; + var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); + // Need to check all key substrings in insert mode. + while (keys.length > 1 && match.type != 'full') { + var keys = vim.inputState.keyBuffer = keys.slice(1); + var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); + if (thisMatch.type != 'none') { match = thisMatch; } + } + if (match.type == 'none') { clearInputState(cm); return false; } + else if (match.type == 'partial') { + if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } + lastInsertModeKeyTimer = window.setTimeout( + function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } }, + getOption('insertModeEscKeysTimeout')); + return !keysAreChars; + } + + if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } + if (keysAreChars) { + var here = cm.getCursor(); + cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input'); + } + clearInputState(cm); + var command = match.command; + if (command.type == 'keyToKey') { + doKeyToKey(command.toKeys); + } else { + commandDispatcher.processCommand(cm, vim, command); + } + return true; + } + + function handleKeyNonInsertMode() { + if (handleMacroRecording() || handleEsc()) { return true; }; + + var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; + if (/^[1-9]\d*$/.test(keys)) { return true; } + + var keysMatcher = /^(\d*)(.*)$/.exec(keys); + if (!keysMatcher) { clearInputState(cm); return false; } + var context = vim.visualMode ? 'visual' : + 'normal'; + var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context); + if (match.type == 'none') { clearInputState(cm); return false; } + else if (match.type == 'partial') { return true; } + + vim.inputState.keyBuffer = ''; + var command = match.command; + var keysMatcher = /^(\d*)(.*)$/.exec(keys); + if (keysMatcher[1] && keysMatcher[1] != '0') { + vim.inputState.pushRepeatDigit(keysMatcher[1]); + } + if (command.type == 'keyToKey') { + doKeyToKey(command.toKeys); + } else { + commandDispatcher.processCommand(cm, vim, command); + } + return true; + } + + return cm.operation(function() { + cm.curOp.isVimOp = true; + try { + if (vim.insertMode) { return handleKeyInsertMode(); } + else { return handleKeyNonInsertMode(); } + } catch (e) { + // clear VIM state in case it's in a bad state. + cm.state.vim = undefined; + throw e; + } + }); + }, + handleEx: function(cm, input) { + exCommandDispatcher.processCommand(cm, input); + } + }; + + // Represents the current input state. + function InputState() { + this.prefixRepeat = []; + this.motionRepeat = []; + + this.operator = null; + this.operatorArgs = null; + this.motion = null; + this.motionArgs = null; + this.keyBuffer = []; // For matching multi-key commands. + this.registerName = null; // Defaults to the unnamed register. + } + InputState.prototype.pushRepeatDigit = function(n) { + if (!this.operator) { + this.prefixRepeat = this.prefixRepeat.concat(n); + } else { + this.motionRepeat = this.motionRepeat.concat(n); + } + }; + InputState.prototype.getRepeat = function() { + var repeat = 0; + if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) { + repeat = 1; + if (this.prefixRepeat.length > 0) { + repeat *= parseInt(this.prefixRepeat.join(''), 10); + } + if (this.motionRepeat.length > 0) { + repeat *= parseInt(this.motionRepeat.join(''), 10); + } + } + return repeat; + }; + + function clearInputState(cm, reason) { + cm.state.vim.inputState = new InputState(); + CodeMirror.signal(cm, 'vim-command-done', reason); + } + + /* + * Register stores information about copy and paste registers. Besides + * text, a register must store whether it is linewise (i.e., when it is + * pasted, should it insert itself into a new line, or should the text be + * inserted at the cursor position.) + */ + function Register(text, linewise, blockwise) { + this.clear(); + this.keyBuffer = [text || '']; + this.insertModeChanges = []; + this.searchQueries = []; + this.linewise = !!linewise; + this.blockwise = !!blockwise; + } + Register.prototype = { + setText: function(text, linewise, blockwise) { + this.keyBuffer = [text || '']; + this.linewise = !!linewise; + this.blockwise = !!blockwise; + }, + pushText: function(text, linewise) { + // if this register has ever been set to linewise, use linewise. + if (linewise) { + if (!this.linewise) { + this.keyBuffer.push('\n'); + } + this.linewise = true; + } + this.keyBuffer.push(text); + }, + pushInsertModeChanges: function(changes) { + this.insertModeChanges.push(createInsertModeChanges(changes)); + }, + pushSearchQuery: function(query) { + this.searchQueries.push(query); + }, + clear: function() { + this.keyBuffer = []; + this.insertModeChanges = []; + this.searchQueries = []; + this.linewise = false; + }, + toString: function() { + return this.keyBuffer.join(''); + } + }; + + /* + * vim registers allow you to keep many independent copy and paste buffers. + * See http://usevim.com/2012/04/13/registers/ for an introduction. + * + * RegisterController keeps the state of all the registers. An initial + * state may be passed in. The unnamed register '"' will always be + * overridden. + */ + function RegisterController(registers) { + this.registers = registers; + this.unnamedRegister = registers['"'] = new Register(); + registers['.'] = new Register(); + registers[':'] = new Register(); + registers['/'] = new Register(); + } + RegisterController.prototype = { + pushText: function(registerName, operator, text, linewise, blockwise) { + if (linewise && text.charAt(0) == '\n') { + text = text.slice(1) + '\n'; + } + if (linewise && text.charAt(text.length - 1) !== '\n'){ + text += '\n'; + } + // Lowercase and uppercase registers refer to the same register. + // Uppercase just means append. + var register = this.isValidRegister(registerName) ? + this.getRegister(registerName) : null; + // if no register/an invalid register was specified, things go to the + // default registers + if (!register) { + switch (operator) { + case 'yank': + // The 0 register contains the text from the most recent yank. + this.registers['0'] = new Register(text, linewise, blockwise); + break; + case 'delete': + case 'change': + if (text.indexOf('\n') == -1) { + // Delete less than 1 line. Update the small delete register. + this.registers['-'] = new Register(text, linewise); + } else { + // Shift down the contents of the numbered registers and put the + // deleted text into register 1. + this.shiftNumericRegisters_(); + this.registers['1'] = new Register(text, linewise); + } + break; + } + // Make sure the unnamed register is set to what just happened + this.unnamedRegister.setText(text, linewise, blockwise); + return; + } + + // If we've gotten to this point, we've actually specified a register + var append = isUpperCase(registerName); + if (append) { + register.pushText(text, linewise); + } else { + register.setText(text, linewise, blockwise); + } + // The unnamed register always has the same value as the last used + // register. + this.unnamedRegister.setText(register.toString(), linewise); + }, + // Gets the register named @name. If one of @name doesn't already exist, + // create it. If @name is invalid, return the unnamedRegister. + getRegister: function(name) { + if (!this.isValidRegister(name)) { + return this.unnamedRegister; + } + name = name.toLowerCase(); + if (!this.registers[name]) { + this.registers[name] = new Register(); + } + return this.registers[name]; + }, + isValidRegister: function(name) { + return name && inArray(name, validRegisters); + }, + shiftNumericRegisters_: function() { + for (var i = 9; i >= 2; i--) { + this.registers[i] = this.getRegister('' + (i - 1)); + } + } + }; + function HistoryController() { + this.historyBuffer = []; + this.iterator; + this.initialPrefix = null; + } + HistoryController.prototype = { + // the input argument here acts a user entered prefix for a small time + // until we start autocompletion in which case it is the autocompleted. + nextMatch: function (input, up) { + var historyBuffer = this.historyBuffer; + var dir = up ? -1 : 1; + if (this.initialPrefix === null) this.initialPrefix = input; + for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i+= dir) { + var element = historyBuffer[i]; + for (var j = 0; j <= element.length; j++) { + if (this.initialPrefix == element.substring(0, j)) { + this.iterator = i; + return element; + } + } + } + // should return the user input in case we reach the end of buffer. + if (i >= historyBuffer.length) { + this.iterator = historyBuffer.length; + return this.initialPrefix; + } + // return the last autocompleted query or exCommand as it is. + if (i < 0 ) return input; + }, + pushInput: function(input) { + var index = this.historyBuffer.indexOf(input); + if (index > -1) this.historyBuffer.splice(index, 1); + if (input.length) this.historyBuffer.push(input); + }, + reset: function() { + this.initialPrefix = null; + this.iterator = this.historyBuffer.length; + } + }; + var commandDispatcher = { + matchCommand: function(keys, keyMap, inputState, context) { + var matches = commandMatches(keys, keyMap, context, inputState); + if (!matches.full && !matches.partial) { + return {type: 'none'}; + } else if (!matches.full && matches.partial) { + return {type: 'partial'}; + } + + var bestMatch; + for (var i = 0; i < matches.full.length; i++) { + var match = matches.full[i]; + if (!bestMatch) { + bestMatch = match; + } + } + if (bestMatch.keys.slice(-11) == '') { + inputState.selectedCharacter = lastChar(keys); + } + return {type: 'full', command: bestMatch}; + }, + processCommand: function(cm, vim, command) { + vim.inputState.repeatOverride = command.repeatOverride; + switch (command.type) { + case 'motion': + this.processMotion(cm, vim, command); + break; + case 'operator': + this.processOperator(cm, vim, command); + break; + case 'operatorMotion': + this.processOperatorMotion(cm, vim, command); + break; + case 'action': + this.processAction(cm, vim, command); + break; + case 'search': + this.processSearch(cm, vim, command); + clearInputState(cm); + break; + case 'ex': + case 'keyToEx': + this.processEx(cm, vim, command); + clearInputState(cm); + break; + default: + break; + } + }, + processMotion: function(cm, vim, command) { + vim.inputState.motion = command.motion; + vim.inputState.motionArgs = copyArgs(command.motionArgs); + this.evalInput(cm, vim); + }, + processOperator: function(cm, vim, command) { + var inputState = vim.inputState; + if (inputState.operator) { + if (inputState.operator == command.operator) { + // Typing an operator twice like 'dd' makes the operator operate + // linewise + inputState.motion = 'expandToLine'; + inputState.motionArgs = { linewise: true }; + this.evalInput(cm, vim); + return; + } else { + // 2 different operators in a row doesn't make sense. + clearInputState(cm); + } + } + inputState.operator = command.operator; + inputState.operatorArgs = copyArgs(command.operatorArgs); + if (vim.visualMode) { + // Operating on a selection in visual mode. We don't need a motion. + this.evalInput(cm, vim); + } + }, + processOperatorMotion: function(cm, vim, command) { + var visualMode = vim.visualMode; + var operatorMotionArgs = copyArgs(command.operatorMotionArgs); + if (operatorMotionArgs) { + // Operator motions may have special behavior in visual mode. + if (visualMode && operatorMotionArgs.visualLine) { + vim.visualLine = true; + } + } + this.processOperator(cm, vim, command); + if (!visualMode) { + this.processMotion(cm, vim, command); + } + }, + processAction: function(cm, vim, command) { + var inputState = vim.inputState; + var repeat = inputState.getRepeat(); + var repeatIsExplicit = !!repeat; + var actionArgs = copyArgs(command.actionArgs) || {}; + if (inputState.selectedCharacter) { + actionArgs.selectedCharacter = inputState.selectedCharacter; + } + // Actions may or may not have motions and operators. Do these first. + if (command.operator) { + this.processOperator(cm, vim, command); + } + if (command.motion) { + this.processMotion(cm, vim, command); + } + if (command.motion || command.operator) { + this.evalInput(cm, vim); + } + actionArgs.repeat = repeat || 1; + actionArgs.repeatIsExplicit = repeatIsExplicit; + actionArgs.registerName = inputState.registerName; + clearInputState(cm); + vim.lastMotion = null; + if (command.isEdit) { + this.recordLastEdit(vim, inputState, command); + } + actions[command.action](cm, actionArgs, vim); + }, + processSearch: function(cm, vim, command) { + if (!cm.getSearchCursor) { + // Search depends on SearchCursor. + return; + } + var forward = command.searchArgs.forward; + var wholeWordOnly = command.searchArgs.wholeWordOnly; + getSearchState(cm).setReversed(!forward); + var promptPrefix = (forward) ? '/' : '?'; + var originalQuery = getSearchState(cm).getQuery(); + var originalScrollPos = cm.getScrollInfo(); + function handleQuery(query, ignoreCase, smartCase) { + vimGlobalState.searchHistoryController.pushInput(query); + vimGlobalState.searchHistoryController.reset(); + try { + updateSearchQuery(cm, query, ignoreCase, smartCase); + } catch (e) { + showConfirm(cm, 'Invalid regex: ' + query); + return; + } + commandDispatcher.processMotion(cm, vim, { + type: 'motion', + motion: 'findNext', + motionArgs: { forward: true, toJumplist: command.searchArgs.toJumplist } + }); + } + function onPromptClose(query) { + cm.scrollTo(originalScrollPos.left, originalScrollPos.top); + handleQuery(query, true /** ignoreCase */, true /** smartCase */); + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isRecording) { + logSearchQuery(macroModeState, query); + } + } + function onPromptKeyUp(e, query, close) { + var keyName = CodeMirror.keyName(e), up; + if (keyName == 'Up' || keyName == 'Down') { + up = keyName == 'Up' ? true : false; + query = vimGlobalState.searchHistoryController.nextMatch(query, up) || ''; + close(query); + } else { + if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') + vimGlobalState.searchHistoryController.reset(); + } + var parsedQuery; + try { + parsedQuery = updateSearchQuery(cm, query, + true /** ignoreCase */, true /** smartCase */); + } catch (e) { + // Swallow bad regexes for incremental search. + } + if (parsedQuery) { + cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30); + } else { + clearSearchHighlight(cm); + cm.scrollTo(originalScrollPos.left, originalScrollPos.top); + } + } + function onPromptKeyDown(e, query, close) { + var keyName = CodeMirror.keyName(e); + if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') { + vimGlobalState.searchHistoryController.pushInput(query); + vimGlobalState.searchHistoryController.reset(); + updateSearchQuery(cm, originalQuery); + clearSearchHighlight(cm); + cm.scrollTo(originalScrollPos.left, originalScrollPos.top); + CodeMirror.e_stop(e); + close(); + cm.focus(); + } + } + switch (command.searchArgs.querySrc) { + case 'prompt': + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isPlaying) { + var query = macroModeState.replaySearchQueries.shift(); + handleQuery(query, true /** ignoreCase */, false /** smartCase */); + } else { + showPrompt(cm, { + onClose: onPromptClose, + prefix: promptPrefix, + desc: searchPromptDesc, + onKeyUp: onPromptKeyUp, + onKeyDown: onPromptKeyDown + }); + } + break; + case 'wordUnderCursor': + var word = expandWordUnderCursor(cm, false /** inclusive */, + true /** forward */, false /** bigWord */, + true /** noSymbol */); + var isKeyword = true; + if (!word) { + word = expandWordUnderCursor(cm, false /** inclusive */, + true /** forward */, false /** bigWord */, + false /** noSymbol */); + isKeyword = false; + } + if (!word) { + return; + } + var query = cm.getLine(word.start.line).substring(word.start.ch, + word.end.ch); + if (isKeyword && wholeWordOnly) { + query = '\\b' + query + '\\b'; + } else { + query = escapeRegex(query); + } + + // cachedCursor is used to save the old position of the cursor + // when * or # causes vim to seek for the nearest word and shift + // the cursor before entering the motion. + vimGlobalState.jumpList.cachedCursor = cm.getCursor(); + cm.setCursor(word.start); + + handleQuery(query, true /** ignoreCase */, false /** smartCase */); + break; + } + }, + processEx: function(cm, vim, command) { + function onPromptClose(input) { + // Give the prompt some time to close so that if processCommand shows + // an error, the elements don't overlap. + vimGlobalState.exCommandHistoryController.pushInput(input); + vimGlobalState.exCommandHistoryController.reset(); + exCommandDispatcher.processCommand(cm, input); + } + function onPromptKeyDown(e, input, close) { + var keyName = CodeMirror.keyName(e), up; + if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') { + vimGlobalState.exCommandHistoryController.pushInput(input); + vimGlobalState.exCommandHistoryController.reset(); + CodeMirror.e_stop(e); + close(); + cm.focus(); + } + if (keyName == 'Up' || keyName == 'Down') { + up = keyName == 'Up' ? true : false; + input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || ''; + close(input); + } else { + if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') + vimGlobalState.exCommandHistoryController.reset(); + } + } + if (command.type == 'keyToEx') { + // Handle user defined Ex to Ex mappings + exCommandDispatcher.processCommand(cm, command.exArgs.input); + } else { + if (vim.visualMode) { + showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>', + onKeyDown: onPromptKeyDown}); + } else { + showPrompt(cm, { onClose: onPromptClose, prefix: ':', + onKeyDown: onPromptKeyDown}); + } + } + }, + evalInput: function(cm, vim) { + // If the motion comand is set, execute both the operator and motion. + // Otherwise return. + var inputState = vim.inputState; + var motion = inputState.motion; + var motionArgs = inputState.motionArgs || {}; + var operator = inputState.operator; + var operatorArgs = inputState.operatorArgs || {}; + var registerName = inputState.registerName; + var selectionEnd = copyCursor(cm.getCursor('head')); + var selectionStart = copyCursor(cm.getCursor('anchor')); + // The difference between cur and selection cursors are that cur is + // being operated on and ignores that there is a selection. + var curStart = copyCursor(selectionEnd); + var curOriginal = copyCursor(curStart); + var curEnd; + var repeat; + if (operator) { + this.recordLastEdit(vim, inputState); + } + if (inputState.repeatOverride !== undefined) { + // If repeatOverride is specified, that takes precedence over the + // input state's repeat. Used by Ex mode and can be user defined. + repeat = inputState.repeatOverride; + } else { + repeat = inputState.getRepeat(); + } + if (repeat > 0 && motionArgs.explicitRepeat) { + motionArgs.repeatIsExplicit = true; + } else if (motionArgs.noRepeat || + (!motionArgs.explicitRepeat && repeat === 0)) { + repeat = 1; + motionArgs.repeatIsExplicit = false; + } + if (inputState.selectedCharacter) { + // If there is a character input, stick it in all of the arg arrays. + motionArgs.selectedCharacter = operatorArgs.selectedCharacter = + inputState.selectedCharacter; + } + motionArgs.repeat = repeat; + clearInputState(cm); + if (motion) { + var motionResult = motions[motion](cm, motionArgs, vim); + vim.lastMotion = motions[motion]; + if (!motionResult) { + return; + } + if (motionArgs.toJumplist) { + var jumpList = vimGlobalState.jumpList; + // if the current motion is # or *, use cachedCursor + var cachedCursor = jumpList.cachedCursor; + if (cachedCursor) { + recordJumpPosition(cm, cachedCursor, motionResult); + delete jumpList.cachedCursor; + } else { + recordJumpPosition(cm, curOriginal, motionResult); + } + } + if (motionResult instanceof Array) { + curStart = motionResult[0]; + curEnd = motionResult[1]; + } else { + curEnd = motionResult; + } + // TODO: Handle null returns from motion commands better. + if (!curEnd) { + curEnd = Pos(curStart.line, curStart.ch); + } + if (vim.visualMode) { + // Check if the selection crossed over itself. Will need to shift + // the start point if that happened. + // offset is set to -1 or 1 to shift the curEnd + // left or right + var offset = 0; + if (cursorIsBefore(selectionStart, selectionEnd) && + (cursorEqual(selectionStart, curEnd) || + cursorIsBefore(curEnd, selectionStart))) { + // The end of the selection has moved from after the start to + // before the start. We will shift the start right by 1. + selectionStart.ch += 1; + offset = -1; + } else if (cursorIsBefore(selectionEnd, selectionStart) && + (cursorEqual(selectionStart, curEnd) || + cursorIsBefore(selectionStart, curEnd))) { + // The opposite happened. We will shift the start left by 1. + selectionStart.ch -= 1; + offset = 1; + } + // in case of visual Block selectionStart and curEnd + // may not be on the same line, + // Also, In case of v_o this should not happen. + if (!vim.visualBlock && !(motionResult instanceof Array)) { + curEnd.ch += offset; + } + if (vim.lastHPos != Infinity) { + vim.lastHPos = curEnd.ch; + } + selectionEnd = curEnd; + selectionStart = (motionResult instanceof Array) ? curStart : selectionStart; + if (vim.visualLine) { + if (cursorIsBefore(selectionStart, selectionEnd)) { + selectionStart.ch = 0; + + var lastLine = cm.lastLine(); + if (selectionEnd.line > lastLine) { + selectionEnd.line = lastLine; + } + selectionEnd.ch = lineLength(cm, selectionEnd.line); + } else { + selectionEnd.ch = 0; + selectionStart.ch = lineLength(cm, selectionStart.line); + } + } else if (vim.visualBlock) { + // Select a block and + // return the diagonally opposite end. + selectionStart = selectBlock(cm, selectionEnd); + } + if (!vim.visualBlock) { + cm.setSelection(selectionStart, selectionEnd); + } + updateMark(cm, vim, '<', + cursorIsBefore(selectionStart, selectionEnd) ? selectionStart + : selectionEnd); + updateMark(cm, vim, '>', + cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd + : selectionStart); + } else if (!operator) { + curEnd = clipCursorToContent(cm, curEnd); + cm.setCursor(curEnd.line, curEnd.ch); + } + } + + if (operator) { + var inverted = false; + vim.lastMotion = null; + var lastSelection = vim.lastSelection; + operatorArgs.repeat = repeat; // Indent in visual mode needs this. + if (vim.visualMode) { + curStart = selectionStart; + curEnd = selectionEnd; + motionArgs.inclusive = true; + operatorArgs.shouldMoveCursor = false; + } + // Swap start and end if motion was backward. + if (curEnd && cursorIsBefore(curEnd, curStart)) { + var tmp = curStart; + curStart = curEnd; + curEnd = tmp; + inverted = true; + } else if (!curEnd) { + curEnd = copyCursor(curStart); + } + if (motionArgs.inclusive && !vim.visualMode) { + // Move the selection end one to the right to include the last + // character. + curEnd.ch++; + } + if (operatorArgs.selOffset) { + // Replaying a visual mode operation + curEnd.line = curStart.line + operatorArgs.selOffset.line; + if (operatorArgs.selOffset.line) {curEnd.ch = operatorArgs.selOffset.ch; } + else { curEnd.ch = curStart.ch + operatorArgs.selOffset.ch; } + // In case of blockwise visual + if (lastSelection && lastSelection.visualBlock) { + var block = lastSelection.visualBlock; + var width = block.width; + var height = block.height; + curEnd = Pos(curStart.line + height, curStart.ch + width); + // selectBlock creates a 'proper' rectangular block. + // We do not want that in all cases, so we manually set selections. + var selections = []; + for (var i = curStart.line; i < curEnd.line; i++) { + var anchor = Pos(i, curStart.ch); + var head = Pos(i, curEnd.ch); + var range = {anchor: anchor, head: head}; + selections.push(range); + } + cm.setSelections(selections); + var blockSelected = true; + } + } else if (vim.visualMode) { + var selOffset = Pos(); + selOffset.line = curEnd.line - curStart.line; + if (selOffset.line) { selOffset.ch = curEnd.ch; } + else { selOffset.ch = curEnd.ch - curStart.ch; } + operatorArgs.selOffset = selOffset; + } + var linewise = motionArgs.linewise || + (vim.visualMode && vim.visualLine) || + operatorArgs.linewise; + if (linewise) { + // Expand selection to entire line. + expandSelectionToLine(cm, curStart, curEnd); + } else if (motionArgs.forward) { + // Clip to trailing newlines only if the motion goes forward. + clipToLine(cm, curStart, curEnd); + } + operatorArgs.registerName = registerName; + // Keep track of linewise as it affects how paste and change behave. + operatorArgs.linewise = linewise; + if (!vim.visualBlock && !blockSelected) { + cm.setSelection(curStart, curEnd); + } + operators[operator](cm, operatorArgs, vim, curStart, + curEnd, curOriginal); + if (vim.visualMode) { + exitVisualMode(cm); + } + } + }, + recordLastEdit: function(vim, inputState, actionCommand) { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isPlaying) { return; } + vim.lastEditInputState = inputState; + vim.lastEditActionCommand = actionCommand; + macroModeState.lastInsertModeChanges.changes = []; + macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false; + } + }; + + /** + * typedef {Object{line:number,ch:number}} Cursor An object containing the + * position of the cursor. + */ + // All of the functions below return Cursor objects. + var motions = { + moveToTopLine: function(cm, motionArgs) { + var line = getUserVisibleLines(cm).top + motionArgs.repeat -1; + return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); + }, + moveToMiddleLine: function(cm) { + var range = getUserVisibleLines(cm); + var line = Math.floor((range.top + range.bottom) * 0.5); + return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); + }, + moveToBottomLine: function(cm, motionArgs) { + var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1; + return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); + }, + expandToLine: function(cm, motionArgs) { + // Expands forward to end of line, and then to next line if repeat is + // >1. Does not handle backward motion! + var cur = cm.getCursor(); + return Pos(cur.line + motionArgs.repeat - 1, Infinity); + }, + findNext: function(cm, motionArgs) { + var state = getSearchState(cm); + var query = state.getQuery(); + if (!query) { + return; + } + var prev = !motionArgs.forward; + // If search is initiated with ? instead of /, negate direction. + prev = (state.isReversed()) ? !prev : prev; + highlightSearchMatches(cm, query); + return findNext(cm, prev/** prev */, query, motionArgs.repeat); + }, + goToMark: function(cm, motionArgs, vim) { + var mark = vim.marks[motionArgs.selectedCharacter]; + if (mark) { + var pos = mark.find(); + return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos; + } + return null; + }, + moveToOtherHighlightedEnd: function(cm, motionArgs, vim) { + var ranges = cm.listSelections(); + var curEnd = cm.getCursor('head'); + var curStart = ranges[0].anchor; + var curIndex = cursorEqual(ranges[0].head, curEnd) ? ranges.length-1 : 0; + if (motionArgs.sameLine && vim.visualBlock) { + curStart = Pos(curEnd.line, ranges[curIndex].anchor.ch); + curEnd = Pos(ranges[curIndex].head.line, curEnd.ch); + } else { + curStart = ranges[curIndex].anchor; + } + cm.setCursor(curEnd); + return ([curEnd, curStart]); + }, + jumpToMark: function(cm, motionArgs, vim) { + var best = cm.getCursor(); + for (var i = 0; i < motionArgs.repeat; i++) { + var cursor = best; + for (var key in vim.marks) { + if (!isLowerCase(key)) { + continue; + } + var mark = vim.marks[key].find(); + var isWrongDirection = (motionArgs.forward) ? + cursorIsBefore(mark, cursor) : cursorIsBefore(cursor, mark); + + if (isWrongDirection) { + continue; + } + if (motionArgs.linewise && (mark.line == cursor.line)) { + continue; + } + + var equal = cursorEqual(cursor, best); + var between = (motionArgs.forward) ? + cursorIsBetween(cursor, mark, best) : + cursorIsBetween(best, mark, cursor); + + if (equal || between) { + best = mark; + } + } + } + + if (motionArgs.linewise) { + // Vim places the cursor on the first non-whitespace character of + // the line if there is one, else it places the cursor at the end + // of the line, regardless of whether a mark was found. + best = Pos(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line))); + } + return best; + }, + moveByCharacters: function(cm, motionArgs) { + var cur = cm.getCursor(); + var repeat = motionArgs.repeat; + var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat; + return Pos(cur.line, ch); + }, + moveByLines: function(cm, motionArgs, vim) { + var cur = cm.getCursor(); + var endCh = cur.ch; + // Depending what our last motion was, we may want to do different + // things. If our last motion was moving vertically, we want to + // preserve the HPos from our last horizontal move. If our last motion + // was going to the end of a line, moving vertically we should go to + // the end of the line, etc. + switch (vim.lastMotion) { + case this.moveByLines: + case this.moveByDisplayLines: + case this.moveByScroll: + case this.moveToColumn: + case this.moveToEol: + endCh = vim.lastHPos; + break; + default: + vim.lastHPos = endCh; + } + var repeat = motionArgs.repeat+(motionArgs.repeatOffset||0); + var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat; + var first = cm.firstLine(); + var last = cm.lastLine(); + // Vim cancels linewise motions that start on an edge and move beyond + // that edge. It does not cancel motions that do not start on an edge. + if ((line < first && cur.line == first) || + (line > last && cur.line == last)) { + return; + } + if (motionArgs.toFirstChar){ + endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line)); + vim.lastHPos = endCh; + } + vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left; + return Pos(line, endCh); + }, + moveByDisplayLines: function(cm, motionArgs, vim) { + var cur = cm.getCursor(); + switch (vim.lastMotion) { + case this.moveByDisplayLines: + case this.moveByScroll: + case this.moveByLines: + case this.moveToColumn: + case this.moveToEol: + break; + default: + vim.lastHSPos = cm.charCoords(cur,'div').left; + } + var repeat = motionArgs.repeat; + var res=cm.findPosV(cur,(motionArgs.forward ? repeat : -repeat),'line',vim.lastHSPos); + if (res.hitSide) { + if (motionArgs.forward) { + var lastCharCoords = cm.charCoords(res, 'div'); + var goalCoords = { top: lastCharCoords.top + 8, left: vim.lastHSPos }; + var res = cm.coordsChar(goalCoords, 'div'); + } else { + var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div'); + resCoords.left = vim.lastHSPos; + res = cm.coordsChar(resCoords, 'div'); + } + } + vim.lastHPos = res.ch; + return res; + }, + moveByPage: function(cm, motionArgs) { + // CodeMirror only exposes functions that move the cursor page down, so + // doing this bad hack to move the cursor and move it back. evalInput + // will move the cursor to where it should be in the end. + var curStart = cm.getCursor(); + var repeat = motionArgs.repeat; + return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page'); + }, + moveByParagraph: function(cm, motionArgs) { + var line = cm.getCursor().line; + var repeat = motionArgs.repeat; + var inc = motionArgs.forward ? 1 : -1; + for (var i = 0; i < repeat; i++) { + if ((!motionArgs.forward && line === cm.firstLine() ) || + (motionArgs.forward && line == cm.lastLine())) { + break; + } + line += inc; + while (line !== cm.firstLine() && line != cm.lastLine() && cm.getLine(line)) { + line += inc; + } + } + return Pos(line, 0); + }, + moveByScroll: function(cm, motionArgs, vim) { + var scrollbox = cm.getScrollInfo(); + var curEnd = null; + var repeat = motionArgs.repeat; + if (!repeat) { + repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight()); + } + var orig = cm.charCoords(cm.getCursor(), 'local'); + motionArgs.repeat = repeat; + var curEnd = motions.moveByDisplayLines(cm, motionArgs, vim); + if (!curEnd) { + return null; + } + var dest = cm.charCoords(curEnd, 'local'); + cm.scrollTo(null, scrollbox.top + dest.top - orig.top); + return curEnd; + }, + moveByWords: function(cm, motionArgs) { + return moveToWord(cm, motionArgs.repeat, !!motionArgs.forward, + !!motionArgs.wordEnd, !!motionArgs.bigWord); + }, + moveTillCharacter: function(cm, motionArgs) { + var repeat = motionArgs.repeat; + var curEnd = moveToCharacter(cm, repeat, motionArgs.forward, + motionArgs.selectedCharacter); + var increment = motionArgs.forward ? -1 : 1; + recordLastCharacterSearch(increment, motionArgs); + if (!curEnd) return null; + curEnd.ch += increment; + return curEnd; + }, + moveToCharacter: function(cm, motionArgs) { + var repeat = motionArgs.repeat; + recordLastCharacterSearch(0, motionArgs); + return moveToCharacter(cm, repeat, motionArgs.forward, + motionArgs.selectedCharacter) || cm.getCursor(); + }, + moveToSymbol: function(cm, motionArgs) { + var repeat = motionArgs.repeat; + return findSymbol(cm, repeat, motionArgs.forward, + motionArgs.selectedCharacter) || cm.getCursor(); + }, + moveToColumn: function(cm, motionArgs, vim) { + var repeat = motionArgs.repeat; + // repeat is equivalent to which column we want to move to! + vim.lastHPos = repeat - 1; + vim.lastHSPos = cm.charCoords(cm.getCursor(),'div').left; + return moveToColumn(cm, repeat); + }, + moveToEol: function(cm, motionArgs, vim) { + var cur = cm.getCursor(); + vim.lastHPos = Infinity; + var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity); + var end=cm.clipPos(retval); + end.ch--; + vim.lastHSPos = cm.charCoords(end,'div').left; + return retval; + }, + moveToFirstNonWhiteSpaceCharacter: function(cm) { + // Go to the start of the line where the text begins, or the end for + // whitespace-only lines + var cursor = cm.getCursor(); + return Pos(cursor.line, + findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))); + }, + moveToMatchedSymbol: function(cm) { + var cursor = cm.getCursor(); + var line = cursor.line; + var ch = cursor.ch; + var lineText = cm.getLine(line); + var symbol; + do { + symbol = lineText.charAt(ch++); + if (symbol && isMatchableSymbol(symbol)) { + var style = cm.getTokenTypeAt(Pos(line, ch)); + if (style !== "string" && style !== "comment") { + break; + } + } + } while (symbol); + if (symbol) { + var matched = cm.findMatchingBracket(Pos(line, ch)); + return matched.to; + } else { + return cursor; + } + }, + moveToStartOfLine: function(cm) { + var cursor = cm.getCursor(); + return Pos(cursor.line, 0); + }, + moveToLineOrEdgeOfDocument: function(cm, motionArgs) { + var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine(); + if (motionArgs.repeatIsExplicit) { + lineNum = motionArgs.repeat - cm.getOption('firstLineNumber'); + } + return Pos(lineNum, + findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))); + }, + textObjectManipulation: function(cm, motionArgs) { + // TODO: lots of possible exceptions that can be thrown here. Try da( + // outside of a () block. + + // TODO: adding <> >< to this map doesn't work, presumably because + // they're operators + var mirroredPairs = {'(': ')', ')': '(', + '{': '}', '}': '{', + '[': ']', ']': '['}; + var selfPaired = {'\'': true, '"': true}; + + var character = motionArgs.selectedCharacter; + // 'b' refers to '()' block. + // 'B' refers to '{}' block. + if (character == 'b') { + character = '('; + } else if (character == 'B') { + character = '{'; + } + + // Inclusive is the difference between a and i + // TODO: Instead of using the additional text object map to perform text + // object operations, merge the map into the defaultKeyMap and use + // motionArgs to define behavior. Define separate entries for 'aw', + // 'iw', 'a[', 'i[', etc. + var inclusive = !motionArgs.textObjectInner; + + var tmp; + if (mirroredPairs[character]) { + tmp = selectCompanionObject(cm, character, inclusive); + } else if (selfPaired[character]) { + tmp = findBeginningAndEnd(cm, character, inclusive); + } else if (character === 'W') { + tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, + true /** bigWord */); + } else if (character === 'w') { + tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, + false /** bigWord */); + } else { + // No text object defined for this, don't move. + return null; + } + + if (!cm.state.vim.visualMode) { + return [tmp.start, tmp.end]; + } else { + return expandSelection(cm, tmp.start, tmp.end); + } + }, + + repeatLastCharacterSearch: function(cm, motionArgs) { + var lastSearch = vimGlobalState.lastChararacterSearch; + var repeat = motionArgs.repeat; + var forward = motionArgs.forward === lastSearch.forward; + var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1); + cm.moveH(-increment, 'char'); + motionArgs.inclusive = forward ? true : false; + var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter); + if (!curEnd) { + cm.moveH(increment, 'char'); + return cm.getCursor(); + } + curEnd.ch += increment; + return curEnd; + } + }; + + var operators = { + change: function(cm, operatorArgs, vim) { + var selections = cm.listSelections(); + var start = selections[0], end = selections[selections.length-1]; + var curStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; + var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; + var text = cm.getSelection(); + var visualBlock = vim.visualBlock; + if (vim.lastSelection && !vim.visualMode) { + visualBlock = vim.lastSelection.visualBlock ? true : visualBlock; + } + var lastInsertModeChanges = vimGlobalState.macroModeState.lastInsertModeChanges; + lastInsertModeChanges.inVisualBlock = visualBlock; + var replacement = new Array(selections.length).join('1').split('1'); + // save the selectionEnd mark + var selectionEnd = vim.marks[">"] && vim.marks[">"].find(); + if (!selectionEnd) { + selectionEnd = cm.getCursor("head"); + } + vimGlobalState.registerController.pushText( + operatorArgs.registerName, 'change', text, + operatorArgs.linewise); + if (operatorArgs.linewise) { + // 'C' in visual block extends the block till eol for all lines + if (visualBlock){ + var startLine = curStart.line; + while (startLine <= curEnd.line) { + var endCh = lineLength(cm, startLine); + var head = Pos(startLine, endCh); + var anchor = Pos(startLine, curStart.ch); + startLine++; + cm.replaceRange('', anchor, head); + } + } else { + // Push the next line back down, if there is a next line. + replacement = '\n'; + if (curEnd.line == curStart.line && curEnd.line == cm.lastLine()) { + replacement = ''; + } + cm.replaceRange(replacement, curStart, curEnd); + cm.indentLine(curStart.line, 'smart'); + // null ch so setCursor moves to end of line. + curStart.ch = null; + cm.setCursor(curStart); + } + } else { + // Exclude trailing whitespace if the range is not all whitespace. + var text = cm.getRange(curStart, curEnd); + if (!isWhiteSpaceString(text)) { + var match = (/\s+$/).exec(text); + if (match) { + curEnd = offsetCursor(curEnd, 0, - match[0].length); + } + } + if (visualBlock) { + cm.replaceSelections(replacement); + } else { + cm.setCursor(curStart); + cm.replaceRange('', curStart, curEnd); + } + } + vim.marks['>'] = cm.setBookmark(selectionEnd); + actions.enterInsertMode(cm, {}, cm.state.vim); + }, + // delete is a javascript keyword. + 'delete': function(cm, operatorArgs, vim) { + var selections = cm.listSelections(); + var start = selections[0], end = selections[selections.length-1]; + var curStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; + var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; + // Save the '>' mark before cm.replaceRange clears it. + var selectionEnd, selectionStart; + var blockwise = vim.visualBlock; + if (vim.visualMode) { + selectionEnd = vim.marks['>'].find(); + selectionStart = vim.marks['<'].find(); + } else if (vim.lastSelection) { + selectionEnd = vim.lastSelection.curStartMark.find(); + selectionStart = vim.lastSelection.curEndMark.find(); + blockwise = vim.lastSelection.visualBlock; + } + var text = cm.getSelection(); + vimGlobalState.registerController.pushText( + operatorArgs.registerName, 'delete', text, + operatorArgs.linewise, blockwise); + var replacement = new Array(selections.length).join('1').split('1'); + // If the ending line is past the last line, inclusive, instead of + // including the trailing \n, include the \n before the starting line + if (operatorArgs.linewise && + curEnd.line == cm.lastLine() && curStart.line == curEnd.line) { + if (curEnd.line == 0) { + curStart.ch = 0; + } + else { + var tmp = copyCursor(curEnd); + curStart.line--; + curStart.ch = lineLength(cm, curStart.line); + curEnd = tmp; + } + cm.replaceRange('', curStart, curEnd); + } else { + cm.replaceSelections(replacement); + } + // restore the saved bookmark + if (selectionEnd) { + var curStartMark = cm.setBookmark(selectionStart); + var curEndMark = cm.setBookmark(selectionEnd); + if (vim.visualMode) { + vim.marks['<'] = curStartMark; + vim.marks['>'] = curEndMark; + } else { + vim.lastSelection.curStartMark = curStartMark; + vim.lastSelection.curEndMark = curEndMark; + } + } + if (operatorArgs.linewise) { + cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + } else { + cm.setCursor(curStart); + } + }, + indent: function(cm, operatorArgs, vim, curStart, curEnd) { + var startLine = curStart.line; + var endLine = curEnd.line; + // In visual mode, n> shifts the selection right n times, instead of + // shifting n lines right once. + var repeat = (vim.visualMode) ? operatorArgs.repeat : 1; + if (operatorArgs.linewise) { + // The only way to delete a newline is to delete until the start of + // the next line, so in linewise mode evalInput will include the next + // line. We don't want this in indent, so we go back a line. + endLine--; + } + for (var i = startLine; i <= endLine; i++) { + for (var j = 0; j < repeat; j++) { + cm.indentLine(i, operatorArgs.indentRight); + } + } + cm.setCursor(curStart); + cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + }, + changeCase: function(cm, operatorArgs, _vim, _curStart, _curEnd, _curOriginal) { + var selections = cm.getSelections(); + var ranges = cm.listSelections(); + var swapped = []; + var toLower = operatorArgs.toLower; + for (var j = 0; j < selections.length; j++) { + var toSwap = selections[j]; + var text = ''; + if (toLower === true) { + text = toSwap.toLowerCase(); + } else if (toLower === false) { + text = toSwap.toUpperCase(); + } else { + for (var i = 0; i < toSwap.length; i++) { + var character = toSwap.charAt(i); + text += isUpperCase(character) ? character.toLowerCase() : + character.toUpperCase(); + } + } + swapped.push(text); + } + cm.replaceSelections(swapped); + var curStart = ranges[0].anchor; + var curEnd = ranges[0].head; + if (!operatorArgs.shouldMoveCursor) { + cm.setCursor(cursorIsBefore(curStart, curEnd) ? curStart : curEnd); + } + }, + yank: function(cm, operatorArgs, vim, _curStart, _curEnd, curOriginal) { + var text = cm.getSelection(); + vimGlobalState.registerController.pushText( + operatorArgs.registerName, 'yank', + text, operatorArgs.linewise, vim.visualBlock); + cm.setCursor(curOriginal); + } + }; + + var actions = { + jumpListWalk: function(cm, actionArgs, vim) { + if (vim.visualMode) { + return; + } + var repeat = actionArgs.repeat; + var forward = actionArgs.forward; + var jumpList = vimGlobalState.jumpList; + + var mark = jumpList.move(cm, forward ? repeat : -repeat); + var markPos = mark ? mark.find() : undefined; + markPos = markPos ? markPos : cm.getCursor(); + cm.setCursor(markPos); + }, + scroll: function(cm, actionArgs, vim) { + if (vim.visualMode) { + return; + } + var repeat = actionArgs.repeat || 1; + var lineHeight = cm.defaultTextHeight(); + var top = cm.getScrollInfo().top; + var delta = lineHeight * repeat; + var newPos = actionArgs.forward ? top + delta : top - delta; + var cursor = copyCursor(cm.getCursor()); + var cursorCoords = cm.charCoords(cursor, 'local'); + if (actionArgs.forward) { + if (newPos > cursorCoords.top) { + cursor.line += (newPos - cursorCoords.top) / lineHeight; + cursor.line = Math.ceil(cursor.line); + cm.setCursor(cursor); + cursorCoords = cm.charCoords(cursor, 'local'); + cm.scrollTo(null, cursorCoords.top); + } else { + // Cursor stays within bounds. Just reposition the scroll window. + cm.scrollTo(null, newPos); + } + } else { + var newBottom = newPos + cm.getScrollInfo().clientHeight; + if (newBottom < cursorCoords.bottom) { + cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight; + cursor.line = Math.floor(cursor.line); + cm.setCursor(cursor); + cursorCoords = cm.charCoords(cursor, 'local'); + cm.scrollTo( + null, cursorCoords.bottom - cm.getScrollInfo().clientHeight); + } else { + // Cursor stays within bounds. Just reposition the scroll window. + cm.scrollTo(null, newPos); + } + } + }, + scrollToCursor: function(cm, actionArgs) { + var lineNum = cm.getCursor().line; + var charCoords = cm.charCoords(Pos(lineNum, 0), 'local'); + var height = cm.getScrollInfo().clientHeight; + var y = charCoords.top; + var lineHeight = charCoords.bottom - y; + switch (actionArgs.position) { + case 'center': y = y - (height / 2) + lineHeight; + break; + case 'bottom': y = y - height + lineHeight*1.4; + break; + case 'top': y = y + lineHeight*0.4; + break; + } + cm.scrollTo(null, y); + }, + replayMacro: function(cm, actionArgs, vim) { + var registerName = actionArgs.selectedCharacter; + var repeat = actionArgs.repeat; + var macroModeState = vimGlobalState.macroModeState; + if (registerName == '@') { + registerName = macroModeState.latestRegister; + } + while(repeat--){ + executeMacroRegister(cm, vim, macroModeState, registerName); + } + }, + enterMacroRecordMode: function(cm, actionArgs) { + var macroModeState = vimGlobalState.macroModeState; + var registerName = actionArgs.selectedCharacter; + macroModeState.enterMacroRecordMode(cm, registerName); + }, + enterInsertMode: function(cm, actionArgs, vim) { + if (cm.getOption('readOnly')) { return; } + vim.insertMode = true; + vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1; + var insertAt = (actionArgs) ? actionArgs.insertAt : null; + if (vim.visualMode) { + var selections = getSelectedAreaRange(cm, vim); + var selectionStart = selections[0]; + var selectionEnd = selections[1]; + } + if (insertAt == 'eol') { + var cursor = cm.getCursor(); + cursor = Pos(cursor.line, lineLength(cm, cursor.line)); + cm.setCursor(cursor); + } else if (insertAt == 'charAfter') { + cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); + } else if (insertAt == 'firstNonBlank') { + if (vim.visualMode && !vim.visualBlock) { + if (selectionEnd.line < selectionStart.line) { + cm.setCursor(selectionEnd); + } else { + selectionStart = Pos(selectionStart.line, 0); + cm.setCursor(selectionStart); + } + cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + } else if (vim.visualBlock) { + selectionEnd = Pos(selectionEnd.line, selectionStart.ch); + cm.setCursor(selectionStart); + selectBlock(cm, selectionEnd); + } else { + cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + } + } else if (insertAt == 'endOfSelectedArea') { + if (vim.visualBlock) { + selectionStart = Pos(selectionStart.line, selectionEnd.ch); + cm.setCursor(selectionStart); + selectBlock(cm, selectionEnd); + } else if (selectionEnd && selectionEnd.line < selectionStart.line) { + selectionEnd = Pos(selectionStart.line, 0); + cm.setCursor(selectionEnd); + } + } else if (insertAt == 'inplace') { + if (vim.visualMode){ + return; + } + } + cm.setOption('keyMap', 'vim-insert'); + cm.setOption('disableInput', false); + if (actionArgs && actionArgs.replace) { + // Handle Replace-mode as a special case of insert mode. + cm.toggleOverwrite(true); + cm.setOption('keyMap', 'vim-replace'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); + } else { + cm.setOption('keyMap', 'vim-insert'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); + } + if (!vimGlobalState.macroModeState.isPlaying) { + // Only record if not replaying. + cm.on('change', onChange); + CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); + } + if (vim.visualMode) { + exitVisualMode(cm); + } + }, + toggleVisualMode: function(cm, actionArgs, vim) { + var repeat = actionArgs.repeat; + var curStart = cm.getCursor(); + var curEnd; + var selections = cm.listSelections(); + // TODO: The repeat should actually select number of characters/lines + // equal to the repeat times the size of the previous visual + // operation. + if (!vim.visualMode) { + vim.visualMode = true; + vim.visualLine = !!actionArgs.linewise; + vim.visualBlock = !!actionArgs.blockwise; + if (vim.visualLine) { + curStart.ch = 0; + curEnd = clipCursorToContent( + cm, Pos(curStart.line + repeat - 1, lineLength(cm, curStart.line)), + true /** includeLineBreak */); + } else { + curEnd = clipCursorToContent( + cm, Pos(curStart.line, curStart.ch + repeat), + true /** includeLineBreak */); + } + cm.setSelection(curStart, curEnd); + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""}); + } else { + curStart = cm.getCursor('anchor'); + curEnd = cm.getCursor('head'); + if (vim.visualLine) { + if (actionArgs.blockwise) { + // This means Ctrl-V pressed in linewise visual + vim.visualBlock = true; + selectBlock(cm, curEnd); + CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'blockwise'}); + } else if (!actionArgs.linewise) { + // v pressed in linewise, switch to characterwise visual mode + CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual'}); + } else { + exitVisualMode(cm); + } + vim.visualLine = false; + } else if (vim.visualBlock) { + if (actionArgs.linewise) { + // Shift-V pressed in blockwise visual mode + vim.visualLine = true; + curStart = Pos(selections[0].anchor.line, 0); + curEnd = Pos(selections[selections.length-1].anchor.line, lineLength(cm, selections[selections.length-1].anchor.line)); + cm.setSelection(curStart, curEnd); + CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'linewise'}); + } else if (!actionArgs.blockwise) { + // v pressed in blockwise mode, Switch to characterwise + if (curEnd != selections[0].head) { + curStart = selections[0].anchor; + } else { + curStart = selections[selections.length-1].anchor; + } + cm.setSelection(curStart, curEnd); + CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual'}); + } else { + exitVisualMode(cm); + } + vim.visualBlock = false; + } else if (actionArgs.linewise) { + // Shift-V pressed in characterwise visual mode. Switch to linewise + // visual mode instead of exiting visual mode. + vim.visualLine = true; + curStart.ch = cursorIsBefore(curStart, curEnd) ? 0 : + lineLength(cm, curStart.line); + curEnd.ch = cursorIsBefore(curStart, curEnd) ? + lineLength(cm, curEnd.line) : 0; + cm.setSelection(curStart, curEnd); + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: "linewise"}); + } else if (actionArgs.blockwise) { + vim.visualBlock = true; + selectBlock(cm, curEnd); + CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'blockwise'}); + } else { + exitVisualMode(cm); + } + } + updateMark(cm, vim, '<', cursorIsBefore(curStart, curEnd) ? curStart + : curEnd); + updateMark(cm, vim, '>', cursorIsBefore(curStart, curEnd) ? curEnd + : curStart); + }, + reselectLastSelection: function(cm, _actionArgs, vim) { + var curStart = vim.marks['<'].find(); + var curEnd = vim.marks['>'].find(); + var lastSelection = vim.lastSelection; + if (lastSelection) { + // Set the selections as per last selection + var selectionStart = lastSelection.curStartMark.find(); + var selectionEnd = lastSelection.curEndMark.find(); + var blockwise = lastSelection.visualBlock; + // update last selection + updateLastSelection(cm, vim, curStart, curEnd); + if (blockwise) { + cm.setCursor(selectionStart); + selectionStart = selectBlock(cm, selectionEnd); + } else { + cm.setSelection(selectionStart, selectionEnd); + selectionStart = cm.getCursor('anchor'); + selectionEnd = cm.getCursor('head'); + } + if (vim.visualMode) { + updateMark(cm, vim, '<', cursorIsBefore(selectionStart, selectionEnd) ? selectionStart + : selectionEnd); + updateMark(cm, vim, '>', cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd + : selectionStart); + } + // Last selection is updated now + vim.visualMode = true; + if (lastSelection.visualLine) { + vim.visualLine = true; + vim.visualBlock = false; + } else if (lastSelection.visualBlock) { + vim.visualLine = false; + vim.visualBlock = true; + } else { + vim.visualBlock = vim.visualLine = false; + } + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""}); + } + }, + joinLines: function(cm, actionArgs, vim) { + var curStart, curEnd; + if (vim.visualMode) { + curStart = cm.getCursor('anchor'); + curEnd = cm.getCursor('head'); + curEnd.ch = lineLength(cm, curEnd.line) - 1; + } else { + // Repeat is the number of lines to join. Minimum 2 lines. + var repeat = Math.max(actionArgs.repeat, 2); + curStart = cm.getCursor(); + curEnd = clipCursorToContent(cm, Pos(curStart.line + repeat - 1, + Infinity)); + } + var finalCh = 0; + cm.operation(function() { + for (var i = curStart.line; i < curEnd.line; i++) { + finalCh = lineLength(cm, curStart.line); + var tmp = Pos(curStart.line + 1, + lineLength(cm, curStart.line + 1)); + var text = cm.getRange(curStart, tmp); + text = text.replace(/\n\s*/g, ' '); + cm.replaceRange(text, curStart, tmp); + } + var curFinalPos = Pos(curStart.line, finalCh); + cm.setCursor(curFinalPos); + }); + }, + newLineAndEnterInsertMode: function(cm, actionArgs, vim) { + vim.insertMode = true; + var insertAt = copyCursor(cm.getCursor()); + if (insertAt.line === cm.firstLine() && !actionArgs.after) { + // Special case for inserting newline before start of document. + cm.replaceRange('\n', Pos(cm.firstLine(), 0)); + cm.setCursor(cm.firstLine(), 0); + } else { + insertAt.line = (actionArgs.after) ? insertAt.line : + insertAt.line - 1; + insertAt.ch = lineLength(cm, insertAt.line); + cm.setCursor(insertAt); + var newlineFn = CodeMirror.commands.newlineAndIndentContinueComment || + CodeMirror.commands.newlineAndIndent; + newlineFn(cm); + } + this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim); + }, + paste: function(cm, actionArgs, vim) { + var cur = copyCursor(cm.getCursor()); + var register = vimGlobalState.registerController.getRegister( + actionArgs.registerName); + var text = register.toString(); + if (!text) { + return; + } + if (actionArgs.matchIndent) { + var tabSize = cm.getOption("tabSize"); + // length that considers tabs and tabSize + var whitespaceLength = function(str) { + var tabs = (str.split("\t").length - 1); + var spaces = (str.split(" ").length - 1); + return tabs * tabSize + spaces * 1; + }; + var currentLine = cm.getLine(cm.getCursor().line); + var indent = whitespaceLength(currentLine.match(/^\s*/)[0]); + // chomp last newline b/c don't want it to match /^\s*/gm + var chompedText = text.replace(/\n$/, ''); + var wasChomped = text !== chompedText; + var firstIndent = whitespaceLength(text.match(/^\s*/)[0]); + var text = chompedText.replace(/^\s*/gm, function(wspace) { + var newIndent = indent + (whitespaceLength(wspace) - firstIndent); + if (newIndent < 0) { + return ""; + } + else if (cm.getOption("indentWithTabs")) { + var quotient = Math.floor(newIndent / tabSize); + return Array(quotient + 1).join('\t'); + } + else { + return Array(newIndent + 1).join(' '); + } + }); + text += wasChomped ? "\n" : ""; + } + if (actionArgs.repeat > 1) { + var text = Array(actionArgs.repeat + 1).join(text); + } + var linewise = register.linewise; + var blockwise = register.blockwise; + if (linewise) { + if(vim.visualMode) { + text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n'; + } else if (actionArgs.after) { + // Move the newline at the end to the start instead, and paste just + // before the newline character of the line we are on right now. + text = '\n' + text.slice(0, text.length - 1); + cur.ch = lineLength(cm, cur.line); + } else { + cur.ch = 0; + } + } else { + if (blockwise) { + text = text.split('\n'); + for (var i = 0; i < text.length; i++) { + text[i] = (text[i] == '') ? ' ' : text[i]; + } + } + cur.ch += actionArgs.after ? 1 : 0; + } + var curPosFinal; + var idx; + if (vim.visualMode) { + // save the pasted text for reselection if the need arises + vim.lastPastedText = text; + var lastSelectionCurEnd; + var selectedArea = getSelectedAreaRange(cm, vim); + var selectionStart = selectedArea[0]; + var selectionEnd = selectedArea[1]; + var selectedText = cm.getSelection(); + var selections = cm.listSelections(); + var emptyStrings = new Array(selections.length).join('1').split('1'); + // save the curEnd marker before it get cleared due to cm.replaceRange. + if (vim.lastSelection) { + lastSelectionCurEnd = vim.lastSelection.curEndMark.find(); + } + // push the previously selected text to unnamed register + vimGlobalState.registerController.unnamedRegister.setText(selectedText); + if (blockwise) { + // first delete the selected text + cm.replaceSelections(emptyStrings); + // Set new selections as per the block length of the yanked text + selectionEnd = Pos(selectionStart.line + text.length-1, selectionStart.ch); + cm.setCursor(selectionStart); + selectBlock(cm, selectionEnd); + cm.replaceSelections(text); + curPosFinal = selectionStart; + } else if (vim.visualBlock) { + cm.replaceSelections(emptyStrings); + cm.setCursor(selectionStart); + cm.replaceRange(text, selectionStart, selectionStart); + curPosFinal = selectionStart; + } else { + cm.replaceRange(text, selectionStart, selectionEnd); + curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1); + } + // restore the the curEnd marker + if(lastSelectionCurEnd) { + vim.lastSelection.curEndMark = cm.setBookmark(lastSelectionCurEnd); + } + if (linewise) { + curPosFinal.ch=0; + } + } else { + if (blockwise) { + cm.setCursor(cur); + for (var i = 0; i < text.length; i++) { + var line = cur.line+i; + if (line > cm.lastLine()) { + cm.replaceRange('\n', Pos(line, 0)); + } + var lastCh = lineLength(cm, line); + if (lastCh < cur.ch) { + extendLineToColumn(cm, line, cur.ch); + } + } + cm.setCursor(cur); + selectBlock(cm, Pos(cur.line + text.length-1, cur.ch)); + cm.replaceSelections(text); + curPosFinal = cur; + } else { + cm.replaceRange(text, cur); + // Now fine tune the cursor to where we want it. + if (linewise && actionArgs.after) { + curPosFinal = Pos( + cur.line + 1, + findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1))); + } else if (linewise && !actionArgs.after) { + curPosFinal = Pos( + cur.line, + findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line))); + } else if (!linewise && actionArgs.after) { + idx = cm.indexFromPos(cur); + curPosFinal = cm.posFromIndex(idx + text.length - 1); + } else { + idx = cm.indexFromPos(cur); + curPosFinal = cm.posFromIndex(idx + text.length); + } + } + } + cm.setCursor(curPosFinal); + if (vim.visualMode) { + exitVisualMode(cm); + } + }, + undo: function(cm, actionArgs) { + cm.operation(function() { + repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)(); + cm.setCursor(cm.getCursor('anchor')); + }); + }, + redo: function(cm, actionArgs) { + repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)(); + }, + setRegister: function(_cm, actionArgs, vim) { + vim.inputState.registerName = actionArgs.selectedCharacter; + }, + setMark: function(cm, actionArgs, vim) { + var markName = actionArgs.selectedCharacter; + updateMark(cm, vim, markName, cm.getCursor()); + }, + replace: function(cm, actionArgs, vim) { + var replaceWith = actionArgs.selectedCharacter; + var curStart = cm.getCursor(); + var replaceTo; + var curEnd; + var selections = cm.listSelections(); + if (vim.visualMode) { + curStart = cm.getCursor('start'); + curEnd = cm.getCursor('end'); + } else { + var line = cm.getLine(curStart.line); + replaceTo = curStart.ch + actionArgs.repeat; + if (replaceTo > line.length) { + replaceTo=line.length; + } + curEnd = Pos(curStart.line, replaceTo); + } + if (replaceWith=='\n') { + if (!vim.visualMode) cm.replaceRange('', curStart, curEnd); + // special case, where vim help says to replace by just one line-break + (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm); + } else { + var replaceWithStr = cm.getRange(curStart, curEnd); + //replace all characters in range by selected, but keep linebreaks + replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith); + if (vim.visualBlock) { + // Tabs are split in visua block before replacing + var spaces = new Array(cm.getOption("tabSize")+1).join(' '); + replaceWithStr = cm.getSelection(); + replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n'); + cm.replaceSelections(replaceWithStr); + } else { + cm.replaceRange(replaceWithStr, curStart, curEnd); + } + if (vim.visualMode) { + curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ? + selections[0].anchor : selections[0].head; + cm.setCursor(curStart); + exitVisualMode(cm); + } else { + cm.setCursor(offsetCursor(curEnd, 0, -1)); + } + } + }, + incrementNumberToken: function(cm, actionArgs) { + var cur = cm.getCursor(); + var lineStr = cm.getLine(cur.line); + var re = /-?\d+/g; + var match; + var start; + var end; + var numberStr; + var token; + while ((match = re.exec(lineStr)) !== null) { + token = match[0]; + start = match.index; + end = start + token.length; + if (cur.ch < end)break; + } + if (!actionArgs.backtrack && (end <= cur.ch))return; + if (token) { + var increment = actionArgs.increase ? 1 : -1; + var number = parseInt(token) + (increment * actionArgs.repeat); + var from = Pos(cur.line, start); + var to = Pos(cur.line, end); + numberStr = number.toString(); + cm.replaceRange(numberStr, from, to); + } else { + return; + } + cm.setCursor(Pos(cur.line, start + numberStr.length - 1)); + }, + repeatLastEdit: function(cm, actionArgs, vim) { + var lastEditInputState = vim.lastEditInputState; + if (!lastEditInputState) { return; } + var repeat = actionArgs.repeat; + if (repeat && actionArgs.repeatIsExplicit) { + vim.lastEditInputState.repeatOverride = repeat; + } else { + repeat = vim.lastEditInputState.repeatOverride || repeat; + } + repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */); + }, + exitInsertMode: exitInsertMode + }; + + /* + * Below are miscellaneous utility functions used by vim.js + */ + + /** + * Clips cursor to ensure that line is within the buffer's range + * If includeLineBreak is true, then allow cur.ch == lineLength. + */ + function clipCursorToContent(cm, cur, includeLineBreak) { + var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine() ); + var maxCh = lineLength(cm, line) - 1; + maxCh = (includeLineBreak) ? maxCh + 1 : maxCh; + var ch = Math.min(Math.max(0, cur.ch), maxCh); + return Pos(line, ch); + } + function copyArgs(args) { + var ret = {}; + for (var prop in args) { + if (args.hasOwnProperty(prop)) { + ret[prop] = args[prop]; + } + } + return ret; + } + function offsetCursor(cur, offsetLine, offsetCh) { + return Pos(cur.line + offsetLine, cur.ch + offsetCh); + } + function commandMatches(keys, keyMap, context, inputState) { + // Partial matches are not applied. They inform the key handler + // that the current key sequence is a subsequence of a valid key + // sequence, so that the key buffer is not cleared. + var match, partial = [], full = []; + for (var i = 0; i < keyMap.length; i++) { + var command = keyMap[i]; + if (context == 'insert' && command.context != 'insert' || + command.context && command.context != context || + inputState.operator && command.type == 'action' || + !(match = commandMatch(keys, command.keys))) { continue; } + if (match == 'partial') { partial.push(command); } + if (match == 'full') { full.push(command); } + } + return { + partial: partial.length && partial, + full: full.length && full + }; + } + function commandMatch(pressed, mapped) { + if (mapped.slice(-11) == '') { + // Last character matches anything. + var prefixLen = mapped.length - 11; + var pressedPrefix = pressed.slice(0, prefixLen); + var mappedPrefix = mapped.slice(0, prefixLen); + return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' : + mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false; + } else { + return pressed == mapped ? 'full' : + mapped.indexOf(pressed) == 0 ? 'partial' : false; + } + } + function lastChar(keys) { + var match = /^.*(<[\w\-]+>)$/.exec(keys); + var selectedCharacter = match ? match[1] : keys.slice(-1); + if (selectedCharacter.length > 1){ + switch(selectedCharacter){ + case '': + selectedCharacter='\n'; + break; + case '': + selectedCharacter=' '; + break; + default: + break; + } + } + return selectedCharacter; + } + function repeatFn(cm, fn, repeat) { + return function() { + for (var i = 0; i < repeat; i++) { + fn(cm); + } + }; + } + function copyCursor(cur) { + return Pos(cur.line, cur.ch); + } + function cursorEqual(cur1, cur2) { + return cur1.ch == cur2.ch && cur1.line == cur2.line; + } + function cursorIsBefore(cur1, cur2) { + if (cur1.line < cur2.line) { + return true; + } + if (cur1.line == cur2.line && cur1.ch < cur2.ch) { + return true; + } + return false; + } + function cursorMin(cur1, cur2) { + return cursorIsBefore(cur1, cur2) ? cur1 : cur2; + } + function cursorMax(cur1, cur2) { + return cursorIsBefore(cur1, cur2) ? cur2 : cur1; + } + function cursorIsBetween(cur1, cur2, cur3) { + // returns true if cur2 is between cur1 and cur3. + var cur1before2 = cursorIsBefore(cur1, cur2); + var cur2before3 = cursorIsBefore(cur2, cur3); + return cur1before2 && cur2before3; + } + function lineLength(cm, lineNum) { + return cm.getLine(lineNum).length; + } + function reverse(s){ + return s.split('').reverse().join(''); + } + function trim(s) { + if (s.trim) { + return s.trim(); + } + return s.replace(/^\s+|\s+$/g, ''); + } + function escapeRegex(s) { + return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1'); + } + function extendLineToColumn(cm, lineNum, column) { + var endCh = lineLength(cm, lineNum); + var spaces = new Array(column-endCh+1).join(' '); + cm.setCursor(Pos(lineNum, endCh)); + cm.replaceRange(spaces, cm.getCursor()); + } + // This functions selects a rectangular block + // of text with selectionEnd as any of its corner + // Height of block: + // Difference in selectionEnd.line and first/last selection.line + // Width of the block: + // Distance between selectionEnd.ch and any(first considered here) selection.ch + function selectBlock(cm, selectionEnd) { + var selections = [], ranges = cm.listSelections(); + var head = copyCursor(cm.clipPos(selectionEnd)); + var isClipped = !cursorEqual(selectionEnd, head); + var curHead = cm.getCursor('head'); + var primIndex = getIndex(ranges, curHead); + var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor); + var max = ranges.length - 1; + var index = max - primIndex > primIndex ? max : 0; + var base = ranges[index].anchor; + + var firstLine = Math.min(base.line, head.line); + var lastLine = Math.max(base.line, head.line); + var baseCh = base.ch, headCh = head.ch; + + var dir = ranges[index].head.ch - baseCh; + var newDir = headCh - baseCh; + if (dir > 0 && newDir <= 0) { + baseCh++; + if (!isClipped) { headCh--; } + } else if (dir < 0 && newDir >= 0) { + baseCh--; + if (!wasClipped) { headCh++; } + } else if (dir < 0 && newDir == -1) { + baseCh--; + headCh++; + } + for (var line = firstLine; line <= lastLine; line++) { + var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)}; + selections.push(range); + } + primIndex = head.line == lastLine ? selections.length - 1 : 0; + cm.setSelections(selections, primIndex); + selectionEnd.ch = headCh; + base.ch = baseCh; + return base; + } + // getIndex returns the index of the cursor in the selections. + function getIndex(ranges, cursor, end) { + for (var i = 0; i < ranges.length; i++) { + var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor); + var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor); + if (atAnchor || atHead) { + return i; + } + } + return -1; + } + function getSelectedAreaRange(cm, vim) { + var lastSelection = vim.lastSelection; + var getCurrentSelectedAreaRange = function() { + var selections = cm.listSelections(); + var start = selections[0]; + var end = selections[selections.length-1]; + var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; + var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; + return [selectionStart, selectionEnd]; + }; + var getLastSelectedAreaRange = function() { + var selectionStart = cm.getCursor(); + var selectionEnd = cm.getCursor(); + var block = lastSelection.visualBlock; + if (block) { + var width = block.width; + var height = block.height; + selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width); + var selections = []; + // selectBlock creates a 'proper' rectangular block. + // We do not want that in all cases, so we manually set selections. + for (var i = selectionStart.line; i < selectionEnd.line; i++) { + var anchor = Pos(i, selectionStart.ch); + var head = Pos(i, selectionEnd.ch); + var range = {anchor: anchor, head: head}; + selections.push(range); + } + cm.setSelections(selections); + } else { + var start = lastSelection.curStartMark.find(); + var end = lastSelection.curEndMark.find(); + var line = end.line - start.line; + var ch = end.ch - start.ch; + selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch}; + if (lastSelection.visualLine) { + selectionStart = Pos(selectionStart.line, 0); + selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line)); + } + cm.setSelection(selectionStart, selectionEnd); + } + return [selectionStart, selectionEnd]; + }; + if (!vim.visualMode) { + // In case of replaying the action. + return getLastSelectedAreaRange(); + } else { + return getCurrentSelectedAreaRange(); + } + } + function updateLastSelection(cm, vim, selectionStart, selectionEnd) { + if (!selectionStart || !selectionEnd) { + selectionStart = vim.marks['<'].find() || cm.getCursor('anchor'); + selectionEnd = vim.marks['>'].find() || cm.getCursor('head'); + } + // To accommodate the effect of lastPastedText in the last selection + if (vim.lastPastedText) { + selectionEnd = cm.posFromIndex(cm.indexFromPos(selectionStart) + vim.lastPastedText.length); + vim.lastPastedText = null; + } + var ranges = cm.listSelections(); + // This check ensures to set the cursor + // position where we left off in previous selection + var swap = getIndex(ranges, selectionStart, 'head') > -1; + if (vim.visualBlock) { + var height = Math.abs(selectionStart.line - selectionEnd.line)+1; + var width = Math.abs(selectionStart.ch - selectionEnd.ch); + var block = {height: height, width: width}; + } + // can't use selection state here because yank has already reset its cursor + // Also, Bookmarks make the visual selections robust to edit operations + vim.lastSelection = {'curStartMark': cm.setBookmark(swap ? selectionEnd : selectionStart), + 'curEndMark': cm.setBookmark(swap ? selectionStart : selectionEnd), + 'visualMode': vim.visualMode, + 'visualLine': vim.visualLine, + 'visualBlock': block}; + } + function expandSelection(cm, start, end) { + var head = cm.getCursor('head'); + var anchor = cm.getCursor('anchor'); + var tmp; + if (cursorIsBefore(end, start)) { + tmp = end; + end = start; + start = tmp; + } + if (cursorIsBefore(head, anchor)) { + head = cursorMin(start, head); + anchor = cursorMax(anchor, end); + } else { + anchor = cursorMin(start, anchor); + head = cursorMax(head, end); + } + return [anchor, head]; + } + function getHead(cm) { + var cur = cm.getCursor('head'); + if (cm.getSelection().length == 1) { + // Small corner case when only 1 character is selected. The "real" + // head is the left of head and anchor. + cur = cursorMin(cur, cm.getCursor('anchor')); + } + return cur; + } + + function exitVisualMode(cm) { + var vim = cm.state.vim; + var selectionStart = cm.getCursor('anchor'); + var selectionEnd = cm.getCursor('head'); + // hack to place the cursor at the right place + // in case of visual block + if (vim.visualBlock && (cursorIsBefore(selectionStart, selectionEnd))) { + selectionEnd.ch--; + } + updateLastSelection(cm, vim); + vim.visualMode = false; + vim.visualLine = false; + vim.visualBlock = false; + if (!cursorEqual(selectionStart, selectionEnd)) { + cm.setCursor(clipCursorToContent(cm, selectionEnd)); + } + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + if (vim.fakeCursor) { + vim.fakeCursor.clear(); + } + } + + // Remove any trailing newlines from the selection. For + // example, with the caret at the start of the last word on the line, + // 'dw' should word, but not the newline, while 'w' should advance the + // caret to the first character of the next line. + function clipToLine(cm, curStart, curEnd) { + var selection = cm.getRange(curStart, curEnd); + // Only clip if the selection ends with trailing newline + whitespace + if (/\n\s*$/.test(selection)) { + var lines = selection.split('\n'); + // We know this is all whitepsace. + lines.pop(); + + // Cases: + // 1. Last word is an empty line - do not clip the trailing '\n' + // 2. Last word is not an empty line - clip the trailing '\n' + var line; + // Find the line containing the last word, and clip all whitespace up + // to it. + for (var line = lines.pop(); lines.length > 0 && line && isWhiteSpaceString(line); line = lines.pop()) { + curEnd.line--; + curEnd.ch = 0; + } + // If the last word is not an empty line, clip an additional newline + if (line) { + curEnd.line--; + curEnd.ch = lineLength(cm, curEnd.line); + } else { + curEnd.ch = 0; + } + } + } + + // Expand the selection to line ends. + function expandSelectionToLine(_cm, curStart, curEnd) { + curStart.ch = 0; + curEnd.ch = 0; + curEnd.line++; + } + + function findFirstNonWhiteSpaceCharacter(text) { + if (!text) { + return 0; + } + var firstNonWS = text.search(/\S/); + return firstNonWS == -1 ? text.length : firstNonWS; + } + + function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) { + var cur = getHead(cm); + var line = cm.getLine(cur.line); + var idx = cur.ch; + + // Seek to first word or non-whitespace character, depending on if + // noSymbol is true. + var textAfterIdx = line.substring(idx); + var firstMatchedChar; + if (noSymbol) { + firstMatchedChar = textAfterIdx.search(/\w/); + } else { + firstMatchedChar = textAfterIdx.search(/\S/); + } + if (firstMatchedChar == -1) { + return null; + } + idx += firstMatchedChar; + textAfterIdx = line.substring(idx); + var textBeforeIdx = line.substring(0, idx); + + var matchRegex; + // Greedy matchers for the "word" we are trying to expand. + if (bigWord) { + matchRegex = /^\S+/; + } else { + if ((/\w/).test(line.charAt(idx))) { + matchRegex = /^\w+/; + } else { + matchRegex = /^[^\w\s]+/; + } + } + + var wordAfterRegex = matchRegex.exec(textAfterIdx); + var wordStart = idx; + var wordEnd = idx + wordAfterRegex[0].length; + // TODO: Find a better way to do this. It will be slow on very long lines. + var revTextBeforeIdx = reverse(textBeforeIdx); + var wordBeforeRegex = matchRegex.exec(revTextBeforeIdx); + if (wordBeforeRegex) { + wordStart -= wordBeforeRegex[0].length; + } + + if (inclusive) { + // If present, trim all whitespace after word. + // Otherwise, trim all whitespace before word. + var textAfterWordEnd = line.substring(wordEnd); + var whitespacesAfterWord = textAfterWordEnd.match(/^\s*/)[0].length; + if (whitespacesAfterWord > 0) { + wordEnd += whitespacesAfterWord; + } else { + var revTrim = revTextBeforeIdx.length - wordStart; + var textBeforeWordStart = revTextBeforeIdx.substring(revTrim); + var whitespacesBeforeWord = textBeforeWordStart.match(/^\s*/)[0].length; + wordStart -= whitespacesBeforeWord; + } + } + + return { start: Pos(cur.line, wordStart), + end: Pos(cur.line, wordEnd) }; + } + + function recordJumpPosition(cm, oldCur, newCur) { + if (!cursorEqual(oldCur, newCur)) { + vimGlobalState.jumpList.add(cm, oldCur, newCur); + } + } + + function recordLastCharacterSearch(increment, args) { + vimGlobalState.lastChararacterSearch.increment = increment; + vimGlobalState.lastChararacterSearch.forward = args.forward; + vimGlobalState.lastChararacterSearch.selectedCharacter = args.selectedCharacter; + } + + var symbolToMode = { + '(': 'bracket', ')': 'bracket', '{': 'bracket', '}': 'bracket', + '[': 'section', ']': 'section', + '*': 'comment', '/': 'comment', + 'm': 'method', 'M': 'method', + '#': 'preprocess' + }; + var findSymbolModes = { + bracket: { + isComplete: function(state) { + if (state.nextCh === state.symb) { + state.depth++; + if (state.depth >= 1)return true; + } else if (state.nextCh === state.reverseSymb) { + state.depth--; + } + return false; + } + }, + section: { + init: function(state) { + state.curMoveThrough = true; + state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}'; + }, + isComplete: function(state) { + return state.index === 0 && state.nextCh === state.symb; + } + }, + comment: { + isComplete: function(state) { + var found = state.lastCh === '*' && state.nextCh === '/'; + state.lastCh = state.nextCh; + return found; + } + }, + // TODO: The original Vim implementation only operates on level 1 and 2. + // The current implementation doesn't check for code block level and + // therefore it operates on any levels. + method: { + init: function(state) { + state.symb = (state.symb === 'm' ? '{' : '}'); + state.reverseSymb = state.symb === '{' ? '}' : '{'; + }, + isComplete: function(state) { + if (state.nextCh === state.symb)return true; + return false; + } + }, + preprocess: { + init: function(state) { + state.index = 0; + }, + isComplete: function(state) { + if (state.nextCh === '#') { + var token = state.lineText.match(/#(\w+)/)[1]; + if (token === 'endif') { + if (state.forward && state.depth === 0) { + return true; + } + state.depth++; + } else if (token === 'if') { + if (!state.forward && state.depth === 0) { + return true; + } + state.depth--; + } + if (token === 'else' && state.depth === 0)return true; + } + return false; + } + } + }; + function findSymbol(cm, repeat, forward, symb) { + var cur = copyCursor(cm.getCursor()); + var increment = forward ? 1 : -1; + var endLine = forward ? cm.lineCount() : -1; + var curCh = cur.ch; + var line = cur.line; + var lineText = cm.getLine(line); + var state = { + lineText: lineText, + nextCh: lineText.charAt(curCh), + lastCh: null, + index: curCh, + symb: symb, + reverseSymb: (forward ? { ')': '(', '}': '{' } : { '(': ')', '{': '}' })[symb], + forward: forward, + depth: 0, + curMoveThrough: false + }; + var mode = symbolToMode[symb]; + if (!mode)return cur; + var init = findSymbolModes[mode].init; + var isComplete = findSymbolModes[mode].isComplete; + if (init) { init(state); } + while (line !== endLine && repeat) { + state.index += increment; + state.nextCh = state.lineText.charAt(state.index); + if (!state.nextCh) { + line += increment; + state.lineText = cm.getLine(line) || ''; + if (increment > 0) { + state.index = 0; + } else { + var lineLen = state.lineText.length; + state.index = (lineLen > 0) ? (lineLen-1) : 0; + } + state.nextCh = state.lineText.charAt(state.index); + } + if (isComplete(state)) { + cur.line = line; + cur.ch = state.index; + repeat--; + } + } + if (state.nextCh || state.curMoveThrough) { + return Pos(line, state.index); + } + return cur; + } + + /* + * Returns the boundaries of the next word. If the cursor in the middle of + * the word, then returns the boundaries of the current word, starting at + * the cursor. If the cursor is at the start/end of a word, and we are going + * forward/backward, respectively, find the boundaries of the next word. + * + * @param {CodeMirror} cm CodeMirror object. + * @param {Cursor} cur The cursor position. + * @param {boolean} forward True to search forward. False to search + * backward. + * @param {boolean} bigWord True if punctuation count as part of the word. + * False if only [a-zA-Z0-9] characters count as part of the word. + * @param {boolean} emptyLineIsWord True if empty lines should be treated + * as words. + * @return {Object{from:number, to:number, line: number}} The boundaries of + * the word, or null if there are no more words. + */ + function findWord(cm, cur, forward, bigWord, emptyLineIsWord) { + var lineNum = cur.line; + var pos = cur.ch; + var line = cm.getLine(lineNum); + var dir = forward ? 1 : -1; + var regexps = bigWord ? bigWordRegexp : wordRegexp; + + if (emptyLineIsWord && line == '') { + lineNum += dir; + line = cm.getLine(lineNum); + if (!isLine(cm, lineNum)) { + return null; + } + pos = (forward) ? 0 : line.length; + } + + while (true) { + if (emptyLineIsWord && line == '') { + return { from: 0, to: 0, line: lineNum }; + } + var stop = (dir > 0) ? line.length : -1; + var wordStart = stop, wordEnd = stop; + // Find bounds of next word. + while (pos != stop) { + var foundWord = false; + for (var i = 0; i < regexps.length && !foundWord; ++i) { + if (regexps[i].test(line.charAt(pos))) { + wordStart = pos; + // Advance to end of word. + while (pos != stop && regexps[i].test(line.charAt(pos))) { + pos += dir; + } + wordEnd = pos; + foundWord = wordStart != wordEnd; + if (wordStart == cur.ch && lineNum == cur.line && + wordEnd == wordStart + dir) { + // We started at the end of a word. Find the next one. + continue; + } else { + return { + from: Math.min(wordStart, wordEnd + 1), + to: Math.max(wordStart, wordEnd), + line: lineNum }; + } + } + } + if (!foundWord) { + pos += dir; + } + } + // Advance to next/prev line. + lineNum += dir; + if (!isLine(cm, lineNum)) { + return null; + } + line = cm.getLine(lineNum); + pos = (dir > 0) ? 0 : line.length; + } + // Should never get here. + throw new Error('The impossible happened.'); + } + + /** + * @param {CodeMirror} cm CodeMirror object. + * @param {int} repeat Number of words to move past. + * @param {boolean} forward True to search forward. False to search + * backward. + * @param {boolean} wordEnd True to move to end of word. False to move to + * beginning of word. + * @param {boolean} bigWord True if punctuation count as part of the word. + * False if only alphabet characters count as part of the word. + * @return {Cursor} The position the cursor should move to. + */ + function moveToWord(cm, repeat, forward, wordEnd, bigWord) { + var cur = cm.getCursor(); + var curStart = copyCursor(cur); + var words = []; + if (forward && !wordEnd || !forward && wordEnd) { + repeat++; + } + // For 'e', empty lines are not considered words, go figure. + var emptyLineIsWord = !(forward && wordEnd); + for (var i = 0; i < repeat; i++) { + var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord); + if (!word) { + var eodCh = lineLength(cm, cm.lastLine()); + words.push(forward + ? {line: cm.lastLine(), from: eodCh, to: eodCh} + : {line: 0, from: 0, to: 0}); + break; + } + words.push(word); + cur = Pos(word.line, forward ? (word.to - 1) : word.from); + } + var shortCircuit = words.length != repeat; + var firstWord = words[0]; + var lastWord = words.pop(); + if (forward && !wordEnd) { + // w + if (!shortCircuit && (firstWord.from != curStart.ch || firstWord.line != curStart.line)) { + // We did not start in the middle of a word. Discard the extra word at the end. + lastWord = words.pop(); + } + return Pos(lastWord.line, lastWord.from); + } else if (forward && wordEnd) { + return Pos(lastWord.line, lastWord.to - 1); + } else if (!forward && wordEnd) { + // ge + if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) { + // We did not start in the middle of a word. Discard the extra word at the end. + lastWord = words.pop(); + } + return Pos(lastWord.line, lastWord.to); + } else { + // b + return Pos(lastWord.line, lastWord.from); + } + } + + function moveToCharacter(cm, repeat, forward, character) { + var cur = cm.getCursor(); + var start = cur.ch; + var idx; + for (var i = 0; i < repeat; i ++) { + var line = cm.getLine(cur.line); + idx = charIdxInLine(start, line, character, forward, true); + if (idx == -1) { + return null; + } + start = idx; + } + return Pos(cm.getCursor().line, idx); + } + + function moveToColumn(cm, repeat) { + // repeat is always >= 1, so repeat - 1 always corresponds + // to the column we want to go to. + var line = cm.getCursor().line; + return clipCursorToContent(cm, Pos(line, repeat - 1)); + } + + function updateMark(cm, vim, markName, pos) { + if (!inArray(markName, validMarks)) { + return; + } + if (vim.marks[markName]) { + vim.marks[markName].clear(); + } + vim.marks[markName] = cm.setBookmark(pos); + } + + function charIdxInLine(start, line, character, forward, includeChar) { + // Search for char in line. + // motion_options: {forward, includeChar} + // If includeChar = true, include it too. + // If forward = true, search forward, else search backwards. + // If char is not found on this line, do nothing + var idx; + if (forward) { + idx = line.indexOf(character, start + 1); + if (idx != -1 && !includeChar) { + idx -= 1; + } + } else { + idx = line.lastIndexOf(character, start - 1); + if (idx != -1 && !includeChar) { + idx += 1; + } + } + return idx; + } + + // TODO: perhaps this finagling of start and end positions belonds + // in codmirror/replaceRange? + function selectCompanionObject(cm, symb, inclusive) { + var cur = getHead(cm), start, end; + + var bracketRegexp = ({ + '(': /[()]/, ')': /[()]/, + '[': /[[\]]/, ']': /[[\]]/, + '{': /[{}]/, '}': /[{}]/})[symb]; + var openSym = ({ + '(': '(', ')': '(', + '[': '[', ']': '[', + '{': '{', '}': '{'})[symb]; + var curChar = cm.getLine(cur.line).charAt(cur.ch); + // Due to the behavior of scanForBracket, we need to add an offset if the + // cursor is on a matching open bracket. + var offset = curChar === openSym ? 1 : 0; + + start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, null, {'bracketRegex': bracketRegexp}); + end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, null, {'bracketRegex': bracketRegexp}); + + if (!start || !end) { + return { start: cur, end: cur }; + } + + start = start.pos; + end = end.pos; + + if ((start.line == end.line && start.ch > end.ch) + || (start.line > end.line)) { + var tmp = start; + start = end; + end = tmp; + } + + if (inclusive) { + end.ch += 1; + } else { + start.ch += 1; + } + + return { start: start, end: end }; + } + + // Takes in a symbol and a cursor and tries to simulate text objects that + // have identical opening and closing symbols + // TODO support across multiple lines + function findBeginningAndEnd(cm, symb, inclusive) { + var cur = copyCursor(getHead(cm)); + var line = cm.getLine(cur.line); + var chars = line.split(''); + var start, end, i, len; + var firstIndex = chars.indexOf(symb); + + // the decision tree is to always look backwards for the beginning first, + // but if the cursor is in front of the first instance of the symb, + // then move the cursor forward + if (cur.ch < firstIndex) { + cur.ch = firstIndex; + // Why is this line even here??? + // cm.setCursor(cur.line, firstIndex+1); + } + // otherwise if the cursor is currently on the closing symbol + else if (firstIndex < cur.ch && chars[cur.ch] == symb) { + end = cur.ch; // assign end to the current cursor + --cur.ch; // make sure to look backwards + } + + // if we're currently on the symbol, we've got a start + if (chars[cur.ch] == symb && !end) { + start = cur.ch + 1; // assign start to ahead of the cursor + } else { + // go backwards to find the start + for (i = cur.ch; i > -1 && !start; i--) { + if (chars[i] == symb) { + start = i + 1; + } + } + } + + // look forwards for the end symbol + if (start && !end) { + for (i = start, len = chars.length; i < len && !end; i++) { + if (chars[i] == symb) { + end = i; + } + } + } + + // nothing found + if (!start || !end) { + return { start: cur, end: cur }; + } + + // include the symbols + if (inclusive) { + --start; ++end; + } + + return { + start: Pos(cur.line, start), + end: Pos(cur.line, end) + }; + } + + // Search functions + defineOption('pcre', true, 'boolean'); + function SearchState() {} + SearchState.prototype = { + getQuery: function() { + return vimGlobalState.query; + }, + setQuery: function(query) { + vimGlobalState.query = query; + }, + getOverlay: function() { + return this.searchOverlay; + }, + setOverlay: function(overlay) { + this.searchOverlay = overlay; + }, + isReversed: function() { + return vimGlobalState.isReversed; + }, + setReversed: function(reversed) { + vimGlobalState.isReversed = reversed; + } + }; + function getSearchState(cm) { + var vim = cm.state.vim; + return vim.searchState_ || (vim.searchState_ = new SearchState()); + } + function dialog(cm, template, shortText, onClose, options) { + if (cm.openDialog) { + cm.openDialog(template, onClose, { bottom: true, value: options.value, + onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp }); + } + else { + onClose(prompt(shortText, '')); + } + } + function splitBySlash(argString) { + var slashes = findUnescapedSlashes(argString) || []; + if (!slashes.length) return []; + var tokens = []; + // in case of strings like foo/bar + if (slashes[0] !== 0) return; + for (var i = 0; i < slashes.length; i++) { + if (typeof slashes[i] == 'number') + tokens.push(argString.substring(slashes[i] + 1, slashes[i+1])); + } + return tokens; + } + + function findUnescapedSlashes(str) { + var escapeNextChar = false; + var slashes = []; + for (var i = 0; i < str.length; i++) { + var c = str.charAt(i); + if (!escapeNextChar && c == '/') { + slashes.push(i); + } + escapeNextChar = !escapeNextChar && (c == '\\'); + } + return slashes; + } + + // Translates a search string from ex (vim) syntax into javascript form. + function translateRegex(str) { + // When these match, add a '\' if unescaped or remove one if escaped. + var specials = '|(){'; + // Remove, but never add, a '\' for these. + var unescape = '}'; + var escapeNextChar = false; + var out = []; + for (var i = -1; i < str.length; i++) { + var c = str.charAt(i) || ''; + var n = str.charAt(i+1) || ''; + var specialComesNext = (n && specials.indexOf(n) != -1); + if (escapeNextChar) { + if (c !== '\\' || !specialComesNext) { + out.push(c); + } + escapeNextChar = false; + } else { + if (c === '\\') { + escapeNextChar = true; + // Treat the unescape list as special for removing, but not adding '\'. + if (n && unescape.indexOf(n) != -1) { + specialComesNext = true; + } + // Not passing this test means removing a '\'. + if (!specialComesNext || n === '\\') { + out.push(c); + } + } else { + out.push(c); + if (specialComesNext && n !== '\\') { + out.push('\\'); + } + } + } + } + return out.join(''); + } + + // Translates the replace part of a search and replace from ex (vim) syntax into + // javascript form. Similar to translateRegex, but additionally fixes back references + // (translates '\[0..9]' to '$[0..9]') and follows different rules for escaping '$'. + function translateRegexReplace(str) { + var escapeNextChar = false; + var out = []; + for (var i = -1; i < str.length; i++) { + var c = str.charAt(i) || ''; + var n = str.charAt(i+1) || ''; + if (escapeNextChar) { + // At any point in the loop, escapeNextChar is true if the previous + // character was a '\' and was not escaped. + out.push(c); + escapeNextChar = false; + } else { + if (c === '\\') { + escapeNextChar = true; + if ((isNumber(n) || n === '$')) { + out.push('$'); + } else if (n !== '/' && n !== '\\') { + out.push('\\'); + } + } else { + if (c === '$') { + out.push('$'); + } + out.push(c); + if (n === '/') { + out.push('\\'); + } + } + } + } + return out.join(''); + } + + // Unescape \ and / in the replace part, for PCRE mode. + function unescapeRegexReplace(str) { + var stream = new CodeMirror.StringStream(str); + var output = []; + while (!stream.eol()) { + // Search for \. + while (stream.peek() && stream.peek() != '\\') { + output.push(stream.next()); + } + if (stream.match('\\/', true)) { + // \/ => / + output.push('/'); + } else if (stream.match('\\\\', true)) { + // \\ => \ + output.push('\\'); + } else { + // Don't change anything + output.push(stream.next()); + } + } + return output.join(''); + } + + /** + * Extract the regular expression from the query and return a Regexp object. + * Returns null if the query is blank. + * If ignoreCase is passed in, the Regexp object will have the 'i' flag set. + * If smartCase is passed in, and the query contains upper case letters, + * then ignoreCase is overridden, and the 'i' flag will not be set. + * If the query contains the /i in the flag part of the regular expression, + * then both ignoreCase and smartCase are ignored, and 'i' will be passed + * through to the Regex object. + */ + function parseQuery(query, ignoreCase, smartCase) { + // First update the last search register + var lastSearchRegister = vimGlobalState.registerController.getRegister('/'); + lastSearchRegister.setText(query); + // Check if the query is already a regex. + if (query instanceof RegExp) { return query; } + // First try to extract regex + flags from the input. If no flags found, + // extract just the regex. IE does not accept flags directly defined in + // the regex string in the form /regex/flags + var slashes = findUnescapedSlashes(query); + var regexPart; + var forceIgnoreCase; + if (!slashes.length) { + // Query looks like 'regexp' + regexPart = query; + } else { + // Query looks like 'regexp/...' + regexPart = query.substring(0, slashes[0]); + var flagsPart = query.substring(slashes[0]); + forceIgnoreCase = (flagsPart.indexOf('i') != -1); + } + if (!regexPart) { + return null; + } + if (!getOption('pcre')) { + regexPart = translateRegex(regexPart); + } + if (smartCase) { + ignoreCase = (/^[^A-Z]*$/).test(regexPart); + } + var regexp = new RegExp(regexPart, + (ignoreCase || forceIgnoreCase) ? 'i' : undefined); + return regexp; + } + function showConfirm(cm, text) { + if (cm.openNotification) { + cm.openNotification('' + text + '', + {bottom: true, duration: 5000}); + } else { + alert(text); + } + } + function makePrompt(prefix, desc) { + var raw = ''; + if (prefix) { + raw += '' + prefix + ''; + } + raw += ' ' + + ''; + if (desc) { + raw += ''; + raw += desc; + raw += ''; + } + return raw; + } + var searchPromptDesc = '(Javascript regexp)'; + function showPrompt(cm, options) { + var shortText = (options.prefix || '') + ' ' + (options.desc || ''); + var prompt = makePrompt(options.prefix, options.desc); + dialog(cm, prompt, shortText, options.onClose, options); + } + function regexEqual(r1, r2) { + if (r1 instanceof RegExp && r2 instanceof RegExp) { + var props = ['global', 'multiline', 'ignoreCase', 'source']; + for (var i = 0; i < props.length; i++) { + var prop = props[i]; + if (r1[prop] !== r2[prop]) { + return false; + } + } + return true; + } + return false; + } + // Returns true if the query is valid. + function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) { + if (!rawQuery) { + return; + } + var state = getSearchState(cm); + var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase); + if (!query) { + return; + } + highlightSearchMatches(cm, query); + if (regexEqual(query, state.getQuery())) { + return query; + } + state.setQuery(query); + return query; + } + function searchOverlay(query) { + if (query.source.charAt(0) == '^') { + var matchSol = true; + } + return { + token: function(stream) { + if (matchSol && !stream.sol()) { + stream.skipToEnd(); + return; + } + var match = stream.match(query, false); + if (match) { + if (match[0].length == 0) { + // Matched empty string, skip to next. + stream.next(); + return 'searching'; + } + if (!stream.sol()) { + // Backtrack 1 to match \b + stream.backUp(1); + if (!query.exec(stream.next() + match[0])) { + stream.next(); + return null; + } + } + stream.match(query); + return 'searching'; + } + while (!stream.eol()) { + stream.next(); + if (stream.match(query, false)) break; + } + }, + query: query + }; + } + function highlightSearchMatches(cm, query) { + var overlay = getSearchState(cm).getOverlay(); + if (!overlay || query != overlay.query) { + if (overlay) { + cm.removeOverlay(overlay); + } + overlay = searchOverlay(query); + cm.addOverlay(overlay); + getSearchState(cm).setOverlay(overlay); + } + } + function findNext(cm, prev, query, repeat) { + if (repeat === undefined) { repeat = 1; } + return cm.operation(function() { + var pos = cm.getCursor(); + var cursor = cm.getSearchCursor(query, pos); + for (var i = 0; i < repeat; i++) { + var found = cursor.find(prev); + if (i == 0 && found && cursorEqual(cursor.from(), pos)) { found = cursor.find(prev); } + if (!found) { + // SearchCursor may have returned null because it hit EOF, wrap + // around and try again. + cursor = cm.getSearchCursor(query, + (prev) ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) ); + if (!cursor.find(prev)) { + return; + } + } + } + return cursor.from(); + }); + } + function clearSearchHighlight(cm) { + cm.removeOverlay(getSearchState(cm).getOverlay()); + getSearchState(cm).setOverlay(null); + } + /** + * Check if pos is in the specified range, INCLUSIVE. + * Range can be specified with 1 or 2 arguments. + * If the first range argument is an array, treat it as an array of line + * numbers. Match pos against any of the lines. + * If the first range argument is a number, + * if there is only 1 range argument, check if pos has the same line + * number + * if there are 2 range arguments, then check if pos is in between the two + * range arguments. + */ + function isInRange(pos, start, end) { + if (typeof pos != 'number') { + // Assume it is a cursor position. Get the line number. + pos = pos.line; + } + if (start instanceof Array) { + return inArray(pos, start); + } else { + if (end) { + return (pos >= start && pos <= end); + } else { + return pos == start; + } + } + } + function getUserVisibleLines(cm) { + var scrollInfo = cm.getScrollInfo(); + var occludeToleranceTop = 6; + var occludeToleranceBottom = 10; + var from = cm.coordsChar({left:0, top: occludeToleranceTop + scrollInfo.top}, 'local'); + var bottomY = scrollInfo.clientHeight - occludeToleranceBottom + scrollInfo.top; + var to = cm.coordsChar({left:0, top: bottomY}, 'local'); + return {top: from.line, bottom: to.line}; + } + + // Ex command handling + // Care must be taken when adding to the default Ex command map. For any + // pair of commands that have a shared prefix, at least one of their + // shortNames must not match the prefix of the other command. + var defaultExCommandMap = [ + { name: 'map' }, + { name: 'imap', shortName: 'im' }, + { name: 'nmap', shortName: 'nm' }, + { name: 'vmap', shortName: 'vm' }, + { name: 'unmap' }, + { name: 'write', shortName: 'w' }, + { name: 'undo', shortName: 'u' }, + { name: 'redo', shortName: 'red' }, + { name: 'set', shortName: 'set' }, + { name: 'sort', shortName: 'sor' }, + { name: 'substitute', shortName: 's', possiblyAsync: true }, + { name: 'nohlsearch', shortName: 'noh' }, + { name: 'delmarks', shortName: 'delm' }, + { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true }, + { name: 'global', shortName: 'g' } + ]; + var ExCommandDispatcher = function() { + this.buildCommandMap_(); + }; + ExCommandDispatcher.prototype = { + processCommand: function(cm, input, opt_params) { + var vim = cm.state.vim; + var commandHistoryRegister = vimGlobalState.registerController.getRegister(':'); + var previousCommand = commandHistoryRegister.toString(); + if (vim.visualMode) { + exitVisualMode(cm); + } + var inputStream = new CodeMirror.StringStream(input); + // update ": with the latest command whether valid or invalid + commandHistoryRegister.setText(input); + var params = opt_params || {}; + params.input = input; + try { + this.parseInput_(cm, inputStream, params); + } catch(e) { + showConfirm(cm, e); + throw e; + } + var command; + var commandName; + if (!params.commandName) { + // If only a line range is defined, move to the line. + if (params.line !== undefined) { + commandName = 'move'; + } + } else { + command = this.matchCommand_(params.commandName); + if (command) { + commandName = command.name; + if (command.excludeFromCommandHistory) { + commandHistoryRegister.setText(previousCommand); + } + this.parseCommandArgs_(inputStream, params, command); + if (command.type == 'exToKey') { + // Handle Ex to Key mapping. + for (var i = 0; i < command.toKeys.length; i++) { + CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping'); + } + return; + } else if (command.type == 'exToEx') { + // Handle Ex to Ex mapping. + this.processCommand(cm, command.toInput); + return; + } + } + } + if (!commandName) { + showConfirm(cm, 'Not an editor command ":' + input + '"'); + return; + } + try { + exCommands[commandName](cm, params); + // Possibly asynchronous commands (e.g. substitute, which might have a + // user confirmation), are responsible for calling the callback when + // done. All others have it taken care of for them here. + if ((!command || !command.possiblyAsync) && params.callback) { + params.callback(); + } + } catch(e) { + showConfirm(cm, e); + throw e; + } + }, + parseInput_: function(cm, inputStream, result) { + inputStream.eatWhile(':'); + // Parse range. + if (inputStream.eat('%')) { + result.line = cm.firstLine(); + result.lineEnd = cm.lastLine(); + } else { + result.line = this.parseLineSpec_(cm, inputStream); + if (result.line !== undefined && inputStream.eat(',')) { + result.lineEnd = this.parseLineSpec_(cm, inputStream); + } + } + + // Parse command name. + var commandMatch = inputStream.match(/^(\w+)/); + if (commandMatch) { + result.commandName = commandMatch[1]; + } else { + result.commandName = inputStream.match(/.*/)[0]; + } + + return result; + }, + parseLineSpec_: function(cm, inputStream) { + var numberMatch = inputStream.match(/^(\d+)/); + if (numberMatch) { + return parseInt(numberMatch[1], 10) - 1; + } + switch (inputStream.next()) { + case '.': + return cm.getCursor().line; + case '$': + return cm.lastLine(); + case '\'': + var mark = cm.state.vim.marks[inputStream.next()]; + if (mark && mark.find()) { + return mark.find().line; + } + throw new Error('Mark not set'); + default: + inputStream.backUp(1); + return undefined; + } + }, + parseCommandArgs_: function(inputStream, params, command) { + if (inputStream.eol()) { + return; + } + params.argString = inputStream.match(/.*/)[0]; + // Parse command-line arguments + var delim = command.argDelimiter || /\s+/; + var args = trim(params.argString).split(delim); + if (args.length && args[0]) { + params.args = args; + } + }, + matchCommand_: function(commandName) { + // Return the command in the command map that matches the shortest + // prefix of the passed in command name. The match is guaranteed to be + // unambiguous if the defaultExCommandMap's shortNames are set up + // correctly. (see @code{defaultExCommandMap}). + for (var i = commandName.length; i > 0; i--) { + var prefix = commandName.substring(0, i); + if (this.commandMap_[prefix]) { + var command = this.commandMap_[prefix]; + if (command.name.indexOf(commandName) === 0) { + return command; + } + } + } + return null; + }, + buildCommandMap_: function() { + this.commandMap_ = {}; + for (var i = 0; i < defaultExCommandMap.length; i++) { + var command = defaultExCommandMap[i]; + var key = command.shortName || command.name; + this.commandMap_[key] = command; + } + }, + map: function(lhs, rhs, ctx) { + if (lhs != ':' && lhs.charAt(0) == ':') { + if (ctx) { throw Error('Mode not supported for ex mappings'); } + var commandName = lhs.substring(1); + if (rhs != ':' && rhs.charAt(0) == ':') { + // Ex to Ex mapping + this.commandMap_[commandName] = { + name: commandName, + type: 'exToEx', + toInput: rhs.substring(1), + user: true + }; + } else { + // Ex to key mapping + this.commandMap_[commandName] = { + name: commandName, + type: 'exToKey', + toKeys: rhs, + user: true + }; + } + } else { + if (rhs != ':' && rhs.charAt(0) == ':') { + // Key to Ex mapping. + var mapping = { + keys: lhs, + type: 'keyToEx', + exArgs: { input: rhs.substring(1) }, + user: true}; + if (ctx) { mapping.context = ctx; } + defaultKeymap.unshift(mapping); + } else { + // Key to key mapping + var mapping = { + keys: lhs, + type: 'keyToKey', + toKeys: rhs, + user: true + }; + if (ctx) { mapping.context = ctx; } + defaultKeymap.unshift(mapping); + } + } + }, + unmap: function(lhs, ctx) { + if (lhs != ':' && lhs.charAt(0) == ':') { + // Ex to Ex or Ex to key mapping + if (ctx) { throw Error('Mode not supported for ex mappings'); } + var commandName = lhs.substring(1); + if (this.commandMap_[commandName] && this.commandMap_[commandName].user) { + delete this.commandMap_[commandName]; + return; + } + } else { + // Key to Ex or key to key mapping + var keys = lhs; + for (var i = 0; i < defaultKeymap.length; i++) { + if (keys == defaultKeymap[i].keys + && defaultKeymap[i].context === ctx + && defaultKeymap[i].user) { + defaultKeymap.splice(i, 1); + return; + } + } + } + throw Error('No such mapping.'); + } + }; + + var exCommands = { + map: function(cm, params, ctx) { + var mapArgs = params.args; + if (!mapArgs || mapArgs.length < 2) { + if (cm) { + showConfirm(cm, 'Invalid mapping: ' + params.input); + } + return; + } + exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx); + }, + imap: function(cm, params) { this.map(cm, params, 'insert'); }, + nmap: function(cm, params) { this.map(cm, params, 'normal'); }, + vmap: function(cm, params) { this.map(cm, params, 'visual'); }, + unmap: function(cm, params, ctx) { + var mapArgs = params.args; + if (!mapArgs || mapArgs.length < 1) { + if (cm) { + showConfirm(cm, 'No such mapping: ' + params.input); + } + return; + } + exCommandDispatcher.unmap(mapArgs[0], ctx); + }, + move: function(cm, params) { + commandDispatcher.processCommand(cm, cm.state.vim, { + type: 'motion', + motion: 'moveToLineOrEdgeOfDocument', + motionArgs: { forward: false, explicitRepeat: true, + linewise: true }, + repeatOverride: params.line+1}); + }, + set: function(cm, params) { + var setArgs = params.args; + if (!setArgs || setArgs.length < 1) { + if (cm) { + showConfirm(cm, 'Invalid mapping: ' + params.input); + } + return; + } + var expr = setArgs[0].split('='); + var optionName = expr[0]; + var value = expr[1]; + var forceGet = false; + + if (optionName.charAt(optionName.length - 1) == '?') { + // If post-fixed with ?, then the set is actually a get. + if (value) { throw Error('Trailing characters: ' + params.argString); } + optionName = optionName.substring(0, optionName.length - 1); + forceGet = true; + } + if (value === undefined && optionName.substring(0, 2) == 'no') { + // To set boolean options to false, the option name is prefixed with + // 'no'. + optionName = optionName.substring(2); + value = false; + } + var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean'; + if (optionIsBoolean && value == undefined) { + // Calling set with a boolean option sets it to true. + value = true; + } + if (!optionIsBoolean && !value || forceGet) { + var oldValue = getOption(optionName); + // If no value is provided, then we assume this is a get. + if (oldValue === true || oldValue === false) { + showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName); + } else { + showConfirm(cm, ' ' + optionName + '=' + oldValue); + } + } else { + setOption(optionName, value); + } + }, + registers: function(cm,params) { + var regArgs = params.args; + var registers = vimGlobalState.registerController.registers; + var regInfo = '----------Registers----------

    '; + if (!regArgs) { + for (var registerName in registers) { + var text = registers[registerName].toString(); + if (text.length) { + regInfo += '"' + registerName + ' ' + text + '
    '; + } + } + } else { + var registerName; + regArgs = regArgs.join(''); + for (var i = 0; i < regArgs.length; i++) { + registerName = regArgs.charAt(i); + if (!vimGlobalState.registerController.isValidRegister(registerName)) { + continue; + } + var register = registers[registerName] || new Register(); + regInfo += '"' + registerName + ' ' + register.toString() + '
    '; + } + } + showConfirm(cm, regInfo); + }, + sort: function(cm, params) { + var reverse, ignoreCase, unique, number; + function parseArgs() { + if (params.argString) { + var args = new CodeMirror.StringStream(params.argString); + if (args.eat('!')) { reverse = true; } + if (args.eol()) { return; } + if (!args.eatSpace()) { return 'Invalid arguments'; } + var opts = args.match(/[a-z]+/); + if (opts) { + opts = opts[0]; + ignoreCase = opts.indexOf('i') != -1; + unique = opts.indexOf('u') != -1; + var decimal = opts.indexOf('d') != -1 && 1; + var hex = opts.indexOf('x') != -1 && 1; + var octal = opts.indexOf('o') != -1 && 1; + if (decimal + hex + octal > 1) { return 'Invalid arguments'; } + number = decimal && 'decimal' || hex && 'hex' || octal && 'octal'; + } + if (args.eatSpace() && args.match(/\/.*\//)) { 'patterns not supported'; } + } + } + var err = parseArgs(); + if (err) { + showConfirm(cm, err + ': ' + params.argString); + return; + } + var lineStart = params.line || cm.firstLine(); + var lineEnd = params.lineEnd || params.line || cm.lastLine(); + if (lineStart == lineEnd) { return; } + var curStart = Pos(lineStart, 0); + var curEnd = Pos(lineEnd, lineLength(cm, lineEnd)); + var text = cm.getRange(curStart, curEnd).split('\n'); + var numberRegex = (number == 'decimal') ? /(-?)([\d]+)/ : + (number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i : + (number == 'octal') ? /([0-7]+)/ : null; + var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null; + var numPart = [], textPart = []; + if (number) { + for (var i = 0; i < text.length; i++) { + if (numberRegex.exec(text[i])) { + numPart.push(text[i]); + } else { + textPart.push(text[i]); + } + } + } else { + textPart = text; + } + function compareFn(a, b) { + if (reverse) { var tmp; tmp = a; a = b; b = tmp; } + if (ignoreCase) { a = a.toLowerCase(); b = b.toLowerCase(); } + var anum = number && numberRegex.exec(a); + var bnum = number && numberRegex.exec(b); + if (!anum) { return a < b ? -1 : 1; } + anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix); + bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix); + return anum - bnum; + } + numPart.sort(compareFn); + textPart.sort(compareFn); + text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart); + if (unique) { // Remove duplicate lines + var textOld = text; + var lastLine; + text = []; + for (var i = 0; i < textOld.length; i++) { + if (textOld[i] != lastLine) { + text.push(textOld[i]); + } + lastLine = textOld[i]; + } + } + cm.replaceRange(text.join('\n'), curStart, curEnd); + }, + global: function(cm, params) { + // a global command is of the form + // :[range]g/pattern/[cmd] + // argString holds the string /pattern/[cmd] + var argString = params.argString; + if (!argString) { + showConfirm(cm, 'Regular Expression missing from global'); + return; + } + // range is specified here + var lineStart = (params.line !== undefined) ? params.line : cm.firstLine(); + var lineEnd = params.lineEnd || params.line || cm.lastLine(); + // get the tokens from argString + var tokens = splitBySlash(argString); + var regexPart = argString, cmd; + if (tokens.length) { + regexPart = tokens[0]; + cmd = tokens.slice(1, tokens.length).join('/'); + } + if (regexPart) { + // If regex part is empty, then use the previous query. Otherwise + // use the regex part as the new query. + try { + updateSearchQuery(cm, regexPart, true /** ignoreCase */, + true /** smartCase */); + } catch (e) { + showConfirm(cm, 'Invalid regex: ' + regexPart); + return; + } + } + // now that we have the regexPart, search for regex matches in the + // specified range of lines + var query = getSearchState(cm).getQuery(); + var matchedLines = [], content = ''; + for (var i = lineStart; i <= lineEnd; i++) { + var matched = query.test(cm.getLine(i)); + if (matched) { + matchedLines.push(i+1); + content+= cm.getLine(i) + '
    '; + } + } + // if there is no [cmd], just display the list of matched lines + if (!cmd) { + showConfirm(cm, content); + return; + } + var index = 0; + var nextCommand = function() { + if (index < matchedLines.length) { + var command = matchedLines[index] + cmd; + exCommandDispatcher.processCommand(cm, command, { + callback: nextCommand + }); + } + index++; + }; + nextCommand(); + }, + substitute: function(cm, params) { + if (!cm.getSearchCursor) { + throw new Error('Search feature not available. Requires searchcursor.js or ' + + 'any other getSearchCursor implementation.'); + } + var argString = params.argString; + var tokens = argString ? splitBySlash(argString) : []; + var regexPart, replacePart = '', trailing, flagsPart, count; + var confirm = false; // Whether to confirm each replace. + var global = false; // True to replace all instances on a line, false to replace only 1. + if (tokens.length) { + regexPart = tokens[0]; + replacePart = tokens[1]; + if (replacePart !== undefined) { + if (getOption('pcre')) { + replacePart = unescapeRegexReplace(replacePart); + } else { + replacePart = translateRegexReplace(replacePart); + } + vimGlobalState.lastSubstituteReplacePart = replacePart; + } + trailing = tokens[2] ? tokens[2].split(' ') : []; + } else { + // either the argString is empty or its of the form ' hello/world' + // actually splitBySlash returns a list of tokens + // only if the string starts with a '/' + if (argString && argString.length) { + showConfirm(cm, 'Substitutions should be of the form ' + + ':s/pattern/replace/'); + return; + } + } + // After the 3rd slash, we can have flags followed by a space followed + // by count. + if (trailing) { + flagsPart = trailing[0]; + count = parseInt(trailing[1]); + if (flagsPart) { + if (flagsPart.indexOf('c') != -1) { + confirm = true; + flagsPart.replace('c', ''); + } + if (flagsPart.indexOf('g') != -1) { + global = true; + flagsPart.replace('g', ''); + } + regexPart = regexPart + '/' + flagsPart; + } + } + if (regexPart) { + // If regex part is empty, then use the previous query. Otherwise use + // the regex part as the new query. + try { + updateSearchQuery(cm, regexPart, true /** ignoreCase */, + true /** smartCase */); + } catch (e) { + showConfirm(cm, 'Invalid regex: ' + regexPart); + return; + } + } + replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart; + if (replacePart === undefined) { + showConfirm(cm, 'No previous substitute regular expression'); + return; + } + var state = getSearchState(cm); + var query = state.getQuery(); + var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line; + var lineEnd = params.lineEnd || lineStart; + if (count) { + lineStart = lineEnd; + lineEnd = lineStart + count - 1; + } + var startPos = clipCursorToContent(cm, Pos(lineStart, 0)); + var cursor = cm.getSearchCursor(query, startPos); + doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback); + }, + redo: CodeMirror.commands.redo, + undo: CodeMirror.commands.undo, + write: function(cm) { + if (CodeMirror.commands.save) { + // If a save command is defined, call it. + CodeMirror.commands.save(cm); + } else { + // Saves to text area if no save command is defined. + cm.save(); + } + }, + nohlsearch: function(cm) { + clearSearchHighlight(cm); + }, + delmarks: function(cm, params) { + if (!params.argString || !trim(params.argString)) { + showConfirm(cm, 'Argument required'); + return; + } + + var state = cm.state.vim; + var stream = new CodeMirror.StringStream(trim(params.argString)); + while (!stream.eol()) { + stream.eatSpace(); + + // Record the streams position at the beginning of the loop for use + // in error messages. + var count = stream.pos; + + if (!stream.match(/[a-zA-Z]/, false)) { + showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); + return; + } + + var sym = stream.next(); + // Check if this symbol is part of a range + if (stream.match('-', true)) { + // This symbol is part of a range. + + // The range must terminate at an alphabetic character. + if (!stream.match(/[a-zA-Z]/, false)) { + showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); + return; + } + + var startMark = sym; + var finishMark = stream.next(); + // The range must terminate at an alphabetic character which + // shares the same case as the start of the range. + if (isLowerCase(startMark) && isLowerCase(finishMark) || + isUpperCase(startMark) && isUpperCase(finishMark)) { + var start = startMark.charCodeAt(0); + var finish = finishMark.charCodeAt(0); + if (start >= finish) { + showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); + return; + } + + // Because marks are always ASCII values, and we have + // determined that they are the same case, we can use + // their char codes to iterate through the defined range. + for (var j = 0; j <= finish - start; j++) { + var mark = String.fromCharCode(start + j); + delete state.marks[mark]; + } + } else { + showConfirm(cm, 'Invalid argument: ' + startMark + '-'); + return; + } + } else { + // This symbol is a valid mark, and is not part of a range. + delete state.marks[sym]; + } + } + } + }; + + var exCommandDispatcher = new ExCommandDispatcher(); + + /** + * @param {CodeMirror} cm CodeMirror instance we are in. + * @param {boolean} confirm Whether to confirm each replace. + * @param {Cursor} lineStart Line to start replacing from. + * @param {Cursor} lineEnd Line to stop replacing at. + * @param {RegExp} query Query for performing matches with. + * @param {string} replaceWith Text to replace matches with. May contain $1, + * $2, etc for replacing captured groups using Javascript replace. + * @param {function()} callback A callback for when the replace is done. + */ + function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query, + replaceWith, callback) { + // Set up all the functions. + cm.state.vim.exMode = true; + var done = false; + var lastPos = searchCursor.from(); + function replaceAll() { + cm.operation(function() { + while (!done) { + replace(); + next(); + } + stop(); + }); + } + function replace() { + var text = cm.getRange(searchCursor.from(), searchCursor.to()); + var newText = text.replace(query, replaceWith); + searchCursor.replace(newText); + } + function next() { + var found; + // The below only loops to skip over multiple occurrences on the same + // line when 'global' is not true. + while(found = searchCursor.findNext() && + isInRange(searchCursor.from(), lineStart, lineEnd)) { + if (!global && lastPos && searchCursor.from().line == lastPos.line) { + continue; + } + cm.scrollIntoView(searchCursor.from(), 30); + cm.setSelection(searchCursor.from(), searchCursor.to()); + lastPos = searchCursor.from(); + done = false; + return; + } + done = true; + } + function stop(close) { + if (close) { close(); } + cm.focus(); + if (lastPos) { + cm.setCursor(lastPos); + var vim = cm.state.vim; + vim.exMode = false; + vim.lastHPos = vim.lastHSPos = lastPos.ch; + } + if (callback) { callback(); } + } + function onPromptKeyDown(e, _value, close) { + // Swallow all keys. + CodeMirror.e_stop(e); + var keyName = CodeMirror.keyName(e); + switch (keyName) { + case 'Y': + replace(); next(); break; + case 'N': + next(); break; + case 'A': + // replaceAll contains a call to close of its own. We don't want it + // to fire too early or multiple times. + var savedCallback = callback; + callback = undefined; + cm.operation(replaceAll); + callback = savedCallback; + break; + case 'L': + replace(); + // fall through and exit. + case 'Q': + case 'Esc': + case 'Ctrl-C': + case 'Ctrl-[': + stop(close); + break; + } + if (done) { stop(close); } + return true; + } + + // Actually do replace. + next(); + if (done) { + showConfirm(cm, 'No matches for ' + query.source); + return; + } + if (!confirm) { + replaceAll(); + if (callback) { callback(); }; + return; + } + showPrompt(cm, { + prefix: 'replace with ' + replaceWith + ' (y/n/a/q/l)', + onKeyDown: onPromptKeyDown + }); + } + + CodeMirror.keyMap.vim = { + attach: attachVimMap, + detach: detachVimMap + }; + + function exitInsertMode(cm) { + var vim = cm.state.vim; + var macroModeState = vimGlobalState.macroModeState; + var insertModeChangeRegister = vimGlobalState.registerController.getRegister('.'); + var isPlaying = macroModeState.isPlaying; + var lastChange = macroModeState.lastInsertModeChanges; + // In case of visual block, the insertModeChanges are not saved as a + // single word, so we convert them to a single word + // so as to update the ". register as expected in real vim. + var text = []; + if (!isPlaying) { + var selLength = lastChange.inVisualBlock ? vim.lastSelection.visualBlock.height : 1; + var changes = lastChange.changes; + var text = []; + var i = 0; + // In case of multiple selections in blockwise visual, + // the inserted text, for example: 'foo', is stored as + // 'f', 'f', InsertModeKey 'o', 'o', 'o', 'o'. (if you have a block with 2 lines). + // We push the contents of the changes array as per the following: + // 1. In case of InsertModeKey, just increment by 1. + // 2. In case of a character, jump by selLength (2 in the example). + while (i < changes.length) { + // This loop will convert 'ffoooo' to 'foo'. + text.push(changes[i]); + if (changes[i] instanceof InsertModeKey) { + i++; + } else { + i+= selLength; + } + } + lastChange.changes = text; + cm.off('change', onChange); + CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); + } + if (!isPlaying && vim.insertModeRepeat > 1) { + // Perform insert mode repeat for commands like 3,a and 3,o. + repeatLastEdit(cm, vim, vim.insertModeRepeat - 1, + true /** repeatForInsert */); + vim.lastEditInputState.repeatOverride = vim.insertModeRepeat; + } + delete vim.insertModeRepeat; + vim.insertMode = false; + cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1); + cm.setOption('keyMap', 'vim'); + cm.setOption('disableInput', true); + cm.toggleOverwrite(false); // exit replace mode if we were in it. + // update the ". register before exiting insert mode + insertModeChangeRegister.setText(lastChange.changes.join('')); + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + if (macroModeState.isRecording) { + logInsertModeChange(macroModeState); + } + } + + // The timeout in milliseconds for the two-character ESC keymap should be + // adjusted according to your typing speed to prevent false positives. + defineOption('insertModeEscKeysTimeout', 200, 'number'); + + CodeMirror.keyMap['vim-insert'] = { + // TODO: override navigation keys so that Esc will cancel automatic + // indentation from o, O, i_ + 'Ctrl-N': 'autocomplete', + 'Ctrl-P': 'autocomplete', + 'Enter': function(cm) { + var fn = CodeMirror.commands.newlineAndIndentContinueComment || + CodeMirror.commands.newlineAndIndent; + fn(cm); + }, + fallthrough: ['default'], + attach: attachVimMap, + detach: detachVimMap + }; + + CodeMirror.keyMap['await-second'] = { + fallthrough: ['vim-insert'], + attach: attachVimMap, + detach: detachVimMap + }; + + CodeMirror.keyMap['vim-replace'] = { + 'Backspace': 'goCharLeft', + fallthrough: ['vim-insert'], + attach: attachVimMap, + detach: detachVimMap + }; + + function executeMacroRegister(cm, vim, macroModeState, registerName) { + var register = vimGlobalState.registerController.getRegister(registerName); + var keyBuffer = register.keyBuffer; + var imc = 0; + macroModeState.isPlaying = true; + macroModeState.replaySearchQueries = register.searchQueries.slice(0); + for (var i = 0; i < keyBuffer.length; i++) { + var text = keyBuffer[i]; + var match, key; + while (text) { + // Pull off one command key, which is either a single character + // or a special sequence wrapped in '<' and '>', e.g. ''. + match = (/<\w+-.+?>|<\w+>|./).exec(text); + key = match[0]; + text = text.substring(match.index + key.length); + CodeMirror.Vim.handleKey(cm, key, 'macro'); + if (vim.insertMode) { + var changes = register.insertModeChanges[imc++].changes; + vimGlobalState.macroModeState.lastInsertModeChanges.changes = + changes; + repeatInsertModeChanges(cm, changes, 1); + exitInsertMode(cm); + } + } + }; + macroModeState.isPlaying = false; + } + + function logKey(macroModeState, key) { + if (macroModeState.isPlaying) { return; } + var registerName = macroModeState.latestRegister; + var register = vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.pushText(key); + } + } + + function logInsertModeChange(macroModeState) { + if (macroModeState.isPlaying) { return; } + var registerName = macroModeState.latestRegister; + var register = vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.pushInsertModeChanges(macroModeState.lastInsertModeChanges); + } + } + + function logSearchQuery(macroModeState, query) { + if (macroModeState.isPlaying) { return; } + var registerName = macroModeState.latestRegister; + var register = vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.pushSearchQuery(query); + } + } + + /** + * Listens for changes made in insert mode. + * Should only be active in insert mode. + */ + function onChange(_cm, changeObj) { + var macroModeState = vimGlobalState.macroModeState; + var lastChange = macroModeState.lastInsertModeChanges; + if (!macroModeState.isPlaying) { + while(changeObj) { + lastChange.expectCursorActivityForChange = true; + if (changeObj.origin == '+input' || changeObj.origin == 'paste' + || changeObj.origin === undefined /* only in testing */) { + var text = changeObj.text.join('\n'); + lastChange.changes.push(text); + } + // Change objects may be chained with next. + changeObj = changeObj.next; + } + } + } + + /** + * Listens for any kind of cursor activity on CodeMirror. + */ + function onCursorActivity(cm) { + var vim = cm.state.vim; + if (vim.insertMode) { + // Tracking cursor activity in insert mode (for macro support). + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isPlaying) { return; } + var lastChange = macroModeState.lastInsertModeChanges; + if (lastChange.expectCursorActivityForChange) { + lastChange.expectCursorActivityForChange = false; + } else { + // Cursor moved outside the context of an edit. Reset the change. + lastChange.changes = []; + } + } else { + handleExternalSelection(cm, vim); + } + if (vim.visualMode) { + var from, head; + from = head = cm.getCursor('head'); + var anchor = cm.getCursor('anchor'); + var to = Pos(head.line, from.ch + (cursorIsBefore(anchor, head) ? -1 : 1)); + if (cursorIsBefore(to, from)) { + var temp = from; + from = to; + to = temp; + } + if (vim.fakeCursor) { + vim.fakeCursor.clear(); + } + vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); + } + } + + function handleExternalSelection(cm, vim) { + var anchor = cm.getCursor('anchor'); + var head = cm.getCursor('head'); + // Enter or exit visual mode to match mouse selection. + if (vim.visualMode && cursorEqual(head, anchor) && lineLength(cm, head.line) > head.ch) { + exitVisualMode(cm); + } else if (!cm.curOp.isVimOp && !vim.visualMode && !vim.insertMode && cm.somethingSelected()) { + vim.visualMode = true; + vim.visualLine = false; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); + } + if (!cm.curOp.isVimOp) { + if (vim.visualMode) { + updateMark(cm, vim, '<', cursorMin(head, anchor)); + updateMark(cm, vim, '>', cursorMax(head, anchor)); + } else if (!vim.insertMode) { + // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse. + vim.lastHPos = cm.getCursor().ch; + } + } + } + + /** Wrapper for special keys pressed in insert mode */ + function InsertModeKey(keyName) { + this.keyName = keyName; + } + + /** + * Handles raw key down events from the text area. + * - Should only be active in insert mode. + * - For recording deletes in insert mode. + */ + function onKeyEventTargetKeyDown(e) { + var macroModeState = vimGlobalState.macroModeState; + var lastChange = macroModeState.lastInsertModeChanges; + var keyName = CodeMirror.keyName(e); + function onKeyFound() { + lastChange.changes.push(new InsertModeKey(keyName)); + return true; + } + if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) { + CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound); + } + } + + /** + * Repeats the last edit, which includes exactly 1 command and at most 1 + * insert. Operator and motion commands are read from lastEditInputState, + * while action commands are read from lastEditActionCommand. + * + * If repeatForInsert is true, then the function was called by + * exitInsertMode to repeat the insert mode changes the user just made. The + * corresponding enterInsertMode call was made with a count. + */ + function repeatLastEdit(cm, vim, repeat, repeatForInsert) { + var macroModeState = vimGlobalState.macroModeState; + macroModeState.isPlaying = true; + var isAction = !!vim.lastEditActionCommand; + var cachedInputState = vim.inputState; + function repeatCommand() { + if (isAction) { + commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand); + } else { + commandDispatcher.evalInput(cm, vim); + } + } + function repeatInsert(repeat) { + if (macroModeState.lastInsertModeChanges.changes.length > 0) { + // For some reason, repeat cw in desktop VIM does not repeat + // insert mode changes. Will conform to that behavior. + repeat = !vim.lastEditActionCommand ? 1 : repeat; + var changeObject = macroModeState.lastInsertModeChanges; + repeatInsertModeChanges(cm, changeObject.changes, repeat); + } + } + vim.inputState = vim.lastEditInputState; + if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) { + // o and O repeat have to be interlaced with insert repeats so that the + // insertions appear on separate lines instead of the last line. + for (var i = 0; i < repeat; i++) { + repeatCommand(); + repeatInsert(1); + } + } else { + if (!repeatForInsert) { + // Hack to get the cursor to end up at the right place. If I is + // repeated in insert mode repeat, cursor will be 1 insert + // change set left of where it should be. + repeatCommand(); + } + repeatInsert(repeat); + } + vim.inputState = cachedInputState; + if (vim.insertMode && !repeatForInsert) { + // Don't exit insert mode twice. If repeatForInsert is set, then we + // were called by an exitInsertMode call lower on the stack. + exitInsertMode(cm); + } + macroModeState.isPlaying = false; + }; + + function repeatInsertModeChanges(cm, changes, repeat) { + function keyHandler(binding) { + if (typeof binding == 'string') { + CodeMirror.commands[binding](cm); + } else { + binding(cm); + } + return true; + } + var curStart = cm.getCursor(); + var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; + if (inVisualBlock) { + // Set up block selection again for repeating the changes. + var vim = cm.state.vim; + var block = vim.lastSelection.visualBlock; + var curEnd = Pos(curStart.line + block.height-1, curStart.ch); + cm.setCursor(curStart); + selectBlock(cm, curEnd); + repeat = cm.listSelections().length; + cm.setCursor(curStart); + } + for (var i = 0; i < repeat; i++) { + for (var j = 0; j < changes.length; j++) { + var change = changes[j]; + if (change instanceof InsertModeKey) { + CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler); + } else { + var cur = cm.getCursor(); + cm.replaceRange(change, cur, cur); + } + } + if (inVisualBlock) { + curStart.line++; + cm.setCursor(curStart); + } + } + } + + resetVimGlobalState(); + //}; + // Initialize Vim and make it available as an API. + CodeMirror.Vim = Vim(); +}); diff --git a/lib/ace/keyboard/vim2_test.js b/lib/ace/keyboard/vim2_test.js new file mode 100644 index 00000000..7f016c47 --- /dev/null +++ b/lib/ace/keyboard/vim2_test.js @@ -0,0 +1,3614 @@ +var code = '' + +' wOrd1 (#%\n' + +' word3] \n' + +'aopop pop 0 1 2 3 4\n' + +' (a) [b] {c} \n' + +'int getchar(void) {\n' + +' static char buf[BUFSIZ];\n' + +' static char *bufp = buf;\n' + +' if (n == 0) { /* buffer is empty */\n' + +' n = read(0, buf, sizeof buf);\n' + +' bufp = buf;\n' + +' }\n' + +'\n' + +' return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n' + +' \n' + +'}\n'; + +var lines = (function() { + lineText = code.split('\n'); + var ret = []; + for (var i = 0; i < lineText.length; i++) { + ret[i] = { + line: i, + length: lineText[i].length, + lineText: lineText[i], + textStart: /^\s*/.exec(lineText[i])[0].length + }; + } + return ret; +})(); +var endOfDocument = makeCursor(lines.length - 1, + lines[lines.length - 1].length); +var wordLine = lines[0]; +var bigWordLine = lines[1]; +var charLine = lines[2]; +var bracesLine = lines[3]; +var seekBraceLine = lines[4]; + +var word1 = { + start: { line: wordLine.line, ch: 1 }, + end: { line: wordLine.line, ch: 5 } +}; +var word2 = { + start: { line: wordLine.line, ch: word1.end.ch + 2 }, + end: { line: wordLine.line, ch: word1.end.ch + 4 } +}; +var word3 = { + start: { line: bigWordLine.line, ch: 1 }, + end: { line: bigWordLine.line, ch: 5 } +}; +var bigWord1 = word1; +var bigWord2 = word2; +var bigWord3 = { + start: { line: bigWordLine.line, ch: 1 }, + end: { line: bigWordLine.line, ch: 7 } +}; +var bigWord4 = { + start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 }, + end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 } +}; + +var oChars = [ { line: charLine.line, ch: 1 }, + { line: charLine.line, ch: 3 }, + { line: charLine.line, ch: 7 } ]; +var pChars = [ { line: charLine.line, ch: 2 }, + { line: charLine.line, ch: 4 }, + { line: charLine.line, ch: 6 }, + { line: charLine.line, ch: 8 } ]; +var numChars = [ { line: charLine.line, ch: 10 }, + { line: charLine.line, ch: 12 }, + { line: charLine.line, ch: 14 }, + { line: charLine.line, ch: 16 }, + { line: charLine.line, ch: 18 }]; +var parens1 = { + start: { line: bracesLine.line, ch: 1 }, + end: { line: bracesLine.line, ch: 3 } +}; +var squares1 = { + start: { line: bracesLine.line, ch: 5 }, + end: { line: bracesLine.line, ch: 7 } +}; +var curlys1 = { + start: { line: bracesLine.line, ch: 9 }, + end: { line: bracesLine.line, ch: 11 } +}; +var seekOutside = { + start: { line: seekBraceLine.line, ch: 1 }, + end: { line: seekBraceLine.line, ch: 16 } +}; +var seekInside = { + start: { line: seekBraceLine.line, ch: 14 }, + end: { line: seekBraceLine.line, ch: 11 } +}; + +function copyCursor(cur) { + return { ch: cur.ch, line: cur.line }; +} + +function forEach(arr, func) { + for (var i = 0; i < arr.length; i++) { + func(arr[i], i, arr); + } +} + +function testVim(name, run, opts, expectedFail) { + var vimOpts = { + lineNumbers: true, + vimMode: true, + showCursorWhenSelecting: true, + value: code + }; + for (var prop in opts) { + if (opts.hasOwnProperty(prop)) { + vimOpts[prop] = opts[prop]; + } + } + return test('vim_' + name, function() { + var place = document.getElementById("testground"); + var cm = CodeMirror(place, vimOpts); + var vim = CodeMirror.Vim.maybeInitVimState_(cm); + + function doKeysFn(cm) { + return function(args) { + if (args instanceof Array) { + arguments = args; + } + for (var i = 0; i < arguments.length; i++) { + CodeMirror.Vim.handleKey(cm, arguments[i]); + } + } + } + function doInsertModeKeysFn(cm) { + return function(args) { + if (args instanceof Array) { arguments = args; } + function executeHandler(handler) { + if (typeof handler == 'string') { + CodeMirror.commands[handler](cm); + } else { + handler(cm); + } + return true; + } + for (var i = 0; i < arguments.length; i++) { + var key = arguments[i]; + // Find key in keymap and handle. + var handled = CodeMirror.lookupKey(key, 'vim-insert', executeHandler); + // Record for insert mode. + if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') { + var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges; + if (lastChange) { + lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key)); + } + } + } + } + } + function doExFn(cm) { + return function(command) { + cm.openDialog = helpers.fakeOpenDialog(command); + helpers.doKeys(':'); + } + } + function assertCursorAtFn(cm) { + return function(line, ch) { + var pos; + if (ch == null && typeof line.line == 'number') { + pos = line; + } else { + pos = makeCursor(line, ch); + } + eqPos(pos, cm.getCursor()); + } + } + function fakeOpenDialog(result) { + return function(text, callback) { + return callback(result); + } + } + function fakeOpenNotification(matcher) { + return function(text) { + matcher(text); + } + } + var helpers = { + doKeys: doKeysFn(cm), + // Warning: Only emulates keymap events, not character insertions. Use + // replaceRange to simulate character insertions. + // Keys are in CodeMirror format, NOT vim format. + doInsertModeKeys: doInsertModeKeysFn(cm), + doEx: doExFn(cm), + assertCursorAt: assertCursorAtFn(cm), + fakeOpenDialog: fakeOpenDialog, + fakeOpenNotification: fakeOpenNotification, + getRegisterController: function() { + return CodeMirror.Vim.getRegisterController(); + } + } + CodeMirror.Vim.resetVimGlobalState_(); + var successful = false; + var savedOpenNotification = cm.openNotification; + try { + run(cm, vim, helpers); + successful = true; + } finally { + cm.openNotification = savedOpenNotification; + if (!successful || verbose) { + place.style.visibility = "visible"; + } else { + place.removeChild(cm.getWrapperElement()); + } + } + }, expectedFail); +}; +testVim('qq@q', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'q', 'l', 'l', 'q'); + helpers.assertCursorAt(0,2); + helpers.doKeys('@', 'q'); + helpers.assertCursorAt(0,4); +}, { value: ' '}); +testVim('@@', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'q', 'l', 'l', 'q'); + helpers.assertCursorAt(0,2); + helpers.doKeys('@', 'q'); + helpers.assertCursorAt(0,4); + helpers.doKeys('@', '@'); + helpers.assertCursorAt(0,6); +}, { value: ' '}); +var jumplistScene = ''+ + 'word\n'+ + '(word)\n'+ + '{word\n'+ + 'word.\n'+ + '\n'+ + 'word search\n'+ + '}word\n'+ + 'word\n'+ + 'word\n'; +function testJumplist(name, keys, endPos, startPos, dialog) { + endPos = makeCursor(endPos[0], endPos[1]); + startPos = makeCursor(startPos[0], startPos[1]); + testVim(name, function(cm, vim, helpers) { + CodeMirror.Vim.resetVimGlobalState_(); + if(dialog)cm.openDialog = helpers.fakeOpenDialog('word'); + cm.setCursor(startPos); + helpers.doKeys.apply(null, keys); + helpers.assertCursorAt(endPos); + }, {value: jumplistScene}); +}; +testJumplist('jumplist_H', ['H', ''], [5,2], [5,2]); +testJumplist('jumplist_M', ['M', ''], [2,2], [2,2]); +testJumplist('jumplist_L', ['L', ''], [2,2], [2,2]); +testJumplist('jumplist_[[', ['[', '[', ''], [5,2], [5,2]); +testJumplist('jumplist_]]', [']', ']', ''], [2,2], [2,2]); +testJumplist('jumplist_G', ['G', ''], [5,2], [5,2]); +testJumplist('jumplist_gg', ['g', 'g', ''], [5,2], [5,2]); +testJumplist('jumplist_%', ['%', ''], [1,5], [1,5]); +testJumplist('jumplist_{', ['{', ''], [1,5], [1,5]); +testJumplist('jumplist_}', ['}', ''], [1,5], [1,5]); +testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', ''], [1,0], [1,5]); +testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', ''], [1,5], [1,5]); +testJumplist('jumplist_*_cachedCursor', ['*', ''], [1,3], [1,3]); +testJumplist('jumplist_#_cachedCursor', ['#', ''], [1,3], [1,3]); +testJumplist('jumplist_n', ['#', 'n', ''], [1,1], [2,3]); +testJumplist('jumplist_N', ['#', 'N', ''], [1,1], [2,3]); +testJumplist('jumplist_repeat_', ['*', '*', '*', '3', ''], [2,3], [2,3]); +testJumplist('jumplist_repeat_', ['*', '*', '*', '3', '', '2', ''], [5,0], [2,3]); +testJumplist('jumplist_repeated_motion', ['3', '*', ''], [2,3], [2,3]); +testJumplist('jumplist_/', ['/', ''], [2,3], [2,3], 'dialog'); +testJumplist('jumplist_?', ['?', ''], [2,3], [2,3], 'dialog'); +testJumplist('jumplist_skip_delted_mark', + ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], + [0,2], [0,2]); +testJumplist('jumplist_skip_delted_mark', + ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], + [1,0], [0,2]); + +/** + * @param name Name of the test + * @param keys An array of keys or a string with a single key to simulate. + * @param endPos The expected end position of the cursor. + * @param startPos The position the cursor should start at, defaults to 0, 0. + */ +function testMotion(name, keys, endPos, startPos) { + testVim(name, function(cm, vim, helpers) { + if (!startPos) { + startPos = { line: 0, ch: 0 }; + } + cm.setCursor(startPos); + helpers.doKeys(keys); + helpers.assertCursorAt(endPos); + }); +}; + +function makeCursor(line, ch) { + return { line: line, ch: ch }; +}; + +function offsetCursor(cur, offsetLine, offsetCh) { + return { line: cur.line + offsetLine, ch: cur.ch + offsetCh }; +}; + +// Motion tests +testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4)); +testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4)); +testMotion('h', 'h', makeCursor(0, 0), word1.start); +testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end); +testMotion('l', 'l', makeCursor(0, 1)); +testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2)); +testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end); +testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end); +testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument); +testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end); +testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4)); +testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4)); +testMotion('w', 'w', word1.start); +testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2)); +testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51)); +testMotion('w_repeat', ['2', 'w'], word2.start); +testMotion('w_wrap', ['w'], word3.start, word2.start); +testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument); +testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0)); +testMotion('W', 'W', bigWord1.start); +testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start); +testMotion('e', 'e', word1.end); +testMotion('e_repeat', ['2', 'e'], word2.end); +testMotion('e_wrap', 'e', word3.end, word2.end); +testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument); +testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0)); +testMotion('b', 'b', word3.start, word3.end); +testMotion('b_repeat', ['2', 'b'], word2.start, word3.end); +testMotion('b_wrap', 'b', word2.start, word3.start); +testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0)); +testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument); +testMotion('ge', ['g', 'e'], word2.end, word3.end); +testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start); +testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start); +testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0), + makeCursor(0, 0)); +testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument); +testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart), + makeCursor(3, 1)); +testMotion('gg_repeat', ['3', 'g', 'g'], + makeCursor(lines[2].line, lines[2].textStart)); +testMotion('G', 'G', + makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart), + makeCursor(3, 1)); +testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line, + lines[2].textStart)); +// TODO: Make the test code long enough to test Ctrl-F and Ctrl-B. +testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8)); +testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8)); +testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8)); +testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4)); +testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8)); +testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1)); +testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1), + makeCursor(0, 3)); +testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0)); +testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]); +testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0)); +testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1), + makeCursor(charLine.line, 0)); +testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1), + pChars[0]); +testMotion('F', ['F', 'p'], pChars[0], pChars[1]); +testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]); +testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]); +testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]); +testMotion('%_parens', ['%'], parens1.end, parens1.start); +testMotion('%_squares', ['%'], squares1.end, squares1.start); +testMotion('%_braces', ['%'], curlys1.end, curlys1.start); +testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start); +testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start); +testVim('%_seek_skip', function(cm, vim, helpers) { + cm.setCursor(0,0); + helpers.doKeys(['%']); + helpers.assertCursorAt(0,9); +}, {value:'01234"("()'}); +testVim('%_skip_string', function(cm, vim, helpers) { + cm.setCursor(0,0); + helpers.doKeys(['%']); + helpers.assertCursorAt(0,4); + cm.setCursor(0,2); + helpers.doKeys(['%']); + helpers.assertCursorAt(0,0); +}, {value:'(")")'}); +(')') +testVim('%_skip_comment', function(cm, vim, helpers) { + cm.setCursor(0,0); + helpers.doKeys(['%']); + helpers.assertCursorAt(0,6); + cm.setCursor(0,3); + helpers.doKeys(['%']); + helpers.assertCursorAt(0,0); +}, {value:'(/*)*/)'}); +// Make sure that moving down after going to the end of a line always leaves you +// at the end of a line, but preserves the offset in other cases +testVim('Changing lines after Eol operation', function(cm, vim, helpers) { + cm.setCursor(0,0); + helpers.doKeys(['$']); + helpers.doKeys(['j']); + // After moving to Eol and then down, we should be at Eol of line 2 + helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 }); + helpers.doKeys(['j']); + // After moving down, we should be at Eol of line 3 + helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 }); + helpers.doKeys(['h']); + helpers.doKeys(['j']); + // After moving back one space and then down, since line 4 is shorter than line 2, we should + // be at Eol of line 2 - 1 + helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 }); + helpers.doKeys(['j']); + helpers.doKeys(['j']); + // After moving down again, since line 3 has enough characters, we should be back to the + // same place we were at on line 1 + helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 }); +}); +//making sure gj and gk recover from clipping +testVim('gj_gk_clipping', function(cm,vim,helpers){ + cm.setCursor(0, 1); + helpers.doKeys('g','j','g','j'); + helpers.assertCursorAt(2, 1); + helpers.doKeys('g','k','g','k'); + helpers.assertCursorAt(0, 1); +},{value: 'line 1\n\nline 2'}); +//testing a mix of j/k and gj/gk +testVim('j_k_and_gj_gk', function(cm,vim,helpers){ + cm.setSize(120); + cm.setCursor(0, 0); + //go to the last character on the first line + helpers.doKeys('$'); + //move up/down on the column within the wrapped line + //side-effect: cursor is not locked to eol anymore + helpers.doKeys('g','k'); + var cur=cm.getCursor(); + eq(cur.line,0); + is((cur.ch<176),'gk didn\'t move cursor back (1)'); + helpers.doKeys('g','j'); + helpers.assertCursorAt(0, 176); + //should move to character 177 on line 2 (j/k preserve character index within line) + helpers.doKeys('j'); + //due to different line wrapping, the cursor can be on a different screen-x now + //gj and gk preserve screen-x on movement, much like moveV + helpers.doKeys('3','g','k'); + cur=cm.getCursor(); + eq(cur.line,1); + is((cur.ch<176),'gk didn\'t move cursor back (2)'); + helpers.doKeys('g','j','2','g','j'); + //should return to the same character-index + helpers.doKeys('k'); + helpers.assertCursorAt(0, 176); +},{ lineWrapping:true, value: 'This line is intentially long to test movement of gj and gk over wrapped lines. I will start on the end of this line, then make a step up and back to set the origin for j and k.\nThis line is supposed to be even longer than the previous. I will jump here and make another wiggle with gj and gk, before I jump back to the line above. Both wiggles should not change my cursor\'s target character but both j/k and gj/gk change each other\'s reference position.'}); +testVim('gj_gk', function(cm, vim, helpers) { + if (phantom) return; + cm.setSize(120); + // Test top of document edge case. + cm.setCursor(0, 4); + helpers.doKeys('g', 'j'); + helpers.doKeys('10', 'g', 'k'); + helpers.assertCursorAt(0, 4); + + // Test moving down preserves column position. + helpers.doKeys('g', 'j'); + var pos1 = cm.getCursor(); + var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4}; + helpers.doKeys('g', 'j'); + helpers.assertCursorAt(expectedPos2); + + // Move to the last character + cm.setCursor(0, 0); + // Move left to reset HSPos + helpers.doKeys('h'); + // Test bottom of document edge case. + helpers.doKeys('100', 'g', 'j'); + var endingPos = cm.getCursor(); + is(endingPos != 0, 'gj should not be on wrapped line 0'); + var topLeftCharCoords = cm.charCoords(makeCursor(0, 0)); + var endingCharCoords = cm.charCoords(endingPos); + is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0'); +},{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' }); +testVim('}', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('}'); + helpers.assertCursorAt(1, 0); + cm.setCursor(0, 0); + helpers.doKeys('2', '}'); + helpers.assertCursorAt(4, 0); + cm.setCursor(0, 0); + helpers.doKeys('6', '}'); + helpers.assertCursorAt(5, 0); +}, { value: 'a\n\nb\nc\n\nd' }); +testVim('{', function(cm, vim, helpers) { + cm.setCursor(5, 0); + helpers.doKeys('{'); + helpers.assertCursorAt(4, 0); + cm.setCursor(5, 0); + helpers.doKeys('2', '{'); + helpers.assertCursorAt(1, 0); + cm.setCursor(5, 0); + helpers.doKeys('6', '{'); + helpers.assertCursorAt(0, 0); +}, { value: 'a\n\nb\nc\n\nd' }); + +// Operator tests +testVim('dl', function(cm, vim, helpers) { + var curStart = makeCursor(0, 0); + cm.setCursor(curStart); + helpers.doKeys('d', 'l'); + eq('word1 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(' ', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1 ' }); +testVim('dl_eol', function(cm, vim, helpers) { + cm.setCursor(0, 6); + helpers.doKeys('d', 'l'); + eq(' word1', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(' ', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 6); +}, { value: ' word1 ' }); +testVim('dl_repeat', function(cm, vim, helpers) { + var curStart = makeCursor(0, 0); + cm.setCursor(curStart); + helpers.doKeys('2', 'd', 'l'); + eq('ord1 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(' w', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1 ' }); +testVim('dh', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + helpers.doKeys('d', 'h'); + eq(' wrd1 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('o', register.toString()); + is(!register.linewise); + eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor()); +}, { value: ' word1 ' }); +testVim('dj', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + helpers.doKeys('d', 'j'); + eq(' word3', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(' word1\nword2\n', register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\nword2\n word3' }); +testVim('dj_end_of_document', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + helpers.doKeys('d', 'j'); + eq(' word1 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 3); +}, { value: ' word1 ' }); +testVim('dk', function(cm, vim, helpers) { + var curStart = makeCursor(1, 3); + cm.setCursor(curStart); + helpers.doKeys('d', 'k'); + eq(' word3', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(' word1\nword2\n', register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\nword2\n word3' }); +testVim('dk_start_of_document', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + helpers.doKeys('d', 'k'); + eq(' word1 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 3); +}, { value: ' word1 ' }); +testVim('dw_space', function(cm, vim, helpers) { + var curStart = makeCursor(0, 0); + cm.setCursor(curStart); + helpers.doKeys('d', 'w'); + eq('word1 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(' ', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1 ' }); +testVim('dw_word', function(cm, vim, helpers) { + var curStart = makeCursor(0, 1); + cm.setCursor(curStart); + helpers.doKeys('d', 'w'); + eq(' word2', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1 ', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1 word2' }); +testVim('dw_only_word', function(cm, vim, helpers) { + // Test that if there is only 1 word left, dw deletes till the end of the + // line. + cm.setCursor(0, 1); + helpers.doKeys('d', 'w'); + eq(' ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1 ', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1 ' }); +testVim('dw_eol', function(cm, vim, helpers) { + // Assert that dw does not delete the newline if last word to delete is at end + // of line. + cm.setCursor(0, 1); + helpers.doKeys('d', 'w'); + eq(' \nword2', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\nword2' }); +testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) { + // Assert that dw does not delete the newline if last word to delete is at end + // of line and it is followed by multiple newlines. + cm.setCursor(0, 1); + helpers.doKeys('d', 'w'); + eq(' \n\nword2', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\n\nword2' }); +testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'w'); + eq(' \nword', cm.getValue()); +}, { value: '\n \nword' }); +testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'w'); + eq('word', cm.getValue()); +}, { value: '\nword' }); +testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'w'); + eq('\n', cm.getValue()); +}, { value: '\n\n' }); +testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'w'); + eq('\n \n', cm.getValue()); +}, { value: ' \n \n' }); +testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'w'); + eq('\n\n', cm.getValue()); +}, { value: ' \n\n' }); +testVim('dw_word_whitespace_word', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'w'); + eq('\n \nword2', cm.getValue()); +}, { value: 'word1\n \nword2'}) +testVim('dw_end_of_document', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('d', 'w'); + eq('\nab', cm.getValue()); +}, { value: '\nabc' }); +testVim('dw_repeat', function(cm, vim, helpers) { + // Assert that dw does delete newline if it should go to the next line, and + // that repeat works properly. + cm.setCursor(0, 1); + helpers.doKeys('d', '2', 'w'); + eq(' ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1\nword2', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\nword2' }); +testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'e'); + eq('\n\n', cm.getValue()); +}, { value: 'word\n\n' }); +testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(0, 3); + helpers.doKeys('d', 'e'); + eq('wor', cm.getValue()); +}, { value: 'word\n\n\n' }); +testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'e'); + eq('', cm.getValue()); +}, { value: ' \n\n\n' }); +testVim('de_end_of_document', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('d', 'e'); + eq('\nab', cm.getValue()); +}, { value: '\nabc' }); +testVim('db_empty_lines', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('d', 'b'); + eq('\n\n', cm.getValue()); +}, { value: '\n\n\n' }); +testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('d', 'b'); + eq('\nword', cm.getValue()); +}, { value: '\n\nword' }); +testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(2, 3); + helpers.doKeys('d', 'b'); + eq('\n\nd', cm.getValue()); +}, { value: '\n\nword' }); +testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('d', 'b'); + eq('', cm.getValue()); +}, { value: '\n \n' }); +testVim('db_start_of_document', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'b'); + eq('abc\n', cm.getValue()); +}, { value: 'abc\n' }); +testVim('dge_empty_lines', function(cm, vim, helpers) { + cm.setCursor(1, 0); + helpers.doKeys('d', 'g', 'e'); + // Note: In real VIM the result should be '', but it's not quite consistent, + // since 2 newlines are deleted. But in the similar case of word\n\n, only + // 1 newline is deleted. We'll diverge from VIM's behavior since it's much + // easier this way. + eq('\n', cm.getValue()); +}, { value: '\n\n' }); +testVim('dge_word_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(1, 0); + helpers.doKeys('d', 'g', 'e'); + eq('wor\n', cm.getValue()); +}, { value: 'word\n\n'}); +testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('d', 'g', 'e'); + eq('', cm.getValue()); +}, { value: '\n \n' }); +testVim('dge_start_of_document', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'g', 'e'); + eq('bc\n', cm.getValue()); +}, { value: 'abc\n' }); +testVim('d_inclusive', function(cm, vim, helpers) { + // Assert that when inclusive is set, the character the cursor is on gets + // deleted too. + var curStart = makeCursor(0, 1); + cm.setCursor(curStart); + helpers.doKeys('d', 'e'); + eq(' ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1 ' }); +testVim('d_reverse', function(cm, vim, helpers) { + // Test that deleting in reverse works. + cm.setCursor(1, 0); + helpers.doKeys('d', 'b'); + eq(' word2 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1\n', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\nword2 ' }); +testVim('dd', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, + { line: 1, ch: 0 }); + var expectedLineCount = cm.lineCount() - 1; + helpers.doKeys('d', 'd'); + eq(expectedLineCount, cm.lineCount()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedBuffer, register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, lines[1].textStart); +}); +testVim('dd_prefix_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, + { line: 2, ch: 0 }); + var expectedLineCount = cm.lineCount() - 2; + helpers.doKeys('2', 'd', 'd'); + eq(expectedLineCount, cm.lineCount()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedBuffer, register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, lines[2].textStart); +}); +testVim('dd_motion_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, + { line: 2, ch: 0 }); + var expectedLineCount = cm.lineCount() - 2; + helpers.doKeys('d', '2', 'd'); + eq(expectedLineCount, cm.lineCount()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedBuffer, register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, lines[2].textStart); +}); +testVim('dd_multiply_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, + { line: 6, ch: 0 }); + var expectedLineCount = cm.lineCount() - 6; + helpers.doKeys('2', 'd', '3', 'd'); + eq(expectedLineCount, cm.lineCount()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedBuffer, register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, lines[6].textStart); +}); +testVim('dd_lastline', function(cm, vim, helpers) { + cm.setCursor(cm.lineCount(), 0); + var expectedLineCount = cm.lineCount() - 1; + helpers.doKeys('d', 'd'); + eq(expectedLineCount, cm.lineCount()); + helpers.assertCursorAt(cm.lineCount() - 1, 0); +}); +testVim('dd_only_line', function(cm, vim, helpers) { + cm.setCursor(0, 0); + var expectedRegister = cm.getValue() + "\n"; + helpers.doKeys('d','d'); + eq(1, cm.lineCount()); + eq('', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedRegister, register.toString()); +}, { value: "thisistheonlyline" }); +// Yank commands should behave the exact same as d commands, expect that nothing +// gets deleted. +testVim('yw_repeat', function(cm, vim, helpers) { + // Assert that yw does yank newline if it should go to the next line, and + // that repeat works properly. + var curStart = makeCursor(0, 1); + cm.setCursor(curStart); + helpers.doKeys('y', '2', 'w'); + eq(' word1\nword2', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1\nword2', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1\nword2' }); +testVim('yy_multiply_repeat', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, + { line: 6, ch: 0 }); + var expectedLineCount = cm.lineCount(); + helpers.doKeys('2', 'y', '3', 'y'); + eq(expectedLineCount, cm.lineCount()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedBuffer, register.toString()); + is(register.linewise); + eqPos(curStart, cm.getCursor()); +}); +// Change commands behave like d commands except that it also enters insert +// mode. In addition, when the change is linewise, an additional newline is +// inserted so that insert mode starts on that line. +testVim('cw', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('c', '2', 'w'); + eq(' word3', cm.getValue()); + helpers.assertCursorAt(0, 0); +}, { value: 'word1 word2 word3'}); +testVim('cw_repeat', function(cm, vim, helpers) { + // Assert that cw does delete newline if it should go to the next line, and + // that repeat works properly. + var curStart = makeCursor(0, 1); + cm.setCursor(curStart); + helpers.doKeys('c', '2', 'w'); + eq(' ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1\nword2', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); + eq('vim-insert', cm.getOption('keyMap')); +}, { value: ' word1\nword2' }); +testVim('cc_multiply_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, + { line: 6, ch: 0 }); + var expectedLineCount = cm.lineCount() - 5; + helpers.doKeys('2', 'c', '3', 'c'); + eq(expectedLineCount, cm.lineCount()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedBuffer, register.toString()); + is(register.linewise); + eq('vim-insert', cm.getOption('keyMap')); +}); +testVim('cc_append', function(cm, vim, helpers) { + var expectedLineCount = cm.lineCount(); + cm.setCursor(cm.lastLine(), 0); + helpers.doKeys('c', 'c'); + eq(expectedLineCount, cm.lineCount()); +}); +testVim('c_visual_block', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'c'); + var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); + replacement.pop(); + cm.replaceSelections(replacement); + eq('1hello\n5hello\nahellofg', cm.getValue()); + helpers.doKeys(''); + cm.setCursor(2, 3); + helpers.doKeys('', '2', 'k', 'h', 'C'); + replacement = new Array(cm.listSelections().length+1).join('world ').split(' '); + replacement.pop(); + cm.replaceSelections(replacement); + eq('1hworld\n5hworld\nahworld', cm.getValue()); +}, {value: '1234\n5678\nabcdefg'}); +testVim('c_visual_block_replay', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('', '2', 'j', 'l', 'c'); + var replacement = new Array(cm.listSelections().length+1).join('fo ').split(' '); + replacement.pop(); + cm.replaceSelections(replacement); + eq('1fo4\n5fo8\nafodefg', cm.getValue()); + helpers.doKeys(''); + cm.setCursor(0, 0); + helpers.doKeys('.'); + eq('foo4\nfoo8\nfoodefg', cm.getValue()); +}, {value: '1234\n5678\nabcdefg'}); + +// Swapcase commands edit in place and do not modify registers. +testVim('g~w_repeat', function(cm, vim, helpers) { + // Assert that dw does delete newline if it should go to the next line, and + // that repeat works properly. + var curStart = makeCursor(0, 1); + cm.setCursor(curStart); + helpers.doKeys('g', '~', '2', 'w'); + eq(' WORD1\nWORD2', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1\nword2' }); +testVim('g~g~', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + var expectedLineCount = cm.lineCount(); + var expectedValue = cm.getValue().toUpperCase(); + helpers.doKeys('2', 'g', '~', '3', 'g', '~'); + eq(expectedValue, cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + eqPos({line: curStart.line, ch:0}, cm.getCursor()); +}, { value: ' word1\nword2\nword3\nword4\nword5\nword6' }); +testVim('gu_and_gU', function(cm, vim, helpers) { + var curStart = makeCursor(0, 7); + var value = cm.getValue(); + cm.setCursor(curStart); + helpers.doKeys('2', 'g', 'U', 'w'); + eq(cm.getValue(), 'wa wb xX WC wd'); + eqPos(curStart, cm.getCursor()); + helpers.doKeys('2', 'g', 'u', 'w'); + eq(cm.getValue(), value); + + helpers.doKeys('2', 'g', 'U', 'B'); + eq(cm.getValue(), 'wa WB Xx wc wd'); + eqPos(makeCursor(0, 3), cm.getCursor()); + + cm.setCursor(makeCursor(0, 4)); + helpers.doKeys('g', 'u', 'i', 'w'); + eq(cm.getValue(), 'wa wb Xx wc wd'); + eqPos(makeCursor(0, 3), cm.getCursor()); + + // TODO: support gUgU guu + // eqPos(makeCursor(0, 0), cm.getCursor()); + + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); +}, { value: 'wa wb xx wc wd' }); +testVim('visual_block_~', function(cm, vim, helpers) { + cm.setCursor(1, 1); + helpers.doKeys('', 'l', 'l', 'j', '~'); + helpers.assertCursorAt(1, 1); + eq('hello\nwoRLd\naBCDe', cm.getValue()); + cm.setCursor(2, 0); + helpers.doKeys('v', 'l', 'l', '~'); + helpers.assertCursorAt(2, 0); + eq('hello\nwoRLd\nAbcDe', cm.getValue()); +},{value: 'hello\nwOrld\nabcde' }); +testVim('._swapCase_visualBlock', function(cm, vim, helpers) { + helpers.doKeys('', 'j', 'j', 'l', '~'); + cm.setCursor(0, 3); + helpers.doKeys('.'); + eq('HelLO\nWorLd\nAbcdE', cm.getValue()); +},{value: 'hEllo\nwOrlD\naBcDe' }); +testVim('._delete_visualBlock', function(cm, vim, helpers) { + helpers.doKeys('', 'j', 'x'); + eq('ive\ne\nsome\nsugar', cm.getValue()); + helpers.doKeys('.'); + eq('ve\n\nsome\nsugar', cm.getValue()); + helpers.doKeys('j', 'j', '.'); + eq('ve\n\nome\nugar', cm.getValue()); + helpers.doKeys('u', '', '.'); + eq('ve\n\nme\ngar', cm.getValue()); +},{value: 'give\nme\nsome\nsugar' }); +testVim('>{motion}', function(cm, vim, helpers) { + cm.setCursor(1, 3); + var expectedLineCount = cm.lineCount(); + var expectedValue = ' word1\n word2\nword3 '; + helpers.doKeys('>', 'k'); + eq(expectedValue, cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 3); +}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); +testVim('>>', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedLineCount = cm.lineCount(); + var expectedValue = ' word1\n word2\nword3 '; + helpers.doKeys('2', '>', '>'); + eq(expectedValue, cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 3); +}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); +testVim('<{motion}', function(cm, vim, helpers) { + cm.setCursor(1, 3); + var expectedLineCount = cm.lineCount(); + var expectedValue = ' word1\nword2\nword3 '; + helpers.doKeys('<', 'k'); + eq(expectedValue, cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); +testVim('<<', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedLineCount = cm.lineCount(); + var expectedValue = ' word1\nword2\nword3 '; + helpers.doKeys('2', '<', '<'); + eq(expectedValue, cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); + +// Edit tests +function testEdit(name, before, pos, edit, after) { + return testVim(name, function(cm, vim, helpers) { + var ch = before.search(pos) + var line = before.substring(0, ch).split('\n').length - 1; + if (line) { + ch = before.substring(0, ch).split('\n').pop().length; + } + cm.setCursor(line, ch); + helpers.doKeys.apply(this, edit.split('')); + eq(after, cm.getValue()); + }, {value: before}); +} + +// These Delete tests effectively cover word-wise Change, Visual & Yank. +// Tabs are used as differentiated whitespace to catch edge cases. +// Normal word: +testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz'); +testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz'); +testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz'); +testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz'); +testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz'); +testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz'); +testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz'); +testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz'); +testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz'); +testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz'); +testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t'); +testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo'); +testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.'); +testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.'); +// Big word: +testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz'); +testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz'); +testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz'); +testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz'); +testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz'); +testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz'); +testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz'); +testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz'); +testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz'); +testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz'); +testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t'); +testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo'); +testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t'); +testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo'); +// Deleting text objects +// Open and close on same line +testEdit('di(_open_spc', 'foo (bAr) baz', /\(/, 'di(', 'foo () baz'); +testEdit('di)_open_spc', 'foo (bAr) baz', /\(/, 'di)', 'foo () baz'); +testEdit('dib_open_spc', 'foo (bAr) baz', /\(/, 'dib', 'foo () baz'); +testEdit('da(_open_spc', 'foo (bAr) baz', /\(/, 'da(', 'foo baz'); +testEdit('da)_open_spc', 'foo (bAr) baz', /\(/, 'da)', 'foo baz'); + +testEdit('di(_middle_spc', 'foo (bAr) baz', /A/, 'di(', 'foo () baz'); +testEdit('di)_middle_spc', 'foo (bAr) baz', /A/, 'di)', 'foo () baz'); +testEdit('da(_middle_spc', 'foo (bAr) baz', /A/, 'da(', 'foo baz'); +testEdit('da)_middle_spc', 'foo (bAr) baz', /A/, 'da)', 'foo baz'); + +testEdit('di(_close_spc', 'foo (bAr) baz', /\)/, 'di(', 'foo () baz'); +testEdit('di)_close_spc', 'foo (bAr) baz', /\)/, 'di)', 'foo () baz'); +testEdit('da(_close_spc', 'foo (bAr) baz', /\)/, 'da(', 'foo baz'); +testEdit('da)_close_spc', 'foo (bAr) baz', /\)/, 'da)', 'foo baz'); + +// delete around and inner b. +testEdit('dab_on_(_should_delete_around_()block', 'o( in(abc) )', /\(a/, 'dab', 'o( in )'); + +// delete around and inner B. +testEdit('daB_on_{_should_delete_around_{}block', 'o{ in{abc} }', /{a/, 'daB', 'o{ in }'); +testEdit('diB_on_{_should_delete_inner_{}block', 'o{ in{abc} }', /{a/, 'diB', 'o{ in{} }'); + +testEdit('da{_on_{_should_delete_inner_block', 'o{ in{abc} }', /{a/, 'da{', 'o{ in }'); +testEdit('di[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'di[', 'foo (bAr) baz'); +testEdit('di[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'di[', 'foo (bAr) baz'); +testEdit('da[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'da[', 'foo (bAr) baz'); +testEdit('da[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'da[', 'foo (bAr) baz'); +testMotion('di(_outside_should_stay', ['d', 'i', '('], { line: 0, ch: 0}, { line: 0, ch: 0}); + +// Open and close on different lines, equally indented +testEdit('di{_middle_spc', 'a{\n\tbar\n}b', /r/, 'di{', 'a{}b'); +testEdit('di}_middle_spc', 'a{\n\tbar\n}b', /r/, 'di}', 'a{}b'); +testEdit('da{_middle_spc', 'a{\n\tbar\n}b', /r/, 'da{', 'ab'); +testEdit('da}_middle_spc', 'a{\n\tbar\n}b', /r/, 'da}', 'ab'); +testEdit('daB_middle_spc', 'a{\n\tbar\n}b', /r/, 'daB', 'ab'); + +// open and close on diff lines, open indented less than close +testEdit('di{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di{', 'a{}b'); +testEdit('di}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di}', 'a{}b'); +testEdit('da{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da{', 'ab'); +testEdit('da}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da}', 'ab'); + +// open and close on diff lines, open indented more than close +testEdit('di[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di[', 'a\t[]b'); +testEdit('di]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di]', 'a\t[]b'); +testEdit('da[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da[', 'a\tb'); +testEdit('da]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da]', 'a\tb'); + +function testSelection(name, before, pos, keys, sel) { + return testVim(name, function(cm, vim, helpers) { + var ch = before.search(pos) + var line = before.substring(0, ch).split('\n').length - 1; + if (line) { + ch = before.substring(0, ch).split('\n').pop().length; + } + cm.setCursor(line, ch); + helpers.doKeys.apply(this, keys.split('')); + eq(sel, cm.getSelection()); + }, {value: before}); +} +testSelection('viw_middle_spc', 'foo \tbAr\t baz', /A/, 'viw', 'bAr'); +testSelection('vaw_middle_spc', 'foo \tbAr\t baz', /A/, 'vaw', 'bAr\t '); +testSelection('viw_middle_punct', 'foo \tbAr,\t baz', /A/, 'viw', 'bAr'); +testSelection('vaW_middle_punct', 'foo \tbAr,\t baz', /A/, 'vaW', 'bAr,\t '); +testSelection('viw_start_spc', 'foo \tbAr\t baz', /b/, 'viw', 'bAr'); +testSelection('viw_end_spc', 'foo \tbAr\t baz', /r/, 'viw', 'bAr'); +testSelection('viw_eol', 'foo \tbAr', /r/, 'viw', 'bAr'); +testSelection('vi{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'vi{', '\n\tbar\n\t'); +testSelection('va{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'va{', '{\n\tbar\n\t}'); + +testVim('mouse_select', function(cm, vim, helpers) { + cm.setSelection(Pos(0, 2), Pos(0, 4), {origin: '*mouse'}); + is(cm.state.vim.visualMode); + is(!cm.state.vim.visualLine); + is(!cm.state.vim.visualBlock); + helpers.doKeys(''); + is(!cm.somethingSelected()); + helpers.doKeys('g', 'v'); + eq('cd', cm.getSelection()); +}, {value: 'abcdef'}); + +// Operator-motion tests +testVim('D', function(cm, vim, helpers) { + cm.setCursor(0, 3); + helpers.doKeys('D'); + eq(' wo\nword2\n word3', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('rd1', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 3); +}, { value: ' word1\nword2\n word3' }); +testVim('C', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + helpers.doKeys('C'); + eq(' wo\nword2\n word3', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('rd1', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); + eq('vim-insert', cm.getOption('keyMap')); +}, { value: ' word1\nword2\n word3' }); +testVim('Y', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + helpers.doKeys('Y'); + eq(' word1\nword2\n word3', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('rd1', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 3); +}, { value: ' word1\nword2\n word3' }); +testVim('~', function(cm, vim, helpers) { + helpers.doKeys('3', '~'); + eq('ABCdefg', cm.getValue()); + helpers.assertCursorAt(0, 3); +}, { value: 'abcdefg' }); + +// Action tests +testVim('ctrl-a', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys(''); + eq('-9', cm.getValue()); + helpers.assertCursorAt(0, 1); + helpers.doKeys('2',''); + eq('-7', cm.getValue()); +}, {value: '-10'}); +testVim('ctrl-x', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys(''); + eq('-1', cm.getValue()); + helpers.assertCursorAt(0, 1); + helpers.doKeys('2',''); + eq('-3', cm.getValue()); +}, {value: '0'}); +testVim('/ search forward', function(cm, vim, helpers) { + forEach(['', ''], function(key) { + cm.setCursor(0, 0); + helpers.doKeys(key); + helpers.assertCursorAt(0, 5); + helpers.doKeys('l'); + helpers.doKeys(key); + helpers.assertCursorAt(0, 10); + cm.setCursor(0, 11); + helpers.doKeys(key); + helpers.assertCursorAt(0, 11); + }); +}, {value: '__jmp1 jmp2 jmp'}); +testVim('a', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('a'); + helpers.assertCursorAt(0, 2); + eq('vim-insert', cm.getOption('keyMap')); +}); +testVim('a_eol', function(cm, vim, helpers) { + cm.setCursor(0, lines[0].length - 1); + helpers.doKeys('a'); + helpers.assertCursorAt(0, lines[0].length); + eq('vim-insert', cm.getOption('keyMap')); +}); +testVim('a_endOfSelectedArea', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('v', 'j', 'l'); + helpers.doKeys('A'); + helpers.assertCursorAt(1, 2); + eq('vim-insert', cm.getOption('keyMap')); +}, {value: 'foo\nbar'}); +testVim('i', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('i'); + helpers.assertCursorAt(0, 1); + eq('vim-insert', cm.getOption('keyMap')); +}); +testVim('i_repeat', function(cm, vim, helpers) { + helpers.doKeys('3', 'i'); + cm.replaceRange('test', cm.getCursor()); + helpers.doKeys(''); + eq('testtesttest', cm.getValue()); + helpers.assertCursorAt(0, 11); +}, { value: '' }); +testVim('i_repeat_delete', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('2', 'i'); + cm.replaceRange('z', cm.getCursor()); + helpers.doInsertModeKeys('Backspace', 'Backspace'); + helpers.doKeys(''); + eq('abe', cm.getValue()); + helpers.assertCursorAt(0, 1); +}, { value: 'abcde' }); +testVim('A', function(cm, vim, helpers) { + helpers.doKeys('A'); + helpers.assertCursorAt(0, lines[0].length); + eq('vim-insert', cm.getOption('keyMap')); +}); +testVim('A_visual_block', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('', '2', 'j', 'l', 'l', 'A'); + var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); + replacement.pop(); + cm.replaceSelections(replacement); + eq('testhello\nmehello\npleahellose', cm.getValue()); + helpers.doKeys(''); + cm.setCursor(0, 0); + helpers.doKeys('.'); + // TODO this doesn't work yet + // eq('teshellothello\nme hello hello\nplehelloahellose', cm.getValue()); +}, {value: 'test\nme\nplease'}); +testVim('I', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('I'); + helpers.assertCursorAt(0, lines[0].textStart); + eq('vim-insert', cm.getOption('keyMap')); +}); +testVim('I_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('3', 'I'); + cm.replaceRange('test', cm.getCursor()); + helpers.doKeys(''); + eq('testtesttestblah', cm.getValue()); + helpers.assertCursorAt(0, 11); +}, { value: 'blah' }); +testVim('I_visual_block', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', '2', 'j', 'l', 'l', 'I'); + var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); + replacement.pop(); + cm.replaceSelections(replacement); + eq('hellotest\nhellome\nhelloplease', cm.getValue()); +}, {value: 'test\nme\nplease'}); +testVim('o', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('o'); + eq('word1\n\nword2', cm.getValue()); + helpers.assertCursorAt(1, 0); + eq('vim-insert', cm.getOption('keyMap')); +}, { value: 'word1\nword2' }); +testVim('o_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('3', 'o'); + cm.replaceRange('test', cm.getCursor()); + helpers.doKeys(''); + eq('\ntest\ntest\ntest', cm.getValue()); + helpers.assertCursorAt(3, 3); +}, { value: '' }); +testVim('O', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('O'); + eq('\nword1\nword2', cm.getValue()); + helpers.assertCursorAt(0, 0); + eq('vim-insert', cm.getOption('keyMap')); +}, { value: 'word1\nword2' }); +testVim('J', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('J'); + var expectedValue = 'word1 word2\nword3\n word4'; + eq(expectedValue, cm.getValue()); + helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1); +}, { value: 'word1 \n word2\nword3\n word4' }); +testVim('J_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('3', 'J'); + var expectedValue = 'word1 word2 word3\n word4'; + eq(expectedValue, cm.getValue()); + helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1); +}, { value: 'word1 \n word2\nword3\n word4' }); +testVim('p', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); + helpers.doKeys('p'); + eq('__abc\ndef_', cm.getValue()); + helpers.assertCursorAt(1, 2); +}, { value: '___' }); +testVim('p_register', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); + helpers.doKeys('"', 'a', 'p'); + eq('__abc\ndef_', cm.getValue()); + helpers.assertCursorAt(1, 2); +}, { value: '___' }); +testVim('p_wrong_register', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); + helpers.doKeys('p'); + eq('___', cm.getValue()); + helpers.assertCursorAt(0, 1); +}, { value: '___' }); +testVim('p_line', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); + helpers.doKeys('2', 'p'); + eq('___\n a\nd\n a\nd', cm.getValue()); + helpers.assertCursorAt(1, 2); +}, { value: '___' }); +testVim('p_lastline', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().pushText('"', 'yank', ' a\nd', true); + helpers.doKeys('2', 'p'); + eq('___\n a\nd\n a\nd', cm.getValue()); + helpers.assertCursorAt(1, 2); +}, { value: '___' }); +testVim(']p_first_indent_is_smaller', function(cm, vim, helpers) { + helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); + helpers.doKeys(']', 'p'); + eq(' ___\n abc\n def', cm.getValue()); +}, { value: ' ___' }); +testVim(']p_first_indent_is_larger', function(cm, vim, helpers) { + helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); + helpers.doKeys(']', 'p'); + eq(' ___\n abc\ndef', cm.getValue()); +}, { value: ' ___' }); +testVim(']p_with_tab_indents', function(cm, vim, helpers) { + helpers.getRegisterController().pushText('"', 'yank', '\t\tabc\n\t\t\tdef\n', true); + helpers.doKeys(']', 'p'); + eq('\t___\n\tabc\n\t\tdef', cm.getValue()); +}, { value: '\t___', indentWithTabs: true}); +testVim(']p_with_spaces_translated_to_tabs', function(cm, vim, helpers) { + helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); + helpers.doKeys(']', 'p'); + eq('\t___\n\tabc\n\t\tdef', cm.getValue()); +}, { value: '\t___', indentWithTabs: true, tabSize: 2 }); +testVim('[p', function(cm, vim, helpers) { + helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); + helpers.doKeys('[', 'p'); + eq(' abc\n def\n ___', cm.getValue()); +}, { value: ' ___' }); +testVim('P', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); + helpers.doKeys('P'); + eq('_abc\ndef__', cm.getValue()); + helpers.assertCursorAt(1, 3); +}, { value: '___' }); +testVim('P_line', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); + helpers.doKeys('2', 'P'); + eq(' a\nd\n a\nd\n___', cm.getValue()); + helpers.assertCursorAt(0, 2); +}, { value: '___' }); +testVim('r', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('3', 'r', 'u'); + eq('wuuuet\nanother', cm.getValue(),'3r failed'); + helpers.assertCursorAt(0, 3); + cm.setCursor(0, 4); + helpers.doKeys('v', 'j', 'h', 'r', ''); + eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed'); +}, { value: 'wordet\nanother' }); +testVim('r_visual_block', function(cm, vim, helpers) { + cm.setCursor(2, 3); + helpers.doKeys('', 'k', 'k', 'h', 'h', 'r', 'l'); + eq('1lll\n5lll\nalllefg', cm.getValue()); + helpers.doKeys('', 'l', 'j', 'r', ''); + eq('1 l\n5 l\nalllefg', cm.getValue()); + cm.setCursor(2, 0); + helpers.doKeys('o'); + helpers.doKeys(''); + cm.replaceRange('\t\t', cm.getCursor()); + helpers.doKeys('', 'h', 'h', 'r', 'r'); + eq('1 l\n5 l\nalllefg\nrrrrrrrr', cm.getValue()); +}, {value: '1234\n5678\nabcdefg'}); +testVim('R', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('R'); + helpers.assertCursorAt(0, 1); + eq('vim-replace', cm.getOption('keyMap')); + is(cm.state.overwrite, 'Setting overwrite state failed'); +}); +testVim('mark', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 't'); + cm.setCursor(0, 0); + helpers.doKeys('`', 't'); + helpers.assertCursorAt(2, 2); + cm.setCursor(2, 0); + cm.replaceRange(' h', cm.getCursor()); + cm.setCursor(0, 0); + helpers.doKeys('\'', 't'); + helpers.assertCursorAt(2, 3); +}); +testVim('jumpToMark_next', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 't'); + cm.setCursor(0, 0); + helpers.doKeys(']', '`'); + helpers.assertCursorAt(2, 2); + cm.setCursor(0, 0); + helpers.doKeys(']', '\''); + helpers.assertCursorAt(2, 0); +}); +testVim('jumpToMark_next_repeat', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(3, 2); + helpers.doKeys('m', 'b'); + cm.setCursor(4, 2); + helpers.doKeys('m', 'c'); + cm.setCursor(0, 0); + helpers.doKeys('2', ']', '`'); + helpers.assertCursorAt(3, 2); + cm.setCursor(0, 0); + helpers.doKeys('2', ']', '\''); + helpers.assertCursorAt(3, 1); +}); +testVim('jumpToMark_next_sameline', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 4); + helpers.doKeys('m', 'b'); + cm.setCursor(2, 2); + helpers.doKeys(']', '`'); + helpers.assertCursorAt(2, 4); +}); +testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('m', 'a'); + cm.setCursor(4, 0); + helpers.doKeys(']', '`'); + helpers.assertCursorAt(4, 0); +}); +testVim('jumpToMark_next_nomark', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys(']', '`'); + helpers.assertCursorAt(2, 2); + helpers.doKeys(']', '\''); + helpers.assertCursorAt(2, 0); +}); +testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(3, 4); + helpers.doKeys('m', 'b'); + cm.setCursor(2, 1); + helpers.doKeys(']', '\''); + helpers.assertCursorAt(3, 1); +}); +testVim('jumpToMark_next_action', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 't'); + cm.setCursor(0, 0); + helpers.doKeys('d', ']', '`'); + helpers.assertCursorAt(0, 0); + var actual = cm.getLine(0); + var expected = 'pop pop 0 1 2 3 4'; + eq(actual, expected, "Deleting while jumping to the next mark failed."); +}); +testVim('jumpToMark_next_line_action', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 't'); + cm.setCursor(0, 0); + helpers.doKeys('d', ']', '\''); + helpers.assertCursorAt(0, 1); + var actual = cm.getLine(0); + var expected = ' (a) [b] {c} ' + eq(actual, expected, "Deleting while jumping to the next mark line failed."); +}); +testVim('jumpToMark_prev', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 't'); + cm.setCursor(4, 0); + helpers.doKeys('[', '`'); + helpers.assertCursorAt(2, 2); + cm.setCursor(4, 0); + helpers.doKeys('[', '\''); + helpers.assertCursorAt(2, 0); +}); +testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(3, 2); + helpers.doKeys('m', 'b'); + cm.setCursor(4, 2); + helpers.doKeys('m', 'c'); + cm.setCursor(5, 0); + helpers.doKeys('2', '[', '`'); + helpers.assertCursorAt(3, 2); + cm.setCursor(5, 0); + helpers.doKeys('2', '[', '\''); + helpers.assertCursorAt(3, 1); +}); +testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 4); + helpers.doKeys('m', 'b'); + cm.setCursor(2, 2); + helpers.doKeys('[', '`'); + helpers.assertCursorAt(2, 0); +}); +testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) { + cm.setCursor(4, 4); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 0); + helpers.doKeys('[', '`'); + helpers.assertCursorAt(2, 0); +}); +testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('[', '`'); + helpers.assertCursorAt(2, 2); + helpers.doKeys('[', '\''); + helpers.assertCursorAt(2, 0); +}); +testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(3, 4); + helpers.doKeys('m', 'b'); + cm.setCursor(3, 6); + helpers.doKeys('[', '\''); + helpers.assertCursorAt(2, 0); +}); +testVim('delmark_single', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('m', 't'); + helpers.doEx('delmarks t'); + cm.setCursor(0, 0); + helpers.doKeys('`', 't'); + helpers.assertCursorAt(0, 0); +}); +testVim('delmark_range', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 2); + helpers.doKeys('m', 'b'); + cm.setCursor(3, 2); + helpers.doKeys('m', 'c'); + cm.setCursor(4, 2); + helpers.doKeys('m', 'd'); + cm.setCursor(5, 2); + helpers.doKeys('m', 'e'); + helpers.doEx('delmarks b-d'); + cm.setCursor(0, 0); + helpers.doKeys('`', 'a'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'b'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'c'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'd'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'e'); + helpers.assertCursorAt(5, 2); +}); +testVim('delmark_multi', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 2); + helpers.doKeys('m', 'b'); + cm.setCursor(3, 2); + helpers.doKeys('m', 'c'); + cm.setCursor(4, 2); + helpers.doKeys('m', 'd'); + cm.setCursor(5, 2); + helpers.doKeys('m', 'e'); + helpers.doEx('delmarks bcd'); + cm.setCursor(0, 0); + helpers.doKeys('`', 'a'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'b'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'c'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'd'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'e'); + helpers.assertCursorAt(5, 2); +}); +testVim('delmark_multi_space', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 2); + helpers.doKeys('m', 'b'); + cm.setCursor(3, 2); + helpers.doKeys('m', 'c'); + cm.setCursor(4, 2); + helpers.doKeys('m', 'd'); + cm.setCursor(5, 2); + helpers.doKeys('m', 'e'); + helpers.doEx('delmarks b c d'); + cm.setCursor(0, 0); + helpers.doKeys('`', 'a'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'b'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'c'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'd'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'e'); + helpers.assertCursorAt(5, 2); +}); +testVim('delmark_all', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 2); + helpers.doKeys('m', 'b'); + cm.setCursor(3, 2); + helpers.doKeys('m', 'c'); + cm.setCursor(4, 2); + helpers.doKeys('m', 'd'); + cm.setCursor(5, 2); + helpers.doKeys('m', 'e'); + helpers.doEx('delmarks a b-de'); + cm.setCursor(0, 0); + helpers.doKeys('`', 'a'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('`', 'b'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('`', 'c'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('`', 'd'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('`', 'e'); + helpers.assertCursorAt(0, 0); +}); +testVim('visual', function(cm, vim, helpers) { + helpers.doKeys('l', 'v', 'l', 'l'); + helpers.assertCursorAt(0, 4); + eqPos(makeCursor(0, 1), cm.getCursor('anchor')); + helpers.doKeys('d'); + eq('15', cm.getValue()); +}, { value: '12345' }); +testVim('visual_exit', function(cm, vim, helpers) { + helpers.doKeys('', 'l', 'j', 'j', ''); + eqPos(cm.getCursor('anchor'), cm.getCursor('head')); + eq(vim.visualMode, false); +}, { value: 'hello\nworld\nfoo' }); +testVim('visual_line', function(cm, vim, helpers) { + helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd'); + eq(' 4\n 5', cm.getValue()); +}, { value: ' 1\n 2\n 3\n 4\n 5' }); +testVim('visual_block', function(cm, vim, helpers) { + // test the block selection with lines of different length + // i.e. extending the selection + // till the end of the longest line. + helpers.doKeys('', 'l', 'j', 'j', '6', 'l', 'd'); + helpers.doKeys('d', 'd', 'd', 'd'); + eq('', cm.getValue()); + // check for left side selection in case + // of moving up to a shorter line. + cm.replaceRange('hello world\n{\nthis is\nsparta!', cm.getCursor()); + cm.setCursor(3, 4); + helpers.doKeys('', 'l', 'k', 'k', 'd'); + eq('hello world\n{\ntis\nsa!', cm.getValue()); + cm.replaceRange('12345\n67891\nabcde', {line: 0, ch: 0}, {line: cm.lastLine(), ch: 6}); + cm.setCursor(1, 2); + helpers.doKeys('', '2', 'l', 'k'); + // circle around the anchor + // and check the selections + var selections = cm.getSelections(); + eq('345891', selections.join('')); + helpers.doKeys('4', 'h'); + selections = cm.getSelections(); + eq('123678', selections.join('')); + helpers.doKeys('j', 'j'); + selections = cm.getSelections(); + eq('678abc', selections.join('')); + helpers.doKeys('4', 'l'); + selections = cm.getSelections(); + eq('891cde', selections.join('')); + // switch between visual modes + cm.setCursor(1, 1); + // blockwise to characterwise visual + helpers.doKeys('', 'j', 'l', 'v'); + selections = cm.getSelections(); + eq('7891\nabc', selections.join('')); + // characterwise to blockwise + helpers.doKeys(''); + selections = cm.getSelections(); + eq('78bc', selections.join('')); + // blockwise to linewise visual + helpers.doKeys('V'); + selections = cm.getSelections(); + eq('67891\nabcde', selections.join('')); +}, {value: '1234\n5678\nabcdefg'}); +testVim('visual_block_crossing_short_line', function(cm, vim, helpers) { + // visual block with long and short lines + cm.setCursor(0, 3); + helpers.doKeys('', 'j', 'j', 'j'); + var selections = cm.getSelections().join(); + eq('4,,d,b', selections); + helpers.doKeys('3', 'k'); + selections = cm.getSelections().join(); + eq('4', selections); + helpers.doKeys('5', 'j', 'k'); + selections = cm.getSelections().join(""); + eq(10, selections.length); +}, {value: '123456\n78\nabcdefg\nfoobar\n}\n'}); +testVim('visual_block_curPos_on_exit', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', '3' , 'l', ''); + eqPos(makeCursor(0, 3), cm.getCursor()); + helpers.doKeys('h', '', '2' , 'j' ,'3' , 'l'); + eq(cm.getSelections().join(), "3456,,cdef"); + helpers.doKeys('4' , 'h'); + eq(cm.getSelections().join(), "23,8,bc"); + helpers.doKeys('2' , 'l'); + eq(cm.getSelections().join(), "34,,cd"); +}, {value: '123456\n78\nabcdefg\nfoobar'}); + +testVim('visual_marks', function(cm, vim, helpers) { + helpers.doKeys('l', 'v', 'l', 'l', 'j', 'j', 'v'); + // Test visual mode marks + cm.setCursor(2, 1); + helpers.doKeys('\'', '<'); + helpers.assertCursorAt(0, 1); + helpers.doKeys('\'', '>'); + helpers.assertCursorAt(2, 0); +}); +testVim('visual_join', function(cm, vim, helpers) { + helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J'); + eq(' 1 2 3\n 4\n 5', cm.getValue()); + is(!vim.visualMode); +}, { value: ' 1\n 2\n 3\n 4\n 5' }); +testVim('visual_blank', function(cm, vim, helpers) { + helpers.doKeys('v', 'k'); + eq(vim.visualMode, true); +}, { value: '\n' }); +testVim('reselect_visual', function(cm, vim, helpers) { + helpers.doKeys('l', 'v', 'l', 'l', 'l', 'y', 'g', 'v'); + helpers.assertCursorAt(0, 5); + eqPos(makeCursor(0, 1), cm.getCursor('anchor')); + helpers.doKeys('v'); + cm.setCursor(1, 0); + helpers.doKeys('v', 'l', 'l', 'p'); + eq('123456\n2345\nbar', cm.getValue()); + cm.setCursor(0, 0); + helpers.doKeys('g', 'v'); + // here the fake cursor is at (1, 3) + helpers.assertCursorAt(1, 4); + eqPos(makeCursor(1, 0), cm.getCursor('anchor')); + helpers.doKeys('v'); + cm.setCursor(2, 0); + helpers.doKeys('v', 'l', 'l', 'g', 'v'); + helpers.assertCursorAt(1, 4); + eqPos(makeCursor(1, 0), cm.getCursor('anchor')); + helpers.doKeys('g', 'v'); + helpers.assertCursorAt(2, 3); + eqPos(makeCursor(2, 0), cm.getCursor('anchor')); + eq('123456\n2345\nbar', cm.getValue()); +}, { value: '123456\nfoo\nbar' }); +testVim('reselect_visual_line', function(cm, vim, helpers) { + helpers.doKeys('l', 'V', 'j', 'j', 'V', 'g', 'v', 'd'); + eq('foo\nand\nbar', cm.getValue()); + cm.setCursor(1, 0); + helpers.doKeys('V', 'y', 'j'); + helpers.doKeys('V', 'p' , 'g', 'v', 'd'); + eq('foo\nand', cm.getValue()); +}, { value: 'hello\nthis\nis\nfoo\nand\nbar' }); +testVim('reselect_visual_block', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('', 'k', 'h', ''); + cm.setCursor(2, 1); + helpers.doKeys('v', 'l', 'g', 'v'); + helpers.assertCursorAt(0, 1); + // Ensure selection is done with visual block mode rather than one + // continuous range. + eq(cm.getSelections().join(''), '23oo') + helpers.doKeys('g', 'v'); + helpers.assertCursorAt(2, 3); + // Ensure selection of deleted range + cm.setCursor(1, 1); + helpers.doKeys('v', '', 'j', 'd', 'g', 'v'); + eq(cm.getSelections().join(''), 'or'); +}, { value: '123456\nfoo\nbar' }); +testVim('s_normal', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('s'); + helpers.doKeys(''); + eq('ac', cm.getValue()); +}, { value: 'abc'}); +testVim('s_visual', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('v', 's'); + helpers.doKeys(''); + helpers.assertCursorAt(0, 0); + eq('ac', cm.getValue()); +}, { value: 'abc'}); +testVim('o_visual', function(cm, vim, helpers) { + cm.setCursor(0,0); + helpers.doKeys('v','l','l','l','o'); + helpers.assertCursorAt(0,0); + helpers.doKeys('v','v','j','j','j','o'); + helpers.assertCursorAt(0,0); + helpers.doKeys('O'); + helpers.doKeys('l','l') + helpers.assertCursorAt(3, 3); + helpers.doKeys('d'); + eq('p',cm.getValue()); +}, { value: 'abcd\nefgh\nijkl\nmnop'}); +testVim('o_visual_block', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('','3','j','l','l', 'o'); + helpers.assertCursorAt(0, 1); + helpers.doKeys('O'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('o'); + helpers.assertCursorAt(3, 1); +}, { value: 'abcd\nefgh\nijkl\nmnop'}); +testVim('changeCase_visual', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('v', 'l', 'l'); + helpers.doKeys('U'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('v', 'l', 'l'); + helpers.doKeys('u'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('l', 'l', 'l', '.'); + helpers.assertCursorAt(0, 3); + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', 'v', 'j', 'U', 'q'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('j', '@', 'a'); + helpers.assertCursorAt(1, 0); + cm.setCursor(3, 0); + helpers.doKeys('V', 'U', 'j', '.'); + eq('ABCDEF\nGHIJKL\nMnopq\nSHORT LINE\nLONG LINE OF TEXT', cm.getValue()); +}, { value: 'abcdef\nghijkl\nmnopq\nshort line\nlong line of text'}); +testVim('changeCase_visual_block', function(cm, vim, helpers) { + cm.setCursor(2, 1); + helpers.doKeys('', 'k', 'k', 'h', 'U'); + eq('ABcdef\nGHijkl\nMNopq\nfoo', cm.getValue()); + cm.setCursor(0, 2); + helpers.doKeys('.'); + eq('ABCDef\nGHIJkl\nMNOPq\nfoo', cm.getValue()); + // check when last line is shorter. + cm.setCursor(2, 2); + helpers.doKeys('.'); + eq('ABCDef\nGHIJkl\nMNOPq\nfoO', cm.getValue()); +}, { value: 'abcdef\nghijkl\nmnopq\nfoo'}); +testVim('visual_paste', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('v', 'l', 'l', 'y', 'j', 'v', 'l', 'p'); + helpers.assertCursorAt(1, 5); + eq('this is a\nunithitest for visual paste', cm.getValue()); + cm.setCursor(0, 0); + // in case of pasting whole line + helpers.doKeys('y', 'y'); + cm.setCursor(1, 6); + helpers.doKeys('v', 'l', 'l', 'l', 'p'); + helpers.assertCursorAt(2, 0); + eq('this is a\nunithi\nthis is a\n for visual paste', cm.getValue()); +}, { value: 'this is a\nunit test for visual paste'}); + +// This checks the contents of the register used to paste the text +testVim('v_paste_from_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('"', 'a', 'y', 'w'); + cm.setCursor(1, 0); + helpers.doKeys('v', 'p'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+register/.test(text)); + }); +}, { value: 'register contents\nare not erased'}); +testVim('S_normal', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('j', 'S'); + helpers.doKeys(''); + helpers.assertCursorAt(1, 0); + eq('aa\n\ncc', cm.getValue()); +}, { value: 'aa\nbb\ncc'}); +testVim('blockwise_paste', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', '3', 'j', 'l', 'y'); + cm.setCursor(0, 2); + // paste one char after the current cursor position + helpers.doKeys('p'); + eq('helhelo\nworwold\nfoofo\nbarba', cm.getValue()); + cm.setCursor(0, 0); + helpers.doKeys('v', '4', 'l', 'y'); + cm.setCursor(0, 0); + helpers.doKeys('', '3', 'j', 'p'); + eq('helheelhelo\norwold\noofo\narba', cm.getValue()); +}, { value: 'hello\nworld\nfoo\nbar'}); +testVim('blockwise_paste_long/short_line', function(cm, vim, helpers) { + // extend short lines in case of different line lengths. + cm.setCursor(0, 0); + helpers.doKeys('', 'j', 'j', 'y'); + cm.setCursor(0, 3); + helpers.doKeys('p'); + eq('hellho\nfoo f\nbar b', cm.getValue()); +}, { value: 'hello\nfoo\nbar'}); +testVim('blockwise_paste_cut_paste', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', '2', 'j', 'x'); + cm.setCursor(0, 0); + helpers.doKeys('P'); + eq('cut\nand\npaste\nme', cm.getValue()); +}, { value: 'cut\nand\npaste\nme'}); +testVim('blockwise_paste_from_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', '2', 'j', '"', 'a', 'y'); + cm.setCursor(0, 3); + helpers.doKeys('"', 'a', 'p'); + eq('foobfar\nhellho\nworlwd', cm.getValue()); +}, { value: 'foobar\nhello\nworld'}); +testVim('blockwise_paste_last_line', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', '2', 'j', 'l', 'y'); + cm.setCursor(3, 0); + helpers.doKeys('p'); + eq('cut\nand\npaste\nmcue\n an\n pa', cm.getValue()); +}, { value: 'cut\nand\npaste\nme'}); + +testVim('S_visual', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('v', 'j', 'S'); + helpers.doKeys(''); + helpers.assertCursorAt(0, 0); + eq('\ncc', cm.getValue()); +}, { value: 'aa\nbb\ncc'}); + +testVim('/ and n/N', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('match'); + helpers.doKeys('/'); + helpers.assertCursorAt(0, 11); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 6); + helpers.doKeys('N'); + helpers.assertCursorAt(0, 11); + + cm.setCursor(0, 0); + helpers.doKeys('2', '/'); + helpers.assertCursorAt(1, 6); +}, { value: 'match nope match \n nope Match' }); +testVim('/_case', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('Match'); + helpers.doKeys('/'); + helpers.assertCursorAt(1, 6); +}, { value: 'match nope match \n nope Match' }); +testVim('/_2_pcre', function(cm, vim, helpers) { + CodeMirror.Vim.setOption('pcre', true); + cm.openDialog = helpers.fakeOpenDialog('(word){2}'); + helpers.doKeys('/'); + helpers.assertCursorAt(1, 9); + helpers.doKeys('n'); + helpers.assertCursorAt(2, 1); +}, { value: 'word\n another wordword\n wordwordword\n' }); +testVim('/_2_nopcre', function(cm, vim, helpers) { + CodeMirror.Vim.setOption('pcre', false); + cm.openDialog = helpers.fakeOpenDialog('\\(word\\)\\{2}'); + helpers.doKeys('/'); + helpers.assertCursorAt(1, 9); + helpers.doKeys('n'); + helpers.assertCursorAt(2, 1); +}, { value: 'word\n another wordword\n wordwordword\n' }); +testVim('/_nongreedy', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('aa'); + helpers.doKeys('/'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 3); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 0); +}, { value: 'aaa aa \n a aa'}); +testVim('?_nongreedy', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('aa'); + helpers.doKeys('?'); + helpers.assertCursorAt(1, 3); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 0); +}, { value: 'aaa aa \n a aa'}); +testVim('/_greedy', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('a+'); + helpers.doKeys('/'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 1); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 3); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 0); +}, { value: 'aaa aa \n a aa'}); +testVim('?_greedy', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('a+'); + helpers.doKeys('?'); + helpers.assertCursorAt(1, 3); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 1); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 0); +}, { value: 'aaa aa \n a aa'}); +testVim('/_greedy_0_or_more', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('a*'); + helpers.doKeys('/'); + helpers.assertCursorAt(0, 3); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 5); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 0); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 1); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 0); +}, { value: 'aaa aa\n aa'}); +testVim('?_greedy_0_or_more', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('a*'); + helpers.doKeys('?'); + helpers.assertCursorAt(1, 1); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 0); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 5); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 3); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 0); +}, { value: 'aaa aa\n aa'}); +testVim('? and n/N', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('match'); + helpers.doKeys('?'); + helpers.assertCursorAt(1, 6); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 11); + helpers.doKeys('N'); + helpers.assertCursorAt(1, 6); + + cm.setCursor(0, 0); + helpers.doKeys('2', '?'); + helpers.assertCursorAt(0, 11); +}, { value: 'match nope match \n nope Match' }); +testVim('*', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('*'); + helpers.assertCursorAt(0, 22); + + cm.setCursor(0, 9); + helpers.doKeys('2', '*'); + helpers.assertCursorAt(1, 8); +}, { value: 'nomatch match nomatch match \nnomatch Match' }); +testVim('*_no_word', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('*'); + helpers.assertCursorAt(0, 0); +}, { value: ' \n match \n' }); +testVim('*_symbol', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('*'); + helpers.assertCursorAt(1, 0); +}, { value: ' /}\n/} match \n' }); +testVim('#', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('#'); + helpers.assertCursorAt(1, 8); + + cm.setCursor(0, 9); + helpers.doKeys('2', '#'); + helpers.assertCursorAt(0, 22); +}, { value: 'nomatch match nomatch match \nnomatch Match' }); +testVim('*_seek', function(cm, vim, helpers) { + // Should skip over space and symbols. + cm.setCursor(0, 3); + helpers.doKeys('*'); + helpers.assertCursorAt(0, 22); +}, { value: ' := match nomatch match \nnomatch Match' }); +testVim('#', function(cm, vim, helpers) { + // Should skip over space and symbols. + cm.setCursor(0, 3); + helpers.doKeys('#'); + helpers.assertCursorAt(1, 8); +}, { value: ' := match nomatch match \nnomatch Match' }); +testVim('g*', function(cm, vim, helpers) { + cm.setCursor(0, 8); + helpers.doKeys('g', '*'); + helpers.assertCursorAt(0, 18); + cm.setCursor(0, 8); + helpers.doKeys('3', 'g', '*'); + helpers.assertCursorAt(1, 8); +}, { value: 'matches match alsoMatch\nmatchme matching' }); +testVim('g#', function(cm, vim, helpers) { + cm.setCursor(0, 8); + helpers.doKeys('g', '#'); + helpers.assertCursorAt(0, 0); + cm.setCursor(0, 8); + helpers.doKeys('3', 'g', '#'); + helpers.assertCursorAt(1, 0); +}, { value: 'matches match alsoMatch\nmatchme matching' }); +testVim('macro_insert', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', '0', 'i'); + cm.replaceRange('foo', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q', '@', 'a'); + eq('foofoo', cm.getValue()); +}, { value: ''}); +testVim('macro_insert_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', '$', 'a'); + cm.replaceRange('larry.', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('a'); + cm.replaceRange('curly.', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q'); + helpers.doKeys('a'); + cm.replaceRange('moe.', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('@', 'a'); + // At this point, the most recent edit should be the 2nd insert change + // inside the macro, i.e. "curly.". + helpers.doKeys('.'); + eq('larry.curly.moe.larry.curly.curly.', cm.getValue()); +}, { value: ''}); +testVim('macro_space', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', ''); + helpers.assertCursorAt(0, 2); + helpers.doKeys('q', 'a', '', '', 'q'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('@', 'a'); + helpers.assertCursorAt(0, 6); + helpers.doKeys('@', 'a'); + helpers.assertCursorAt(0, 8); +}, { value: 'one line of text.'}); +testVim('macro_t_search', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', 't', 'e', 'q'); + helpers.assertCursorAt(0, 1); + helpers.doKeys('l', '@', 'a'); + helpers.assertCursorAt(0, 6); + helpers.doKeys('l', ';'); + helpers.assertCursorAt(0, 12); +}, { value: 'one line of text.'}); +testVim('macro_f_search', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'b', 'f', 'e', 'q'); + helpers.assertCursorAt(0, 2); + helpers.doKeys('@', 'b'); + helpers.assertCursorAt(0, 7); + helpers.doKeys(';'); + helpers.assertCursorAt(0, 13); +}, { value: 'one line of text.'}); +testVim('macro_slash_search', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'c'); + cm.openDialog = helpers.fakeOpenDialog('e'); + helpers.doKeys('/', 'q'); + helpers.assertCursorAt(0, 2); + helpers.doKeys('@', 'c'); + helpers.assertCursorAt(0, 7); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 13); +}, { value: 'one line of text.'}); +testVim('macro_multislash_search', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'd'); + cm.openDialog = helpers.fakeOpenDialog('e'); + helpers.doKeys('/'); + cm.openDialog = helpers.fakeOpenDialog('t'); + helpers.doKeys('/', 'q'); + helpers.assertCursorAt(0, 12); + helpers.doKeys('@', 'd'); + helpers.assertCursorAt(0, 15); +}, { value: 'one line of text to rule them all.'}); +testVim('macro_parens', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'z', 'i'); + cm.replaceRange('(', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('e', 'a'); + cm.replaceRange(')', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q'); + helpers.doKeys('w', '@', 'z'); + helpers.doKeys('w', '@', 'z'); + eq('(see) (spot) (run)', cm.getValue()); +}, { value: 'see spot run'}); +testVim('macro_overwrite', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'z', '0', 'i'); + cm.replaceRange('I ', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q'); + helpers.doKeys('e'); + // Now replace the macro with something else. + helpers.doKeys('q', 'z', 'a'); + cm.replaceRange('.', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q'); + helpers.doKeys('e', '@', 'z'); + helpers.doKeys('e', '@', 'z'); + eq('I see. spot. run.', cm.getValue()); +}, { value: 'see spot run'}); +testVim('macro_search_f', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', 'f', ' '); + helpers.assertCursorAt(0,3); + helpers.doKeys('q', '0'); + helpers.assertCursorAt(0,0); + helpers.doKeys('@', 'a'); + helpers.assertCursorAt(0,3); +}, { value: 'The quick brown fox jumped over the lazy dog.'}); +testVim('macro_search_2f', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', '2', 'f', ' '); + helpers.assertCursorAt(0,9); + helpers.doKeys('q', '0'); + helpers.assertCursorAt(0,0); + helpers.doKeys('@', 'a'); + helpers.assertCursorAt(0,9); +}, { value: 'The quick brown fox jumped over the lazy dog.'}); +testVim('yank_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('"', 'a', 'y', 'y'); + helpers.doKeys('j', '"', 'b', 'y', 'y'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+foo/.test(text)); + is(/b\s+bar/.test(text)); + }); + helpers.doKeys(':'); +}, { value: 'foo\nbar'}); +testVim('yank_visual_block', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('', 'l', 'j', '"', 'a', 'y'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+oo\nar/.test(text)); + }); + helpers.doKeys(':'); +}, { value: 'foo\nbar'}); +testVim('yank_append_line_to_line_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('"', 'a', 'y', 'y'); + helpers.doKeys('j', '"', 'A', 'y', 'y'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+foo\nbar/.test(text)); + is(/"\s+foo\nbar/.test(text)); + }); + helpers.doKeys(':'); +}, { value: 'foo\nbar'}); +testVim('yank_append_word_to_word_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('"', 'a', 'y', 'w'); + helpers.doKeys('j', '"', 'A', 'y', 'w'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+foobar/.test(text)); + is(/"\s+foobar/.test(text)); + }); + helpers.doKeys(':'); +}, { value: 'foo\nbar'}); +testVim('yank_append_line_to_word_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('"', 'a', 'y', 'w'); + helpers.doKeys('j', '"', 'A', 'y', 'y'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+foo\nbar/.test(text)); + is(/"\s+foo\nbar/.test(text)); + }); + helpers.doKeys(':'); +}, { value: 'foo\nbar'}); +testVim('yank_append_word_to_line_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('"', 'a', 'y', 'y'); + helpers.doKeys('j', '"', 'A', 'y', 'w'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+foo\nbar/.test(text)); + is(/"\s+foo\nbar/.test(text)); + }); + helpers.doKeys(':'); +}, { value: 'foo\nbar'}); +testVim('macro_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', 'i'); + cm.replaceRange('gangnam', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q'); + helpers.doKeys('q', 'b', 'o'); + cm.replaceRange('style', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+i/.test(text)); + is(/b\s+o/.test(text)); + }); + helpers.doKeys(':'); +}, { value: ''}); +testVim('._register', function(cm,vim,helpers) { + cm.setCursor(0,0); + helpers.doKeys('i'); + cm.replaceRange('foo',cm.getCursor()); + helpers.doKeys(''); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/\.\s+foo/.test(text)); + }); + helpers.doKeys(':'); +}, {value: ''}); +testVim(':_register', function(cm,vim,helpers) { + helpers.doEx('bar'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/:\s+bar/.test(text)); + }); + helpers.doKeys(':'); +}, {value: ''}); +testVim('search_register_escape', function(cm, vim, helpers) { + // Check that the register is restored if the user escapes rather than confirms. + cm.openDialog = helpers.fakeOpenDialog('waldo'); + helpers.doKeys('/'); + var onKeyDown; + var onKeyUp; + var KEYCODES = { + f: 70, + o: 79, + Esc: 27 + }; + cm.openDialog = function(template, callback, options) { + onKeyDown = options.onKeyDown; + onKeyUp = options.onKeyUp; + }; + var close = function() {}; + helpers.doKeys('/'); + // Fake some keyboard events coming in. + onKeyDown({keyCode: KEYCODES.f}, '', close); + onKeyUp({keyCode: KEYCODES.f}, '', close); + onKeyDown({keyCode: KEYCODES.o}, 'f', close); + onKeyUp({keyCode: KEYCODES.o}, 'f', close); + onKeyDown({keyCode: KEYCODES.o}, 'fo', close); + onKeyUp({keyCode: KEYCODES.o}, 'fo', close); + onKeyDown({keyCode: KEYCODES.Esc}, 'foo', close); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/waldo/.test(text)); + is(!/foo/.test(text)); + }); + helpers.doKeys(':'); +}, {value: ''}); +testVim('search_register', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('foo'); + helpers.doKeys('/'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/\/\s+foo/.test(text)); + }); + helpers.doKeys(':'); +}, {value: ''}); +testVim('search_history', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('this'); + helpers.doKeys('/'); + cm.openDialog = helpers.fakeOpenDialog('checks'); + helpers.doKeys('/'); + cm.openDialog = helpers.fakeOpenDialog('search'); + helpers.doKeys('/'); + cm.openDialog = helpers.fakeOpenDialog('history'); + helpers.doKeys('/'); + cm.openDialog = helpers.fakeOpenDialog('checks'); + helpers.doKeys('/'); + var onKeyDown; + var onKeyUp; + var query = ''; + var keyCodes = { + Up: 38, + Down: 40 + }; + cm.openDialog = function(template, callback, options) { + onKeyUp = options.onKeyUp; + onKeyDown = options.onKeyDown; + }; + var close = function(newVal) { + if (typeof newVal == 'string') query = newVal; + } + helpers.doKeys('/'); + onKeyDown({keyCode: keyCodes.Up}, query, close); + onKeyUp({keyCode: keyCodes.Up}, query, close); + eq(query, 'checks'); + onKeyDown({keyCode: keyCodes.Up}, query, close); + onKeyUp({keyCode: keyCodes.Up}, query, close); + eq(query, 'history'); + onKeyDown({keyCode: keyCodes.Up}, query, close); + onKeyUp({keyCode: keyCodes.Up}, query, close); + eq(query, 'search'); + onKeyDown({keyCode: keyCodes.Up}, query, close); + onKeyUp({keyCode: keyCodes.Up}, query, close); + eq(query, 'this'); + onKeyDown({keyCode: keyCodes.Down}, query, close); + onKeyUp({keyCode: keyCodes.Down}, query, close); + eq(query, 'search'); +}, {value: ''}); +testVim('exCommand_history', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('registers'); + helpers.doKeys(':'); + cm.openDialog = helpers.fakeOpenDialog('sort'); + helpers.doKeys(':'); + cm.openDialog = helpers.fakeOpenDialog('map'); + helpers.doKeys(':'); + cm.openDialog = helpers.fakeOpenDialog('invalid'); + helpers.doKeys(':'); + var onKeyDown; + var onKeyUp; + var input = ''; + var keyCodes = { + Up: 38, + Down: 40, + s: 115 + }; + cm.openDialog = function(template, callback, options) { + onKeyUp = options.onKeyUp; + onKeyDown = options.onKeyDown; + }; + var close = function(newVal) { + if (typeof newVal == 'string') input = newVal; + } + helpers.doKeys(':'); + onKeyDown({keyCode: keyCodes.Up}, input, close); + eq(input, 'invalid'); + onKeyDown({keyCode: keyCodes.Up}, input, close); + eq(input, 'map'); + onKeyDown({keyCode: keyCodes.Up}, input, close); + eq(input, 'sort'); + onKeyDown({keyCode: keyCodes.Up}, input, close); + eq(input, 'registers'); + onKeyDown({keyCode: keyCodes.s}, '', close); + input = 's'; + onKeyDown({keyCode: keyCodes.Up}, input, close); + eq(input, 'sort'); +}, {value: ''}); +testVim('.', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('2', 'd', 'w'); + helpers.doKeys('.'); + eq('5 6', cm.getValue()); +}, { value: '1 2 3 4 5 6'}); +testVim('._repeat', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('2', 'd', 'w'); + helpers.doKeys('3', '.'); + eq('6', cm.getValue()); +}, { value: '1 2 3 4 5 6'}); +testVim('._insert', function(cm, vim, helpers) { + helpers.doKeys('i'); + cm.replaceRange('test', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('.'); + eq('testestt', cm.getValue()); + helpers.assertCursorAt(0, 6); +}, { value: ''}); +testVim('._insert_repeat', function(cm, vim, helpers) { + helpers.doKeys('i'); + cm.replaceRange('test', cm.getCursor()); + cm.setCursor(0, 4); + helpers.doKeys(''); + helpers.doKeys('2', '.'); + eq('testesttestt', cm.getValue()); + helpers.assertCursorAt(0, 10); +}, { value: ''}); +testVim('._repeat_insert', function(cm, vim, helpers) { + helpers.doKeys('3', 'i'); + cm.replaceRange('te', cm.getCursor()); + cm.setCursor(0, 2); + helpers.doKeys(''); + helpers.doKeys('.'); + eq('tetettetetee', cm.getValue()); + helpers.assertCursorAt(0, 10); +}, { value: ''}); +testVim('._insert_o', function(cm, vim, helpers) { + helpers.doKeys('o'); + cm.replaceRange('z', cm.getCursor()); + cm.setCursor(1, 1); + helpers.doKeys(''); + helpers.doKeys('.'); + eq('\nz\nz', cm.getValue()); + helpers.assertCursorAt(2, 0); +}, { value: ''}); +testVim('._insert_o_repeat', function(cm, vim, helpers) { + helpers.doKeys('o'); + cm.replaceRange('z', cm.getCursor()); + helpers.doKeys(''); + cm.setCursor(1, 0); + helpers.doKeys('2', '.'); + eq('\nz\nz\nz', cm.getValue()); + helpers.assertCursorAt(3, 0); +}, { value: ''}); +testVim('._insert_o_indent', function(cm, vim, helpers) { + helpers.doKeys('o'); + cm.replaceRange('z', cm.getCursor()); + helpers.doKeys(''); + cm.setCursor(1, 2); + helpers.doKeys('.'); + eq('{\n z\n z', cm.getValue()); + helpers.assertCursorAt(2, 2); +}, { value: '{'}); +testVim('._insert_cw', function(cm, vim, helpers) { + helpers.doKeys('c', 'w'); + cm.replaceRange('test', cm.getCursor()); + helpers.doKeys(''); + cm.setCursor(0, 3); + helpers.doKeys('2', 'l'); + helpers.doKeys('.'); + eq('test test word3', cm.getValue()); + helpers.assertCursorAt(0, 8); +}, { value: 'word1 word2 word3' }); +testVim('._insert_cw_repeat', function(cm, vim, helpers) { + // For some reason, repeat cw in desktop VIM will does not repeat insert mode + // changes. Will conform to that behavior. + helpers.doKeys('c', 'w'); + cm.replaceRange('test', cm.getCursor()); + helpers.doKeys(''); + cm.setCursor(0, 4); + helpers.doKeys('l'); + helpers.doKeys('2', '.'); + eq('test test', cm.getValue()); + helpers.assertCursorAt(0, 8); +}, { value: 'word1 word2 word3' }); +testVim('._delete', function(cm, vim, helpers) { + cm.setCursor(0, 5); + helpers.doKeys('i'); + helpers.doInsertModeKeys('Backspace'); + helpers.doKeys(''); + helpers.doKeys('.'); + eq('zace', cm.getValue()); + helpers.assertCursorAt(0, 1); +}, { value: 'zabcde'}); +testVim('._delete_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 6); + helpers.doKeys('i'); + helpers.doInsertModeKeys('Backspace'); + helpers.doKeys(''); + helpers.doKeys('2', '.'); + eq('zzce', cm.getValue()); + helpers.assertCursorAt(0, 1); +}, { value: 'zzabcde'}); +testVim('._visual_>', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('V', 'j', '>'); + cm.setCursor(2, 0) + helpers.doKeys('.'); + eq(' 1\n 2\n 3\n 4', cm.getValue()); + helpers.assertCursorAt(2, 2); +}, { value: '1\n2\n3\n4'}); +testVim('f;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('f', 'x'); + helpers.doKeys(';'); + helpers.doKeys('2', ';'); + eq(9, cm.getCursor().ch); +}, { value: '01x3xx678x'}); +testVim('F;', function(cm, vim, helpers) { + cm.setCursor(0, 8); + helpers.doKeys('F', 'x'); + helpers.doKeys(';'); + helpers.doKeys('2', ';'); + eq(2, cm.getCursor().ch); +}, { value: '01x3xx6x8x'}); +testVim('t;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('t', 'x'); + helpers.doKeys(';'); + helpers.doKeys('2', ';'); + eq(8, cm.getCursor().ch); +}, { value: '01x3xx678x'}); +testVim('T;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('T', 'x'); + helpers.doKeys(';'); + helpers.doKeys('2', ';'); + eq(2, cm.getCursor().ch); +}, { value: '0xx3xx678x'}); +testVim('f,', function(cm, vim, helpers) { + cm.setCursor(0, 6); + helpers.doKeys('f', 'x'); + helpers.doKeys(','); + helpers.doKeys('2', ','); + eq(2, cm.getCursor().ch); +}, { value: '01x3xx678x'}); +testVim('F,', function(cm, vim, helpers) { + cm.setCursor(0, 3); + helpers.doKeys('F', 'x'); + helpers.doKeys(','); + helpers.doKeys('2', ','); + eq(9, cm.getCursor().ch); +}, { value: '01x3xx678x'}); +testVim('t,', function(cm, vim, helpers) { + cm.setCursor(0, 6); + helpers.doKeys('t', 'x'); + helpers.doKeys(','); + helpers.doKeys('2', ','); + eq(3, cm.getCursor().ch); +}, { value: '01x3xx678x'}); +testVim('T,', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('T', 'x'); + helpers.doKeys(','); + helpers.doKeys('2', ','); + eq(8, cm.getCursor().ch); +}, { value: '01x3xx67xx'}); +testVim('fd,;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('f', '4'); + cm.setCursor(0, 0); + helpers.doKeys('d', ';'); + eq('56789', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 9); + helpers.doKeys('d', ','); + eq('01239', cm.getValue()); +}, { value: '0123456789'}); +testVim('Fd,;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('F', '4'); + cm.setCursor(0, 9); + helpers.doKeys('d', ';'); + eq('01239', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 0); + helpers.doKeys('d', ','); + eq('56789', cm.getValue()); +}, { value: '0123456789'}); +testVim('td,;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('t', '4'); + cm.setCursor(0, 0); + helpers.doKeys('d', ';'); + eq('456789', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 9); + helpers.doKeys('d', ','); + eq('012349', cm.getValue()); +}, { value: '0123456789'}); +testVim('Td,;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('T', '4'); + cm.setCursor(0, 9); + helpers.doKeys('d', ';'); + eq('012349', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 0); + helpers.doKeys('d', ','); + eq('456789', cm.getValue()); +}, { value: '0123456789'}); +testVim('fc,;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('f', '4'); + cm.setCursor(0, 0); + helpers.doKeys('c', ';', ''); + eq('56789', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 9); + helpers.doKeys('c', ','); + eq('01239', cm.getValue()); +}, { value: '0123456789'}); +testVim('Fc,;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('F', '4'); + cm.setCursor(0, 9); + helpers.doKeys('c', ';', ''); + eq('01239', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 0); + helpers.doKeys('c', ','); + eq('56789', cm.getValue()); +}, { value: '0123456789'}); +testVim('tc,;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('t', '4'); + cm.setCursor(0, 0); + helpers.doKeys('c', ';', ''); + eq('456789', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 9); + helpers.doKeys('c', ','); + eq('012349', cm.getValue()); +}, { value: '0123456789'}); +testVim('Tc,;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('T', '4'); + cm.setCursor(0, 9); + helpers.doKeys('c', ';', ''); + eq('012349', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 0); + helpers.doKeys('c', ','); + eq('456789', cm.getValue()); +}, { value: '0123456789'}); +testVim('fy,;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('f', '4'); + cm.setCursor(0, 0); + helpers.doKeys('y', ';', 'P'); + eq('012340123456789', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 9); + helpers.doKeys('y', ',', 'P'); + eq('012345678456789', cm.getValue()); +}, { value: '0123456789'}); +testVim('Fy,;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('F', '4'); + cm.setCursor(0, 9); + helpers.doKeys('y', ';', 'p'); + eq('012345678945678', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 0); + helpers.doKeys('y', ',', 'P'); + eq('012340123456789', cm.getValue()); +}, { value: '0123456789'}); +testVim('ty,;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('t', '4'); + cm.setCursor(0, 0); + helpers.doKeys('y', ';', 'P'); + eq('01230123456789', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 9); + helpers.doKeys('y', ',', 'p'); + eq('01234567895678', cm.getValue()); +}, { value: '0123456789'}); +testVim('Ty,;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('T', '4'); + cm.setCursor(0, 9); + helpers.doKeys('y', ';', 'p'); + eq('01234567895678', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 0); + helpers.doKeys('y', ',', 'P'); + eq('01230123456789', cm.getValue()); +}, { value: '0123456789'}); +testVim('HML', function(cm, vim, helpers) { + var lines = 35; + var textHeight = cm.defaultTextHeight(); + cm.setSize(600, lines*textHeight); + cm.setCursor(120, 0); + helpers.doKeys('H'); + helpers.assertCursorAt(86, 2); + helpers.doKeys('L'); + helpers.assertCursorAt(120, 4); + helpers.doKeys('M'); + helpers.assertCursorAt(103,4); +}, { value: (function(){ + var lines = new Array(100); + var upper = ' xx\n'; + var lower = ' xx\n'; + upper = lines.join(upper); + lower = lines.join(lower); + return upper + lower; +})()}); + +var zVals = []; +forEach(['zb','zz','zt','z-','z.','z'], function(e, idx){ + var lineNum = 250; + var lines = 35; + testVim(e, function(cm, vim, helpers) { + var k1 = e[0]; + var k2 = e.substring(1); + var textHeight = cm.defaultTextHeight(); + cm.setSize(600, lines*textHeight); + cm.setCursor(lineNum, 0); + helpers.doKeys(k1, k2); + zVals[idx] = cm.getScrollInfo().top; + }, { value: (function(){ + return new Array(500).join('\n'); + })()}); +}); +testVim('zb', function(cm, vim, helpers){ + eq(zVals[2], zVals[5]); +}); + +var moveTillCharacterSandbox = + 'The quick brown fox \n' + 'jumped over the lazy dog.' +testVim('moveTillCharacter', function(cm, vim, helpers){ + cm.setCursor(0, 0); + // Search for the 'q'. + cm.openDialog = helpers.fakeOpenDialog('q'); + helpers.doKeys('/'); + eq(4, cm.getCursor().ch); + // Jump to just before the first o in the list. + helpers.doKeys('t'); + helpers.doKeys('o'); + eq('The quick brown fox \n', cm.getValue()); + // Delete that one character. + helpers.doKeys('d'); + helpers.doKeys('t'); + helpers.doKeys('o'); + eq('The quick bown fox \n', cm.getValue()); + // Delete everything until the next 'o'. + helpers.doKeys('.'); + eq('The quick box \n', cm.getValue()); + // An unmatched character should have no effect. + helpers.doKeys('d'); + helpers.doKeys('t'); + helpers.doKeys('q'); + eq('The quick box \n', cm.getValue()); + // Matches should only be possible on single lines. + helpers.doKeys('d'); + helpers.doKeys('t'); + helpers.doKeys('z'); + eq('The quick box \n', cm.getValue()); + // After all that, the search for 'q' should still be active, so the 'N' command + // can run it again in reverse. Use that to delete everything back to the 'q'. + helpers.doKeys('d'); + helpers.doKeys('N'); + eq('The ox \n', cm.getValue()); + eq(4, cm.getCursor().ch); +}, { value: moveTillCharacterSandbox}); +testVim('searchForPipe', function(cm, vim, helpers){ + CodeMirror.Vim.setOption('pcre', false); + cm.setCursor(0, 0); + // Search for the '|'. + cm.openDialog = helpers.fakeOpenDialog('|'); + helpers.doKeys('/'); + eq(4, cm.getCursor().ch); +}, { value: 'this|that'}); + + +var scrollMotionSandbox = + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'; +testVim('scrollMotion', function(cm, vim, helpers){ + var prevCursor, prevScrollInfo; + cm.setCursor(0, 0); + // ctrl-y at the top of the file should have no effect. + helpers.doKeys(''); + eq(0, cm.getCursor().line); + prevScrollInfo = cm.getScrollInfo(); + helpers.doKeys(''); + eq(1, cm.getCursor().line); + is(prevScrollInfo.top < cm.getScrollInfo().top); + // Jump to the end of the sandbox. + cm.setCursor(1000, 0); + prevCursor = cm.getCursor(); + // ctrl-e at the bottom of the file should have no effect. + helpers.doKeys(''); + eq(prevCursor.line, cm.getCursor().line); + prevScrollInfo = cm.getScrollInfo(); + helpers.doKeys(''); + eq(prevCursor.line - 1, cm.getCursor().line); + is(prevScrollInfo.top > cm.getScrollInfo().top); +}, { value: scrollMotionSandbox}); + +var squareBracketMotionSandbox = ''+ + '({\n'+//0 + ' ({\n'+//11 + ' /*comment {\n'+//2 + ' */(\n'+//3 + '#else \n'+//4 + ' /* )\n'+//5 + '#if }\n'+//6 + ' )}*/\n'+//7 + ')}\n'+//8 + '{}\n'+//9 + '#else {{\n'+//10 + '{}\n'+//11 + '}\n'+//12 + '{\n'+//13 + '#endif\n'+//14 + '}\n'+//15 + '}\n'+//16 + '#else';//17 +testVim('[[, ]]', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys(']', ']'); + helpers.assertCursorAt(9,0); + helpers.doKeys('2', ']', ']'); + helpers.assertCursorAt(13,0); + helpers.doKeys(']', ']'); + helpers.assertCursorAt(17,0); + helpers.doKeys('[', '['); + helpers.assertCursorAt(13,0); + helpers.doKeys('2', '[', '['); + helpers.assertCursorAt(9,0); + helpers.doKeys('[', '['); + helpers.assertCursorAt(0,0); +}, { value: squareBracketMotionSandbox}); +testVim('[], ][', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys(']', '['); + helpers.assertCursorAt(12,0); + helpers.doKeys('2', ']', '['); + helpers.assertCursorAt(16,0); + helpers.doKeys(']', '['); + helpers.assertCursorAt(17,0); + helpers.doKeys('[', ']'); + helpers.assertCursorAt(16,0); + helpers.doKeys('2', '[', ']'); + helpers.assertCursorAt(12,0); + helpers.doKeys('[', ']'); + helpers.assertCursorAt(0,0); +}, { value: squareBracketMotionSandbox}); +testVim('[{, ]}', function(cm, vim, helpers) { + cm.setCursor(4, 10); + helpers.doKeys('[', '{'); + helpers.assertCursorAt(2,12); + helpers.doKeys('2', '[', '{'); + helpers.assertCursorAt(0,1); + cm.setCursor(4, 10); + helpers.doKeys(']', '}'); + helpers.assertCursorAt(6,11); + helpers.doKeys('2', ']', '}'); + helpers.assertCursorAt(8,1); + cm.setCursor(0,1); + helpers.doKeys(']', '}'); + helpers.assertCursorAt(8,1); + helpers.doKeys('[', '{'); + helpers.assertCursorAt(0,1); +}, { value: squareBracketMotionSandbox}); +testVim('[(, ])', function(cm, vim, helpers) { + cm.setCursor(4, 10); + helpers.doKeys('[', '('); + helpers.assertCursorAt(3,14); + helpers.doKeys('2', '[', '('); + helpers.assertCursorAt(0,0); + cm.setCursor(4, 10); + helpers.doKeys(']', ')'); + helpers.assertCursorAt(5,11); + helpers.doKeys('2', ']', ')'); + helpers.assertCursorAt(8,0); + helpers.doKeys('[', '('); + helpers.assertCursorAt(0,0); + helpers.doKeys(']', ')'); + helpers.assertCursorAt(8,0); +}, { value: squareBracketMotionSandbox}); +testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) { + forEach(['*', '/'], function(key){ + cm.setCursor(7, 0); + helpers.doKeys('2', '[', key); + helpers.assertCursorAt(2,2); + helpers.doKeys('2', ']', key); + helpers.assertCursorAt(7,5); + }); +}, { value: squareBracketMotionSandbox}); +testVim('[#, ]#', function(cm, vim, helpers) { + cm.setCursor(10, 3); + helpers.doKeys('2', '[', '#'); + helpers.assertCursorAt(4,0); + helpers.doKeys('5', ']', '#'); + helpers.assertCursorAt(17,0); + cm.setCursor(10, 3); + helpers.doKeys(']', '#'); + helpers.assertCursorAt(14,0); +}, { value: squareBracketMotionSandbox}); +testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) { + cm.setCursor(11, 0); + helpers.doKeys('[', 'm'); + helpers.assertCursorAt(10,7); + helpers.doKeys('4', '[', 'm'); + helpers.assertCursorAt(1,3); + helpers.doKeys('5', ']', 'm'); + helpers.assertCursorAt(11,0); + helpers.doKeys('[', 'M'); + helpers.assertCursorAt(9,1); + helpers.doKeys('3', ']', 'M'); + helpers.assertCursorAt(15,0); + helpers.doKeys('5', '[', 'M'); + helpers.assertCursorAt(7,3); +}, { value: squareBracketMotionSandbox}); + +// Ex mode tests +testVim('ex_go_to_line', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doEx('4'); + helpers.assertCursorAt(3, 0); +}, { value: 'a\nb\nc\nd\ne\n'}); +testVim('ex_write', function(cm, vim, helpers) { + var tmp = CodeMirror.commands.save; + var written; + var actualCm; + CodeMirror.commands.save = function(cm) { + written = true; + actualCm = cm; + }; + // Test that w, wr, wri ... write all trigger :write. + var command = 'write'; + for (var i = 1; i < command.length; i++) { + written = false; + actualCm = null; + helpers.doEx(command.substring(0, i)); + eq(written, true); + eq(actualCm, cm); + } + CodeMirror.commands.save = tmp; +}); +testVim('ex_sort', function(cm, vim, helpers) { + helpers.doEx('sort'); + eq('Z\na\nb\nc\nd', cm.getValue()); +}, { value: 'b\nZ\nd\nc\na'}); +testVim('ex_sort_reverse', function(cm, vim, helpers) { + helpers.doEx('sort!'); + eq('d\nc\nb\na', cm.getValue()); +}, { value: 'b\nd\nc\na'}); +testVim('ex_sort_range', function(cm, vim, helpers) { + helpers.doEx('2,3sort'); + eq('b\nc\nd\na', cm.getValue()); +}, { value: 'b\nd\nc\na'}); +testVim('ex_sort_oneline', function(cm, vim, helpers) { + helpers.doEx('2sort'); + // Expect no change. + eq('b\nd\nc\na', cm.getValue()); +}, { value: 'b\nd\nc\na'}); +testVim('ex_sort_ignoreCase', function(cm, vim, helpers) { + helpers.doEx('sort i'); + eq('a\nb\nc\nd\nZ', cm.getValue()); +}, { value: 'b\nZ\nd\nc\na'}); +testVim('ex_sort_unique', function(cm, vim, helpers) { + helpers.doEx('sort u'); + eq('Z\na\nb\nc\nd', cm.getValue()); +}, { value: 'b\nZ\na\na\nd\na\nc\na'}); +testVim('ex_sort_decimal', function(cm, vim, helpers) { + helpers.doEx('sort d'); + eq('d3\n s5\n6\n.9', cm.getValue()); +}, { value: '6\nd3\n s5\n.9'}); +testVim('ex_sort_decimal_negative', function(cm, vim, helpers) { + helpers.doEx('sort d'); + eq('z-9\nd3\n s5\n6\n.9', cm.getValue()); +}, { value: '6\nd3\n s5\n.9\nz-9'}); +testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) { + helpers.doEx('sort! d'); + eq('.9\n6\n s5\nd3', cm.getValue()); +}, { value: '6\nd3\n s5\n.9'}); +testVim('ex_sort_hex', function(cm, vim, helpers) { + helpers.doEx('sort x'); + eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue()); +}, { value: '6\nd3\n s5\n&0xB\n.9'}); +testVim('ex_sort_octal', function(cm, vim, helpers) { + helpers.doEx('sort o'); + eq('.8\n.9\nd3\n s5\n6', cm.getValue()); +}, { value: '6\nd3\n s5\n.9\n.8'}); +testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) { + helpers.doEx('sort d'); + eq('y\nz\nc1\nb2\na3', cm.getValue()); +}, { value: 'a3\nz\nc1\ny\nb2'}); +testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) { + helpers.doEx('sort! d'); + eq('a3\nb2\nc1\nz\ny', cm.getValue()); +}, { value: 'a3\nz\nc1\ny\nb2'}); +// test for :global command +testVim('ex_global', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doEx('g/one/s//two'); + eq('two two\n two two\n two two', cm.getValue()); + helpers.doEx('1,2g/two/s//one'); + eq('one one\n one one\n two two', cm.getValue()); +}, {value: 'one one\n one one\n one one'}); +testVim('ex_global_confirm', function(cm, vim, helpers) { + cm.setCursor(0, 0); + var onKeyDown; + var openDialogSave = cm.openDialog; + var KEYCODES = { + a: 65, + n: 78, + q: 81, + y: 89 + }; + // Intercept the ex command, 'global' + cm.openDialog = function(template, callback, options) { + // Intercept the prompt for the embedded ex command, 'substitute' + cm.openDialog = function(template, callback, options) { + onKeyDown = options.onKeyDown; + }; + callback('g/one/s//two/gc'); + }; + helpers.doKeys(':'); + var close = function() {}; + onKeyDown({keyCode: KEYCODES.n}, '', close); + onKeyDown({keyCode: KEYCODES.y}, '', close); + onKeyDown({keyCode: KEYCODES.a}, '', close); + onKeyDown({keyCode: KEYCODES.q}, '', close); + onKeyDown({keyCode: KEYCODES.y}, '', close); + eq('one two\n two two\n one one\n two one\n one one', cm.getValue()); +}, {value: 'one one\n one one\n one one\n one one\n one one'}); +// Basic substitute tests. +testVim('ex_substitute_same_line', function(cm, vim, helpers) { + cm.setCursor(1, 0); + helpers.doEx('s/one/two/g'); + eq('one one\n two two', cm.getValue()); +}, { value: 'one one\n one one'}); +testVim('ex_substitute_full_file', function(cm, vim, helpers) { + cm.setCursor(1, 0); + helpers.doEx('%s/one/two/g'); + eq('two two\n two two', cm.getValue()); +}, { value: 'one one\n one one'}); +testVim('ex_substitute_input_range', function(cm, vim, helpers) { + cm.setCursor(1, 0); + helpers.doEx('1,3s/\\d/0/g'); + eq('0\n0\n0\n4', cm.getValue()); +}, { value: '1\n2\n3\n4' }); +testVim('ex_substitute_visual_range', function(cm, vim, helpers) { + cm.setCursor(1, 0); + // Set last visual mode selection marks '< and '> at lines 2 and 4 + helpers.doKeys('V', '2', 'j', 'v'); + helpers.doEx('\'<,\'>s/\\d/0/g'); + eq('1\n0\n0\n0\n5', cm.getValue()); +}, { value: '1\n2\n3\n4\n5' }); +testVim('ex_substitute_empty_query', function(cm, vim, helpers) { + // If the query is empty, use last query. + cm.setCursor(1, 0); + cm.openDialog = helpers.fakeOpenDialog('1'); + helpers.doKeys('/'); + helpers.doEx('s//b/g'); + eq('abb ab2 ab3', cm.getValue()); +}, { value: 'a11 a12 a13' }); +testVim('ex_substitute_javascript', function(cm, vim, helpers) { + CodeMirror.Vim.setOption('pcre', false); + cm.setCursor(1, 0); + // Throw all the things that javascript likes to treat as special values + // into the replace part. All should be literal (this is VIM). + helpers.doEx('s/\\(\\d+\\)/$$ $\' $` $& \\1/g') + eq('a $$ $\' $` $& 0 b', cm.getValue()); +}, { value: 'a 0 b' }); +testVim('ex_substitute_empty_arguments', function(cm,vim,helpers) { + cm.setCursor(0, 0); + helpers.doEx('s/a/b/g'); + cm.setCursor(1, 0); + helpers.doEx('s'); + eq('b b\nb a', cm.getValue()); +}, {value: 'a a\na a'}); + +// More complex substitute tests that test both pcre and nopcre options. +function testSubstitute(name, options) { + testVim(name + '_pcre', function(cm, vim, helpers) { + cm.setCursor(1, 0); + CodeMirror.Vim.setOption('pcre', true); + helpers.doEx(options.expr); + eq(options.expectedValue, cm.getValue()); + }, options); + // If no noPcreExpr is defined, assume that it's the same as the expr. + var noPcreExpr = options.noPcreExpr ? options.noPcreExpr : options.expr; + testVim(name + '_nopcre', function(cm, vim, helpers) { + cm.setCursor(1, 0); + CodeMirror.Vim.setOption('pcre', false); + helpers.doEx(noPcreExpr); + eq(options.expectedValue, cm.getValue()); + }, options); +} +testSubstitute('ex_substitute_capture', { + value: 'a11 a12 a13', + expectedValue: 'a1111 a1212 a1313', + // $n is a backreference + expr: 's/(\\d+)/$1$1/g', + // \n is a backreference. + noPcreExpr: 's/\\(\\d+\\)/\\1\\1/g'}); +testSubstitute('ex_substitute_capture2', { + value: 'a 0 b', + expectedValue: 'a $00 b', + expr: 's/(\\d+)/$$$1$1/g', + noPcreExpr: 's/\\(\\d+\\)/$\\1\\1/g'}); +testSubstitute('ex_substitute_nocapture', { + value: 'a11 a12 a13', + expectedValue: 'a$1$1 a$1$1 a$1$1', + expr: 's/(\\d+)/$$1$$1/g', + noPcreExpr: 's/\\(\\d+\\)/$1$1/g'}); +testSubstitute('ex_substitute_nocapture2', { + value: 'a 0 b', + expectedValue: 'a $10 b', + expr: 's/(\\d+)/$$1$1/g', + noPcreExpr: 's/\\(\\d+\\)/\\$1\\1/g'}); +testSubstitute('ex_substitute_nocapture', { + value: 'a b c', + expectedValue: 'a $ c', + expr: 's/b/$$/', + noPcreExpr: 's/b/$/'}); +testSubstitute('ex_substitute_slash_regex', { + value: 'one/two \n three/four', + expectedValue: 'one|two \n three|four', + expr: '%s/\\//|'}); +testSubstitute('ex_substitute_pipe_regex', { + value: 'one|two \n three|four', + expectedValue: 'one,two \n three,four', + expr: '%s/\\|/,/', + noPcreExpr: '%s/|/,/'}); +testSubstitute('ex_substitute_or_regex', { + value: 'one|two \n three|four', + expectedValue: 'ana|twa \n thraa|faar', + expr: '%s/o|e|u/a/g', + noPcreExpr: '%s/o\\|e\\|u/a/g'}); +testSubstitute('ex_substitute_or_word_regex', { + value: 'one|two \n three|four', + expectedValue: 'five|five \n three|four', + expr: '%s/(one|two)/five/g', + noPcreExpr: '%s/\\(one\\|two\\)/five/g'}); +testSubstitute('ex_substitute_backslashslash_regex', { + value: 'one\\two \n three\\four', + expectedValue: 'one,two \n three,four', + expr: '%s/\\\\/,'}); +testSubstitute('ex_substitute_slash_replacement', { + value: 'one,two \n three,four', + expectedValue: 'one/two \n three/four', + expr: '%s/,/\\/'}); +testSubstitute('ex_substitute_backslash_replacement', { + value: 'one,two \n three,four', + expectedValue: 'one\\two \n three\\four', + expr: '%s/,/\\\\/g'}); +testSubstitute('ex_substitute_multibackslash_replacement', { + value: 'one,two \n three,four', + expectedValue: 'one\\\\\\\\two \n three\\\\\\\\four', // 2*8 backslashes. + expr: '%s/,/\\\\\\\\\\\\\\\\/g'}); // 16 backslashes. +testSubstitute('ex_substitute_braces_word', { + value: 'ababab abb ab{2}', + expectedValue: 'ab abb ab{2}', + expr: '%s/(ab){2}//g', + noPcreExpr: '%s/\\(ab\\)\\{2\\}//g'}); +testSubstitute('ex_substitute_braces_range', { + value: 'a aa aaa aaaa', + expectedValue: 'a a', + expr: '%s/a{2,3}//g', + noPcreExpr: '%s/a\\{2,3\\}//g'}); +testSubstitute('ex_substitute_braces_literal', { + value: 'ababab abb ab{2}', + expectedValue: 'ababab abb ', + expr: '%s/ab\\{2\\}//g', + noPcreExpr: '%s/ab{2}//g'}); +testSubstitute('ex_substitute_braces_char', { + value: 'ababab abb ab{2}', + expectedValue: 'ababab ab{2}', + expr: '%s/ab{2}//g', + noPcreExpr: '%s/ab\\{2\\}//g'}); +testSubstitute('ex_substitute_braces_no_escape', { + value: 'ababab abb ab{2}', + expectedValue: 'ababab ab{2}', + expr: '%s/ab{2}//g', + noPcreExpr: '%s/ab\\{2}//g'}); +testSubstitute('ex_substitute_count', { + value: '1\n2\n3\n4', + expectedValue: '1\n0\n0\n4', + expr: 's/\\d/0/i 2'}); +testSubstitute('ex_substitute_count_with_range', { + value: '1\n2\n3\n4', + expectedValue: '1\n2\n0\n0', + expr: '1,3s/\\d/0/ 3'}); +testSubstitute('ex_substitute_not_global', { + value: 'aaa\nbaa\ncaa', + expectedValue: 'xaa\nbxa\ncxa', + expr: '%s/a/x/'}); +function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) { + testVim(name, function(cm, vim, helpers) { + var savedOpenDialog = cm.openDialog; + var savedKeyName = CodeMirror.keyName; + var onKeyDown; + var recordedCallback; + var closed = true; // Start out closed, set false on second openDialog. + function close() { + closed = true; + } + // First openDialog should save callback. + cm.openDialog = function(template, callback, options) { + recordedCallback = callback; + } + // Do first openDialog. + helpers.doKeys(':'); + // Second openDialog should save keyDown handler. + cm.openDialog = function(template, callback, options) { + onKeyDown = options.onKeyDown; + closed = false; + }; + // Return the command to Vim and trigger second openDialog. + recordedCallback(command); + // The event should really use keyCode, but here just mock it out and use + // key and replace keyName to just return key. + CodeMirror.keyName = function (e) { return e.key; } + keys = keys.toUpperCase(); + for (var i = 0; i < keys.length; i++) { + is(!closed); + onKeyDown({ key: keys.charAt(i) }, '', close); + } + try { + eq(expectedValue, cm.getValue()); + helpers.assertCursorAt(finalPos); + is(closed); + } catch(e) { + throw e + } finally { + // Restore overriden functions. + CodeMirror.keyName = savedKeyName; + cm.openDialog = savedOpenDialog; + } + }, { value: initialValue }); +}; +testSubstituteConfirm('ex_substitute_confirm_emptydoc', + '%s/x/b/c', '', '', '', makeCursor(0, 0)); +testSubstituteConfirm('ex_substitute_confirm_nomatch', + '%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0)); +testSubstituteConfirm('ex_substitute_confirm_accept', + '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1)); +testSubstituteConfirm('ex_substitute_confirm_random_keys', + '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1)); +testSubstituteConfirm('ex_substitute_confirm_some', + '%s/a/b/cg', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1)); +testSubstituteConfirm('ex_substitute_confirm_all', + '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1)); +testSubstituteConfirm('ex_substitute_confirm_accept_then_all', + '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1)); +testSubstituteConfirm('ex_substitute_confirm_quit', + '%s/a/b/cg', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3)); +testSubstituteConfirm('ex_substitute_confirm_last', + '%s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); +testSubstituteConfirm('ex_substitute_confirm_oneline', + '1s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); +testSubstituteConfirm('ex_substitute_confirm_range_accept', + '1,2s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0)); +testSubstituteConfirm('ex_substitute_confirm_range_some', + '1,3s/a/b/cg', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0)); +testSubstituteConfirm('ex_substitute_confirm_range_all', + '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0)); +testSubstituteConfirm('ex_substitute_confirm_range_last', + '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0)); +//:noh should clear highlighting of search-results but allow to resume search through n +testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('match'); + helpers.doKeys('?'); + helpers.doEx('noh'); + eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared'); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting'); +}, { value: 'match nope match \n nope Match' }); +testVim('set_boolean', function(cm, vim, helpers) { + CodeMirror.Vim.defineOption('testoption', true, 'boolean'); + // Test default value is set. + is(CodeMirror.Vim.getOption('testoption')); + try { + // Test fail to set to non-boolean + CodeMirror.Vim.setOption('testoption', '5'); + fail(); + } catch (expected) {}; + // Test setOption + CodeMirror.Vim.setOption('testoption', false); + is(!CodeMirror.Vim.getOption('testoption')); +}); +testVim('ex_set_boolean', function(cm, vim, helpers) { + CodeMirror.Vim.defineOption('testoption', true, 'boolean'); + // Test default value is set. + is(CodeMirror.Vim.getOption('testoption')); + try { + // Test fail to set to non-boolean + helpers.doEx('set testoption=22'); + fail(); + } catch (expected) {}; + // Test setOption + helpers.doEx('set notestoption'); + is(!CodeMirror.Vim.getOption('testoption')); +}); +testVim('set_string', function(cm, vim, helpers) { + CodeMirror.Vim.defineOption('testoption', 'a', 'string'); + // Test default value is set. + eq('a', CodeMirror.Vim.getOption('testoption')); + try { + // Test fail to set non-string. + CodeMirror.Vim.setOption('testoption', true); + fail(); + } catch (expected) {}; + try { + // Test fail to set 'notestoption' + CodeMirror.Vim.setOption('notestoption', 'b'); + fail(); + } catch (expected) {}; + // Test setOption + CodeMirror.Vim.setOption('testoption', 'c'); + eq('c', CodeMirror.Vim.getOption('testoption')); +}); +testVim('ex_set_string', function(cm, vim, helpers) { + CodeMirror.Vim.defineOption('testoption', 'a', 'string'); + // Test default value is set. + eq('a', CodeMirror.Vim.getOption('testoption')); + try { + // Test fail to set 'notestoption' + helpers.doEx('set notestoption=b'); + fail(); + } catch (expected) {}; + // Test setOption + helpers.doEx('set testoption=c') + eq('c', CodeMirror.Vim.getOption('testoption')); +}); +// TODO: Reset key maps after each test. +testVim('ex_map_key2key', function(cm, vim, helpers) { + helpers.doEx('map a x'); + helpers.doKeys('a'); + helpers.assertCursorAt(0, 0); + eq('bc', cm.getValue()); +}, { value: 'abc' }); +testVim('ex_unmap_key2key', function(cm, vim, helpers) { + helpers.doEx('unmap a'); + helpers.doKeys('a'); + eq('vim-insert', cm.getOption('keyMap')); +}, { value: 'abc' }); +testVim('ex_unmap_key2key_does_not_remove_default', function(cm, vim, helpers) { + try { + helpers.doEx('unmap a'); + fail(); + } catch (expected) {} + helpers.doKeys('a'); + eq('vim-insert', cm.getOption('keyMap')); +}, { value: 'abc' }); +testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) { + helpers.doEx('map ; :'); + var dialogOpened = false; + cm.openDialog = function() { + dialogOpened = true; + } + helpers.doKeys(';'); + eq(dialogOpened, true); +}); +testVim('ex_map_ex2key:', function(cm, vim, helpers) { + helpers.doEx('map :del x'); + helpers.doEx('del'); + helpers.assertCursorAt(0, 0); + eq('bc', cm.getValue()); +}, { value: 'abc' }); +testVim('ex_map_ex2ex', function(cm, vim, helpers) { + helpers.doEx('map :del :w'); + var tmp = CodeMirror.commands.save; + var written = false; + var actualCm; + CodeMirror.commands.save = function(cm) { + written = true; + actualCm = cm; + }; + helpers.doEx('del'); + CodeMirror.commands.save = tmp; + eq(written, true); + eq(actualCm, cm); +}); +testVim('ex_map_key2ex', function(cm, vim, helpers) { + helpers.doEx('map a :w'); + var tmp = CodeMirror.commands.save; + var written = false; + var actualCm; + CodeMirror.commands.save = function(cm) { + written = true; + actualCm = cm; + }; + helpers.doKeys('a'); + CodeMirror.commands.save = tmp; + eq(written, true); + eq(actualCm, cm); +}); +testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) { + CodeMirror.Vim.map('b', ':w', 'visual'); + var tmp = CodeMirror.commands.save; + var written = false; + var actualCm; + CodeMirror.commands.save = function(cm) { + written = true; + actualCm = cm; + }; + // Mapping should not work in normal mode. + helpers.doKeys('b'); + eq(written, false); + // Mapping should work in visual mode. + helpers.doKeys('v', 'b'); + eq(written, true); + eq(actualCm, cm); + + CodeMirror.commands.save = tmp; +}); +testVim('ex_imap', function(cm, vim, helpers) { + CodeMirror.Vim.map('jk', '', 'insert'); + helpers.doKeys('i'); + is(vim.insertMode); + helpers.doKeys('j', 'k'); + is(!vim.insertMode); +}) + +// Testing registration of functions as ex-commands and mapping to -keys +testVim('ex_api_test', function(cm, vim, helpers) { + var res=false; + var val='from'; + CodeMirror.Vim.defineEx('extest','ext',function(cm,params){ + if(params.args)val=params.args[0]; + else res=true; + }); + helpers.doEx(':ext to'); + eq(val,'to','Defining ex-command failed'); + CodeMirror.Vim.map('',':ext'); + helpers.doKeys('',''); + is(res,'Mapping to key failed'); +}); +// For now, this test needs to be last because it messes up : for future tests. +testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) { + helpers.doEx('map : x'); + helpers.doKeys(':'); + helpers.assertCursorAt(0, 0); + eq('bc', cm.getValue()); +}, { value: 'abc' }); + +// Test event handlers +testVim('beforeSelectionChange', function(cm, vim, helpers) { + cm.setCursor(0, 100); + eqPos(cm.getCursor('head'), cm.getCursor('anchor')); +}, { value: 'abc' }); + + diff --git a/tool/update_deps.js b/tool/update_deps.js index 4b340ec2..d230fde6 100644 --- a/tool/update_deps.js +++ b/tool/update_deps.js @@ -1,7 +1,7 @@ -var https = require("https") - , http = require("http") - , url = require("url") - , fs = require("fs"); +var https = require("https"); +var http = require("http"); +var url = require("url"); +var fs = require("fs"); var Path = require("path"); var spawn = require("child_process").spawn; @@ -119,6 +119,22 @@ var deps = { }); } }, + vim: { + fetch: function(){ + var rootHref = "https://raw.githubusercontent.com/codemirror/CodeMirror/master/" + var fileMap = {"keymap/vim.js": "keyboard/vim2.js", "test/vim_test.js": "keyboard/vim2_test.js"}; + async.forEach(Object.keys(fileMap), function(x, next) { + download(rootHref + x, function(e, d) { + d = d.replace(/^\(function.*{[^{}]+^}[^{}]+{/m, "define(function(require, exports, module) {"); + d = d.replace(/^\s*return vimApi;\s*};/gm, " //};") + .replace("var Vim = function() {", "$& return vimApi; } //{") + fs.writeFile(rootDir + fileMap[x], d, next) + }) + }, function() { + console.log("done") + }); + } + }, coffee: { fetch: function(){ var rootHref = "https://raw.github.com/jashkenas/coffee-script/master/"; From 8daf190b2ecc88ce35840cb98f25dac51dd25499 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 28 Oct 2014 23:22:09 +0400 Subject: [PATCH 063/315] add CodeMirror api proxy for vim mode --- lib/ace/editor.js | 4 +- lib/ace/keyboard/vim2.js | 922 ++++++++++++++++++++++++++++++++++ lib/ace/keyboard/vim2_test.js | 106 +++- lib/ace/multi_select.js | 2 +- lib/ace/test/all_browser.js | 1 + 5 files changed, 1028 insertions(+), 7 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 9d911410..13aa2f60 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -158,7 +158,7 @@ var Editor = function(renderer, session) { if (this.curOp) { if (e && e.returnValue === false) return this.curOp = null; - + this._signal("beforeEndOperation"); var command = this.curOp.command; if (command && command.scrollIntoView) { switch (command.scrollIntoView) { @@ -2476,6 +2476,7 @@ var Editor = function(renderer, session) { **/ this.undo = function() { this.$blockScrolling++; + this.session.$syncInformUndoManager(); this.session.getUndoManager().undo(); this.$blockScrolling--; this.renderer.scrollCursorIntoView(null, 0.5); @@ -2487,6 +2488,7 @@ var Editor = function(renderer, session) { **/ this.redo = function() { this.$blockScrolling++; + this.session.$syncInformUndoManager(); this.session.getUndoManager().redo(); this.$blockScrolling--; this.renderer.scrollCursorIntoView(null, 0.5); diff --git a/lib/ace/keyboard/vim2.js b/lib/ace/keyboard/vim2.js index 27f18c6e..c0f780ac 100644 --- a/lib/ace/keyboard/vim2.js +++ b/lib/ace/keyboard/vim2.js @@ -62,6 +62,799 @@ define(function(require, exports, module) { 'use strict'; + /* function log() { + var d = ""; + function format(p) { + if (typeof p != "object") + return p + "" + if ("line" in p) { + return p.line + ":" + p.ch + } + if ("anchor" in p) { + return format(p.anchor) + "->" + format(p.head) + } + if (Array.isArray(p)) + return "[" + p.map(function(x) {return format(x)})+"]" + return JSON.stringify(p) + } + for (var i = 0; i < arguments.length; i++) { + var p = arguments[i] + var f = format(p) + d+= f+" " + } + console.log(d) + } */ + var Range = require("../range").Range; + var EventEmitter = require("../lib/event_emitter").EventEmitter; + var dom = require("../lib/dom"); + var oop = require("../lib/oop"); + var KEYS = require("../lib/keys"); + var event = require("../lib/event"); + var Search = require("../search").Search; + var SearchHighlight = require("../search_highlight").SearchHighlight; + var multiSelectCommands = require("../commands/multi_select_commands"); + require("../multi_select"); + + var CodeMirror = function(ace) { + this.ace = ace; + this.state = {}; + this.marks = {}; + this.$uid = 0; + this.onChange = this.onChange.bind(this); + this.onSelectionChange = this.onSelectionChange.bind(this); + this.onBeforeEndOperation = this.onBeforeEndOperation.bind(this); + this.ace.on('change', this.onChange); + this.ace.on('changeSelection', this.onSelectionChange); + this.ace.on('beforeEndOperation', this.onBeforeEndOperation); + }; + CodeMirror.Pos = function(line, ch) { + if (!(this instanceof Pos)) return new Pos(line, ch); + this.line = line; this.ch = ch; + }; + CodeMirror.defineOption = function(name, val, setter) {}; + CodeMirror.commands = { + redo: function(cm) { cm.ace.redo(); }, + undo: function(cm) { cm.ace.undo(); }, + newlineAndIndent: function(cm) { cm.ace.insert("\n"); }, + }; + CodeMirror.keyMap = {}; + CodeMirror.addClass = CodeMirror.rmClass = + CodeMirror.e_stop = function() {}; + CodeMirror.keyName = function(e) { + if (e.key) return e.key; + var key = (KEYS[e.keyCode] || ""); + if (key.length == 1) key = key.toUpperCase(); + key = event.getModifierString(e).replace(/(^|-)\w/g, function(m) { + return m.toUpperCase(); + }) + key; + return key; + }; + CodeMirror.keyMap['default'] = function(key) { + return function(cm) { + var cmd = cm.ace.commands.commandKeyBinding[key.toLowerCase()]; + return cmd && cm.ace.execCommand(cmd) !== false; + }; + }; + CodeMirror.lookupKey = function lookupKey(key, map, handle) { + if (typeof map == "string") + map = CodeMirror.keyMap[map]; + var found = typeof map == "function" ? map(key) : map[key]; + if (found === false) return "nothing"; + if (found === "...") return "multi"; + if (found != null && handle(found)) return "handled"; + + if (map.fallthrough) { + if (!Array.isArray(map.fallthrough)) + return lookupKey(key, map.fallthrough, handle); + for (var i = 0; i < map.fallthrough.length; i++) { + var result = lookupKey(key, map.fallthrough[i], handle); + if (result) return result; + } + } + }; + + CodeMirror.signal = function(o, name, e) { return o._signal(name, e) }; + CodeMirror.on = event.addListener; + CodeMirror.off = event.removeListener; +(function() { + oop.implement(CodeMirror.prototype, EventEmitter); + + this.destroy = function() { + this.ace.off('change', this.onChange); + this.ace.off('changeSelection', this.onSelectionChange); + this.ace.off('beforeEndOperation', this.onBeforeEndOperation); + this.removeOverlay(); + }; + this.virtualSelectionMode = function() { + return this.ace.inVirtualSelectionMode && this.ace.selection.index + }; + this.onChange = function(delta) { + var oldDelta = delta.data; + delta = { + start: oldDelta.range.start, + end: oldDelta.range.end, + action: oldDelta.action, + lines: oldDelta.lines || [oldDelta.text] + };// v1.2 api compatibility + if (delta.action[0] == 'i') { + var change = { text: delta.lines }; + var curOp = this.curOp = this.curOp || {}; + if (!curOp.changeHandlers) + curOp.changeHandlers = this._eventRegistry["change"] && this._eventRegistry["change"].slice(); + if (this.virtualSelectionMode()) return; + if (!curOp.lastChange) { + curOp.lastChange = curOp.change = change; + } else { + curOp.lastChange.next = curOp.lastChange = change; + } + } + this.$updateMarkers(delta); + }; + this.onSelectionChange = function() { + var curOp = this.curOp = this.curOp || {}; + if (!curOp.cursorActivityHandlers) + curOp.cursorActivityHandlers = this._eventRegistry["cursorActivity"] && this._eventRegistry["cursorActivity"].slice(); + this.curOp.cursorActivity = true; + if (this.ace.inMultiSelectMode) { + this.ace.keyBinding.removeKeyboardHandler(multiSelectCommands.keyboardHandler); + } + }; + this.operation = function(fn, force) { + if (!force && this.curOp || force && this.curOp && this.curOp.force) { + return fn(); + } + if (force || !this.ace.curOp) { + if (this.curOp) + this.onBeforeEndOperation(); + } + if (!this.ace.curOp) { + var prevOp = this.ace.prevOp; + this.ace.startOperation({ + command: { name: "vim", scrollIntoView: "cursor" } + }); + } + var curOp = this.curOp = this.curOp || {}; + this.curOp.force = force; + var result = fn(); + if (this.ace.curOp && this.ace.curOp.command.name == "vim") { + this.ace.endOperation(); + if (!curOp.cursorActivity && !curOp.lastChange && prevOp) + this.ace.prevOp = prevOp; + } + if (force || !this.ace.curOp) { + if (this.curOp) + this.onBeforeEndOperation(); + } + return result; + }; + this.onBeforeEndOperation = function() { + var op = this.curOp; + if (op) { + if (op.change) { this.signal("change", op.change, op); } + if (op && op.cursorActivity) { this.signal("cursorActivity", null, op); } + this.curOp = null; + } + }; + + this.signal = function(eventName, e, handlers) { + var listeners = handlers ? handlers[eventName + "Handlers"] + : (this._eventRegistry || {})[eventName]; + if (!listeners) + return; + listeners = listeners.slice(); + for (var i=0; i 0) { + point.row += rowShift; + point.column += point.row == end.row ? colShift : 0; + continue; + } + if (!isInsert && cmp2 <= 0) { + point.row = start.row; + point.column = start.column; + if (cmp2 === 0) + point.bias = 1 + } + } + }; + var Marker = function(cm, id, row, column) { + this.cm = cm; + this.id = id; + this.row = row; + this.column = column; + cm.marks[this.id] = this; + }; + Marker.prototype.clear = function() { delete this.cm.marks[this.id] }; + Marker.prototype.find = function() { return toCmPos(this) }; + this.setBookmark = function(cursor, options) { + var bm = new Marker(this, this.$uid++, cursor.line, cursor.ch); + if (!options || !options.insertLeft) + bm.$insertRight = true; + this.marks[bm.id] = bm; + return bm; + }; + this.moveH = function(increment, unit) { + if (unit == 'char') { + var sel = this.ace.selection; + sel.clearSelection(); + sel.moveCursorBy(0, increment); + } + }; + this.findPosV = function(start, amaount, unit, goalColumn) { + if (unit == 'line') { + var screenPos = this.ace.session.documentToScreenPosition(start.line, start.ch); + if (goalColumn != null) + screenPos.column = goalColumn; + screenPos.row += amaount; + // not what codemirror does but vim mode needs only it + screenPos.row = Math.min(Math.max(0, screenPos.row), this.ace.session.getScreenLength() - 1); + var pos = this.ace.session.screenToDocumentPosition(screenPos.row, screenPos.column); + return toCmPos(pos); + } else { + debugger; + } + }; + this.charCoords = function(pos, mode) { + if (mode == 'div' || !mode) { + var sc = this.ace.session.documentToScreenPosition(pos.line, pos.ch); + return {left: sc.column, top: sc.row}; + }if (mode == 'local') { + var renderer = this.ace.renderer; + var sc = this.ace.session.documentToScreenPosition(pos.line, pos.ch); + var lh = renderer.layerConfig.lineHeight; + var cw = renderer.layerConfig.characterWidth; + var top = lh * sc.row; + return {left: sc.column * cw, top: top, bottom: top + lh}; + } + }; + this.coordsChar = function(pos, mode) { + var renderer = this.ace.renderer; + if (mode == 'local') { + var row = Math.max(0, Math.floor(pos.top / renderer.lineHeight)); + var col = Math.max(0, Math.floor(pos.left / renderer.characterWidth)); + var ch = renderer.session.screenToDocumentPosition(row, col); + return toCmPos(ch); + } else if (mode == 'div') { + throw "not implemented"; + } + }; + this.openDialog = function() { + debugger + }; + this.getSearchCursor = function(query, pos, caseFold) { + var caseSensitive = false; + var isRegexp = false; + if (query instanceof RegExp && !query.global) { + caseSensitive = !query.ignoreCase; + query = query.source; + isRegexp = true; + } + var search = new Search(); + if (pos.ch == undefined) pos.ch = Number.MAX_VALUE; + var acePos = {row: pos.line, column: pos.ch}; + var cm = this; + var last = null; + return { + findNext: function() { return this.find(false) }, + findPrevious: function() {return this.find(true) }, + find: function(back) { + search.setOptions({ + needle: query, + caseSensitive: caseSensitive, + wrap: false, + backwards: back, + regExp: isRegexp, + start: last || acePos + }); + var range = search.find(cm.ace.session); + if (range && range.isEmpty()) { + if (cm.getLine(range.start.row).length == range.start.column) { + search.$options.start = range; + range = search.find(cm.ace.session); + } + } + last = range; + return last; + }, + from: function() { return last && toCmPos(last.start) }, + to: function() { return last && toCmPos(last.end) }, + replace: function(text) { + if (last) { + last.end = cm.ace.session.doc.replace(last, text); + } + } + }; + }; + this.scrollTo = function(x, y) { + var renderer = this.ace.renderer; + var config = renderer.layerConfig; + var maxHeight = config.maxHeight; + maxHeight -= (renderer.$size.scrollerHeight - renderer.lineHeight) * renderer.$scrollPastEnd; + if (y != null) this.ace.session.setScrollTop(Math.max(0, Math.min(y, maxHeight))); + if (x != null) this.ace.session.setScrollLeft(Math.max(0, Math.min(x, config.width))); + }; + this.scrollInfo = function() { return 0; }; + this.scrollIntoView = function(pos, margin) { + if (pos) + this.ace.renderer.scrollCursorIntoView(toAcePos(pos), null, margin); + }; + this.getLine = function(row) { return this.ace.session.getLine(row) }; + this.getRange = function(s, e) { + return this.ace.session.getTextRange(new Range(s.line, s.ch, e.line, e.ch)); + }; + this.replaceRange = function(text, s, e) { + if (!e) e = s; + return this.ace.session.replace(new Range(s.line, s.ch, e.line, e.ch), text); + }; + this.replaceSelections = function(p) { + var sel = this.ace.selection; + if (this.ace.inVirtualSelectionMode) { + this.ace.session.replace(sel.getRange(), p[0] || ""); + return; + } + sel.inVirtualSelectionMode = true; + var ranges = sel.rangeList.ranges; + if (!ranges.length) ranges = [this.ace.multiSelect.getRange()]; + for (var i = ranges.length; i--;) + this.ace.session.replace(ranges[i], p[i] || ""); + sel.inVirtualSelectionMode = false; + }; + this.getSelection = function() { + return this.ace.getSelectedText(); + }; + this.getSelections = function() { + return this.listSelections().map(function(x) { + return this.getRange(x.anchor, x.head); + }, this); + }; + this.getInputField = function() { + return this.ace.textInput.getElement(); + }; + this.getWrapperElement = function() { + return this.ace.containter; + }; + var optMap = { + indentWithTabs: "useSoftTabs", + indentUnit: "tabSize", + firstLineNumber: "firstLineNumber" + }; + this.setOption = function(name, val) { + this.state[name] = val; + switch (name) { + case 'indentWithTabs': + name = optMap[name]; + val = !val; + break; + default: + name = optMap[name]; + } + if (name) + this.ace.setOption(name, val); + }; + this.getOption = function(name, val) { + var aceOpt = optMap[name]; + if (aceOpt) + val = this.ace.getOption(aceOpt); + switch (name) { + case 'indentWithTabs': + name = optMap[name]; + return !val; + } + return aceOpt ? val : this.state[name]; + }; + this.toggleOverwrite = function(on) { + this.state.overwrite = on; + return this.ace.setOverwrite(on); + }; + this.addOverlay = function(o) { + if (!this.$searchHighlight || !this.$searchHighlight.session) { + var highlight = new SearchHighlight(null, "ace_highlight-marker", "text"); + var marker = this.ace.session.addDynamicMarker(highlight); + highlight.id = marker.id; + highlight.session = this.ace.session; + highlight.destroy = function(o) { + highlight.session.off("change", highlight.updateOnChange); + highlight.session.off("changeEditor", highlight.destroy); + highlight.session.removeMarker(highlight.id); + highlight.session = null; + }; + highlight.updateOnChange = function(delta) { + delta = delta.data.range;// v1.2 api compatibility + var row = delta.start.row; + if (row == delta.end.row) highlight.cache[row] = undefined; + else highlight.cache.splice(row, highlight.cache.length); + } + highlight.session.on("changeEditor", highlight.destroy); + highlight.session.on("change", highlight.updateOnChange); + } + var re = new RegExp(o.query.source, "gmi"); + console.log(re) + this.$searchHighlight = o.highlight = highlight; + this.$searchHighlight.setRegexp(re); + this.ace.renderer.updateBackMarkers(); + }; + this.removeOverlay = function(o) { + if (this.$searchHighlight && this.$searchHighlight.session) { + this.$searchHighlight.destroy(); + } + }; + this.getScrollInfo = function() { + var renderer = this.ace.renderer; + var config = renderer.layerConfig; + return { + left: renderer.scrollLeft, + top: renderer.scrollTop, + height: config.maxHeight, + width: config.width, + clientHeight: config.height, + clientWidth: config.width + }; + }; + this.getValue = function() { + return this.ace.getValue(); + }; + this.setValue = function(v) { + return this.ace.setValue(v); + }; + this.getTokenTypeAt = function(pos) { + var token = this.ace.session.getTokenAt(pos.line, pos.ch); + return token && /comment|string/.test(token.type) ? "string" : ""; + }; + this.findMatchingBracket = function(pos) { + var m = this.ace.session.findMatchingBracket(toAcePos(pos)); + return {to: m && toCmPos(m)}; + }; + this.indentLine = function(line, method) { + if (method === true) + this.ace.session.indentRows(line, line, "\t"); + else if (method === false) + this.ace.session.outdentRows(new Range(line, 0, line, 0)); + }; + this.indexFromPos = function(pos) { + return this.ace.session.doc.positionToIndex(toAcePos(pos)); + }; + this.posFromIndex = function(index) { + return toCmPos(this.ace.session.doc.indexToPosition(index)); + }; + this.focus = function(index) { + return this.ace.focus(); + }; + this.blur = function(index) { + return this.ace.blur(); + }; + this.defaultTextHeight = function(index) { + return this.ace.renderer.layerConfig.lineHeight; + }; + this.scanForBracket = function(pos, dir, _, options) { + var re = options.bracketRegex.source; + if (dir == 1) { + var m = this.ace.session.$findClosingBracket(re.slice(1, 2), toAcePos(pos), /paren|text/); + } else { + var m = this.ace.session.$findOpeningBracket(re.slice(-2, -1), {row: pos.line, column: pos.ch + 1}, /paren|text/); + } + return m && {pos: toCmPos(m)}; + }; + this.refresh = function() { + return this.ace.resize(true); + }; +}).call(CodeMirror.prototype); + function toAcePos(cmPos) { + return {row: cmPos.line, column: cmPos.ch}; + } + function toCmPos(acePos) { + return new Pos(acePos.row, acePos.column); + } + + var StringStream = CodeMirror.StringStream = function(string, tabSize) { + this.pos = this.start = 0; + this.string = string; + this.tabSize = tabSize || 8; + this.lastColumnPos = this.lastColumnValue = 0; + this.lineStart = 0; + }; + + StringStream.prototype = { + eol: function() {return this.pos >= this.string.length;}, + sol: function() {return this.pos == this.lineStart;}, + peek: function() {return this.string.charAt(this.pos) || undefined;}, + next: function() { + if (this.pos < this.string.length) + return this.string.charAt(this.pos++); + }, + eat: function(match) { + var ch = this.string.charAt(this.pos); + if (typeof match == "string") var ok = ch == match; + else var ok = ch && (match.test ? match.test(ch) : match(ch)); + if (ok) {++this.pos; return ch;} + }, + eatWhile: function(match) { + var start = this.pos; + while (this.eat(match)){} + return this.pos > start; + }, + eatSpace: function() { + var start = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; + return this.pos > start; + }, + skipToEnd: function() {this.pos = this.string.length;}, + skipTo: function(ch) { + var found = this.string.indexOf(ch, this.pos); + if (found > -1) {this.pos = found; return true;} + }, + backUp: function(n) {this.pos -= n;}, + column: function() { + throw "not implemented"; + }, + indentation: function() { + throw "not implemented"; + }, + match: function(pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; + var substr = this.string.substr(this.pos, pattern.length); + if (cased(substr) == cased(pattern)) { + if (consume !== false) this.pos += pattern.length; + return true; + } + } else { + var match = this.string.slice(this.pos).match(pattern); + if (match && match.index > 0) return null; + if (match && consume !== false) this.pos += match[0].length; + return match; + } + }, + current: function(){return this.string.slice(this.start, this.pos);}, + hideFirstChars: function(n, inner) { + this.lineStart += n; + try { return inner(); } + finally { this.lineStart -= n; } + } + }; + +// todo replace with showCommandLine +CodeMirror.defineExtension = function(name, fn) { + CodeMirror.prototype[name] = fn; +}; +dom.importCssString(".normal-mode .ace_cursor{\ + border: 0!important;\ + background-color: red;\ + opacity: 0.5;\ +}.ace_dialog {\ + position: absolute;\ + left: 0; right: 0;\ + background: white;\ + z-index: 15;\ + padding: .1em .8em;\ + overflow: hidden;\ + color: #333;\ +}\ +.ace_dialog-top {\ + border-bottom: 1px solid #eee;\ + top: 0;\ +}\ +.ace_dialog-bottom {\ + border-top: 1px solid #eee;\ + bottom: 0;\ +}\ +.ace_dialog input {\ + border: none;\ + outline: none;\ + background: transparent;\ + width: 20em;\ + color: inherit;\ + font-family: monospace;\ +}", "vimMode"); +(function() { + function dialogDiv(cm, template, bottom) { + var wrap = cm.ace.container; + var dialog; + dialog = wrap.appendChild(document.createElement("div")); + if (bottom) + dialog.className = "ace_dialog ace_dialog-bottom"; + else + dialog.className = "ace_dialog ace_dialog-top"; + + if (typeof template == "string") { + dialog.innerHTML = template; + } else { // Assuming it's a detached DOM element. + dialog.appendChild(template); + } + return dialog; + } + + function closeNotification(cm, newVal) { + if (cm.state.currentNotificationClose) + cm.state.currentNotificationClose(); + cm.state.currentNotificationClose = newVal; + } + + CodeMirror.defineExtension("openDialog", function(template, callback, options) { + if (this.virtualSelectionMode()) return; + if (!options) options = {}; + + closeNotification(this, null); + + var dialog = dialogDiv(this, template, options.bottom); + var closed = false, me = this; + function close(newVal) { + if (typeof newVal == 'string') { + inp.value = newVal; + } else { + if (closed) return; + closed = true; + dialog.parentNode.removeChild(dialog); + me.focus(); + + if (options.onClose) options.onClose(dialog); + } + } + + var inp = dialog.getElementsByTagName("input")[0], button; + if (inp) { + if (options.value) { + inp.value = options.value; + inp.select(); + } + + if (options.onInput) + CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); + if (options.onKeyUp) + CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); + + CodeMirror.on(inp, "keydown", function(e) { + if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } + if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { + inp.blur(); + CodeMirror.e_stop(e); + close(); + } + if (e.keyCode == 13) callback(inp.value); + }); + + if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close); + + inp.focus(); + } else if (button = dialog.getElementsByTagName("button")[0]) { + CodeMirror.on(button, "click", function() { + close(); + me.focus(); + }); + + if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); + + button.focus(); + } + return close; + }); + + CodeMirror.defineExtension("openNotification", function(template, options) { + if (this.virtualSelectionMode()) return; + closeNotification(this, close); + var dialog = dialogDiv(this, template, options && options.bottom); + var closed = false, doneTimer; + var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; + + function close() { + if (closed) return; + closed = true; + clearTimeout(doneTimer); + dialog.parentNode.removeChild(dialog); + } + + CodeMirror.on(dialog, 'click', function(e) { + CodeMirror.e_preventDefault(e); + close(); + }); + + if (duration) + doneTimer = setTimeout(close, duration); + + return close; + }); +})(); + + var defaultKeymap = [ // Key to key mapping. This goes first to make it possible to override // existing mappings. @@ -3752,6 +4545,11 @@ define(function(require, exports, module) { } } function getUserVisibleLines(cm) { + var renderer = cm.ace.renderer; + return { + top: renderer.getFirstFullyVisibleRow(), + bottom: renderer.getLastFullyVisibleRow() + } var scrollInfo = cm.getScrollInfo(); var occludeToleranceTop = 6; var occludeToleranceBottom = 10; @@ -4838,4 +5636,128 @@ define(function(require, exports, module) { //}; // Initialize Vim and make it available as an API. CodeMirror.Vim = Vim(); + + Vim = CodeMirror.Vim; + + specialKey = {'return':'CR',backspace:'BS','delete':'Del',esc:'Esc', + left:'Left',right:'Right',up:'Up',down:'Down',space: 'Space', + home:'Home',end:'End',pageup:'PageUp',pagedown:'PageDown', enter: 'CR' + }; + function lookupKey(hashId, key, e) { + if (key.length > 1 && key[0] == "n") { + key = key.replace("numpad", ""); + } + key = specialKey[key] || key; + var name = ''; + if (e.ctrlKey) { name += 'C-'; } + if (e.altKey) { name += 'A-'; } + if (e.shiftKey) { name += 'S-'; } + + name += key; + if (name.length > 1) { name = '<' + name + '>'; } + return name; + } + var handleKey = CodeMirror.Vim.handleKey + CodeMirror.Vim.handleKey = function(cm, key, origin) { + return cm.operation(function() { + return handleKey(cm, key, origin); + }, true); + }; + exports.CodeMirror = CodeMirror; + var getVim = Vim.maybeInitVimState_; + exports.handler = { + cm: null, + drawCursor: function(style, pixelPos, config, sel, session) { + var vim = this.cm.state.vim; + var w = config.characterWidth; + var h = config.lineHeight; + var top = pixelPos.top; + var left = pixelPos.left; + if (!vim.insertMode) { + var isbackwards = !sel.cursor + ? session.selection.isBackwards() || session.selection.isEmpty() + : Range.comparePoints(sel.cursor, sel.start) <= 0 + if (!isbackwards && left > w) + left -= w + } + if (!vim.insertMode && vim.status) { + h = h / 2; + top += h; + } + style.left = left + "px"; + style.top = top + "px"; + style.width = w + "px"; + style.height = h + "px"; + }, + handleKeyboard: function(data, hashId, key, keyCode, e) { + var cm = data.editor.state.cm; + var vim = getVim(cm); + if (keyCode == -1) return; + if (hashId == -1 || hashId & 1 || hashId === 0 && key.length > 1) { + var insertMode = vim.insertMode; + var name = lookupKey(hashId, key, e || {}); + if (vim.status == null) + vim.status = ""; + var isHandled = CodeMirror.Vim.handleKey(cm, name, 'user'); + if (isHandled && vim.status != null) + vim.status += name; + else if (vim.status == null) + vim.status = ""; + cm._signal("changeStatus"); + if (!isHandled && (hashId != -1 || insertMode)) + return; + return {command: "null", passEvent: !isHandled}; + } + }, + attach: function(editor) { + if (!editor.state) editor.state = {}; + var cm = new CodeMirror(editor); + editor.state.cm = cm; + editor.$vimModeHandler = Object.create(this); + editor.$vimModeHandler.cm = editor.state.cm; + var vim = CodeMirror.Vim.maybeInitVimState_(cm); + CodeMirror.keyMap.vim.attach(cm); + vim.status = null; + cm.on('vim-command-done', function() { + vim.status = null; + cm.ace._signal("changeStatus"); + }); + cm.on("changeStatus", function() { + cm.ace.renderer.updateCursor(); + cm.ace._signal("changeStatus"); + }); + cm.on("vim-mode-change", function() { + cm.ace.renderer.setStyle("normal-mode", !vim.insertMode); + cm._signal("changeStatus"); + }); + cm.ace.renderer.setStyle("normal-mode", !vim.insertMode); + editor.renderer.$cursorLayer.drawCursor = this.drawCursor.bind(editor.$vimModeHandler); + }, + detach: function(editor) { + var cm = editor.state.cm; + CodeMirror.keyMap.vim.detach(cm); + cm.destroy(); + editor.state.cm = null; + editor.$vimModeHandler = null; + editor.renderer.$cursorLayer.drawCursor = null; + editor.renderer.setStyle("normal-mode", false); + }, + getStatusText: function(editor) { + var cm = editor.state.cm; + var vim = getVim(cm); + if (vim.insertMode) + return "INSERT"; + var status = ""; + if (vim.visualMode) { + status += "VISUAL"; + if (vim.visualLine) + status += " LINE"; + if (vim.visualBlock) + status += " BLOCK"; + } + if (vim.status) + status += (status ? " " : "") + vim.status; + return status; + } + } }); diff --git a/lib/ace/keyboard/vim2_test.js b/lib/ace/keyboard/vim2_test.js index 7f016c47..b437bcd7 100644 --- a/lib/ace/keyboard/vim2_test.js +++ b/lib/ace/keyboard/vim2_test.js @@ -1,3 +1,90 @@ + +if (typeof process !== "undefined") { + require("amd-loader"); +} + +define(function(require, exports, module) { + +var EditSession = require("./../edit_session").EditSession; +var Editor = require("./../editor").Editor; +var UndoManager = require("./../undomanager").UndoManager; +var MockRenderer = require("./../test/mockrenderer").MockRenderer; +var JavaScriptMode = require("./../mode/javascript").Mode; +var VirtualRenderer = require("./../virtual_renderer").VirtualRenderer; +var assert = require("./../test/assertions"); +var keys = require("./../lib/keys"); +var vim = require("./vim2"); + +var el = document.createElement("div"); +el.style.position = "fixed"; +el.style.left = "20px"; +el.style.top = "30px"; +el.style.width = "500px"; +el.style.height = "300px"; +document.body.appendChild(el); + +if (!el.getBoundingClientRect) + return console.log("Skipping test: This test only runs in the browser"); + +var renderer = new VirtualRenderer(el); +editor = new Editor(renderer);//(new MockRenderer()); +editor.session.setUndoManager(new UndoManager()); +editor.session.setUseWorker(false); +editor.session.setMode(new JavaScriptMode()); +function CodeMirror(place, opts) { + if (opts.value != null) + editor.session.setValue(opts.value); + editor.setOption("wrap", opts.lineWrapping); + editor.setOption("useSoftTabs", !opts.indentWithTabs); + editor.setKeyboardHandler(null); + editor.setKeyboardHandler(vim.handler); + var cm = editor.state.cm; + cm.setOption("tabSize", opts.tabSize || 4); + cm.setOption("indentUnit", opts.indentUnit || 2); + + cm.setSize = function(w, h) { + var changed = false; + if (w && editor.w != w) { + changed = true; + el.style.width = (editor.w = w) + "px"; + } + if (h && editor.h != h) { + changed = true; + el.style.height = (editor.h = h) + "px"; + } + if (changed) + editor.resize(true); + }; + cm.setSize(500, 300); + return cm; +} +for (var key in vim.CodeMirror) + CodeMirror[key] = vim.CodeMirror[key]; +var editor; +var i = 0; +function test(name, fn) { + // if (name != 'vim_search_history') return + // for (i = 0; i < 1000; i++) + // exports["test " + name + i] = fn; // vim_ex_global_confirm + if (i++ < 0 || /- /.test(name)) + exports["test " + name] = function() {}; + else + exports["test " + name] = fn; +} + + +// cm.setBookmark({ch: 5, line: 0}) +// cm.setBookmark({ch: 4, line: 0}) +// cm.replaceRange("x-", {ch: 4, line: 0}, {ch: 5, line: 0}); [editor.$vimModeHandler.cm.marks[0].find(),editor.$vimModeHandler.cm.marks[1].find()] + +var lineText, verbose, phantom; +var Pos = CodeMirror.Pos; +var place = document.createElement("div"); +var eqPos = assert.deepEqual; +var eq = assert.equal; +var is = assert.ok; + + var code = '' + ' wOrd1 (#%\n' + ' word3] \n' + @@ -203,11 +290,11 @@ function testVim(name, run, opts, expectedFail) { successful = true; } finally { cm.openNotification = savedOpenNotification; - if (!successful || verbose) { - place.style.visibility = "visible"; - } else { - place.removeChild(cm.getWrapperElement()); - } + // if (!successful || verbose) { + // place.style.visibility = "visible"; + // } else { + // place.removeChild(cm.getWrapperElement()); + // } } }, expectedFail); }; @@ -2840,6 +2927,7 @@ testVim('HML', function(cm, vim, helpers) { var textHeight = cm.defaultTextHeight(); cm.setSize(600, lines*textHeight); cm.setCursor(120, 0); + cm.refresh(); //ace! helpers.doKeys('H'); helpers.assertCursorAt(86, 2); helpers.doKeys('L'); @@ -2952,10 +3040,12 @@ testVim('scrollMotion', function(cm, vim, helpers){ is(prevScrollInfo.top < cm.getScrollInfo().top); // Jump to the end of the sandbox. cm.setCursor(1000, 0); + cm.refresh(); //ace! prevCursor = cm.getCursor(); // ctrl-e at the bottom of the file should have no effect. helpers.doKeys(''); eq(prevCursor.line, cm.getCursor().line); + cm.refresh(); //ace! prevScrollInfo = cm.getScrollInfo(); helpers.doKeys(''); eq(prevCursor.line - 1, cm.getCursor().line); @@ -3612,3 +3702,9 @@ testVim('beforeSelectionChange', function(cm, vim, helpers) { }, { value: 'abc' }); +}); + + +if (typeof module !== "undefined" && module === require.main) { + require("asyncjs").test.testcase(module.exports).exec(); +} diff --git a/lib/ace/multi_select.js b/lib/ace/multi_select.js index f393012e..04d644ce 100644 --- a/lib/ace/multi_select.js +++ b/lib/ace/multi_select.js @@ -552,7 +552,7 @@ var Editor = require("./editor").Editor; var pos = anchor == this.multiSelect.anchor ? range.cursor == range.start ? range.end : range.start : range.cursor; - if (!isSamePoint(pos, anchor)) + if (!isSamePoint(this.session.$clipPositionToDocument(pos.row, pos.column), anchor)) this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange()); } }; diff --git a/lib/ace/test/all_browser.js b/lib/ace/test/all_browser.js index 9b5742dd..f05148e9 100644 --- a/lib/ace/test/all_browser.js +++ b/lib/ace/test/all_browser.js @@ -25,6 +25,7 @@ var testNames = [ "ace/keyboard/emacs_test", "ace/keyboard/keybinding_test", "ace/keyboard/vim_test", + "ace/keyboard/vim2_test", "ace/layer/text_test", "ace/lib/event_emitter_test", "ace/mode/coffee/parser_test", From aa472742cca502ade03bfb03861d186c30df9a52 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 28 Oct 2014 21:19:43 +0400 Subject: [PATCH 064/315] allow to customize cursor appearance --- lib/ace/layer/cursor.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/ace/layer/cursor.js b/lib/ace/layer/cursor.js index 4578482a..53c30e56 100644 --- a/lib/ace/layer/cursor.js +++ b/lib/ace/layer/cursor.js @@ -195,11 +195,15 @@ var Cursor = function(parentEl) { } var style = (this.cursors[cursorIndex++] || this.addCursor()).style; - - style.left = pixelPos.left + "px"; - style.top = pixelPos.top + "px"; - style.width = config.characterWidth + "px"; - style.height = config.lineHeight + "px"; + + if (!this.drawCursor) { + style.left = pixelPos.left + "px"; + style.top = pixelPos.top + "px"; + style.width = config.characterWidth + "px"; + style.height = config.lineHeight + "px"; + } else { + this.drawCursor(style, pixelPos, config, selections[i], this.session); + } } while (this.cursors.length > cursorIndex) this.removeCursor(); @@ -211,6 +215,8 @@ var Cursor = function(parentEl) { this.$pixelPos = pixelPos; this.restartTimer(); }; + + this.drawCursor = null; this.$setOverwrite = function(overwrite) { if (overwrite != this.overwrite) { From bd7de6b43b25faf5c449a16838b0204a6e0468ba Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 28 Oct 2014 22:01:33 +0400 Subject: [PATCH 065/315] fix find next for regexps matching empty range --- lib/ace/search.js | 21 ++++++++++++++------- lib/ace/search_test.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/lib/ace/search.js b/lib/ace/search.js index c5119319..2785640b 100644 --- a/lib/ace/search.js +++ b/lib/ace/search.js @@ -102,8 +102,8 @@ var Search = function() { * @returns {Range} **/ this.find = function(session) { - var iterator = this.$matchIterator(session, this.$options); - + var options = this.$options; + var iterator = this.$matchIterator(session, options); if (!iterator) return false; @@ -111,7 +111,13 @@ var Search = function() { iterator.forEach(function(range, row, offset) { if (!range.start) { var column = range.offset + (offset || 0); - firstRange = new Range(row, column, row, column+range.length); + firstRange = new Range(row, column, row, column + range.length); + if (!range.length && options.start && options.start.start + && options.skipCurrent != false && firstRange.isEqual(options.start) + ) { + firstRange = null; + return false; + } } else firstRange = range; return true; @@ -240,8 +246,7 @@ var Search = function() { if (!re) return false; - var self = this, callback, backwards = options.backwards; - + var callback; if (options.$isMultiLine) { var len = re.length; var matchIterator = function(line, row, offset) { @@ -266,7 +271,7 @@ var Search = function() { if (callback(range)) return true; }; - } else if (backwards) { + } else if (options.backwards) { var matchIterator = function(line, row, startIndex) { var matches = lang.getMatchOffsets(line, re); for (var i = matches.length-1; i >= 0; i--) @@ -281,11 +286,13 @@ var Search = function() { return true; }; } + + var lineIterator = this.$lineIterator(session, options); return { forEach: function(_callback) { callback = _callback; - self.$lineIterator(session, options).forEach(matchIterator); + lineIterator.forEach(matchIterator); } }; }; diff --git a/lib/ace/search_test.js b/lib/ace/search_test.js index 6e12a53e..3c27c4d8 100644 --- a/lib/ace/search_test.js +++ b/lib/ace/search_test.js @@ -36,6 +36,8 @@ define(function(require, exports, module) { "use strict"; var EditSession = require("./edit_session").EditSession; +var MockRenderer = require("./test/mockrenderer").MockRenderer; +var Editor = require("./editor").Editor; var Search = require("./search").Search; var assert = require("./test/assertions"); @@ -451,6 +453,37 @@ module.exports = { assert.position(ranges[1].end, 0, 11); assert.position(ranges[0].start, 0, 0); assert.position(ranges[0].end, 0, 3); + }, + + "test: find next empty range" : function() { + var session = new EditSession("foo foobar foo"); + var editor = new Editor(new MockRenderer(), session); + + var options = { + needle: "o*", + wrap: true, + regExp: true, + backwards: false + }; + var positions = [4, 5.2, 7, 8, 9, 10, 11, 12.2, 14, 0, 1.2, 3]; + + session.selection.moveCursorTo(0, 3); + for (var i = 0; i < 12; i++) { + editor.find(options) + var range = editor.selection.getRange(); + var start = range.start.column; + var len = range.end.column - start; + assert.equal(start + 0.1 * len, positions[i]) + } + options.backwards = true; + positions = [1.2, 1, 0, 14, 12.2, 12, 11, 10, 9, 8, 7, 5.2, 5, 4, 3]; + for (var i = 0; i < 16; i++) { + editor.find(options); + var range = editor.selection.getRange(); + var start = range.start.column; + var len = range.end.column - start; + console.log(start + 0.1 * len) + } } }; From 068c950517fecc4cfb0cd620b532790764511251 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 4 Nov 2014 17:43:57 +0400 Subject: [PATCH 066/315] add support for multiple selections --- lib/ace/keyboard/vim2.js | 160 ++++++++++++++++++++++++++++++++++----- 1 file changed, 140 insertions(+), 20 deletions(-) diff --git a/lib/ace/keyboard/vim2.js b/lib/ace/keyboard/vim2.js index c0f780ac..4b709888 100644 --- a/lib/ace/keyboard/vim2.js +++ b/lib/ace/keyboard/vim2.js @@ -1161,14 +1161,19 @@ dom.importCssString(".normal-mode .ace_cursor{\ function defineOption(name, defaultValue, type) { if (defaultValue === undefined) { throw Error('defaultValue is required'); } if (!type) { type = 'string'; } - options[name] = { - type: type, - defaultValue: defaultValue - }; + var opt = name; + if (typeof name == "string") + opt = { + type: type, + defaultValue: defaultValue + }; + else + name = opt.name; + options[name] = opt; setOption(name, defaultValue); } - function setOption(name, value) { + function setOption(name, value, cm) { var option = options[name]; if (!option) { throw Error('Unknown option: ' + name); @@ -1181,7 +1186,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ value = true; } } - option.value = option.type == 'boolean' ? !!value : value; + option.value = value; + if (option.set) option.set(value, cm); } function getOption(name) { @@ -2564,6 +2570,9 @@ dom.importCssString(".normal-mode .ace_cursor{\ } else if (character === 'w') { tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, false /** bigWord */); + } else if (character === 'p') { + tmp = expandParagraphUnderCursor(cm, inclusive, true /** forward */, + false /** bigWord */); } else { // No text object defined for this, don't move. return null; @@ -4867,7 +4876,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ showConfirm(cm, ' ' + optionName + '=' + oldValue); } } else { - setOption(optionName, value); + setOption(optionName, value, cm); } }, registers: function(cm,params) { @@ -5657,18 +5666,61 @@ dom.importCssString(".normal-mode .ace_cursor{\ if (name.length > 1) { name = '<' + name + '>'; } return name; } - var handleKey = CodeMirror.Vim.handleKey - CodeMirror.Vim.handleKey = function(cm, key, origin) { + var handleKey = Vim.handleKey + Vim.handleKey = function(cm, key, origin) { return cm.operation(function() { return handleKey(cm, key, origin); }, true); + } + function cloneVimState(state) { + var n = new state.constructor(); + Object.keys(state).forEach(function(key) { + var o = state[key]; + if (Array.isArray(o)) + o = o.slice(); + else if (o && typeof o == "object" && o.constructor != Object) + o = cloneVimState(o); + n[key] = o; + }); + return n; + } + function multiSelectHandleKey(cm, key, origin) { + var isHandled = false; + var vim = Vim.maybeInitVimState_(cm); + var visualBlock = vim.visualBlock || vim.wasInVisualBlock; + if (vim.wasInVisualBlock && !cm.ace.inMultiSelectMode) { + vim.wasInVisualBlock = false; + } else if (cm.ace.inMultiSelectMode && vim.visualBlock) { + vim.wasInVisualBlock = true; + } + + if (key == '' && !vim.insertMode && !vim.visualMode && cm.ace.inMultiSelectMode) { + cm.ace.exitMultiSelectMode(); + } else if (visualBlock || !cm.ace.inMultiSelectMode || cm.ace.inVirtualSelectionMode) { + isHandled = Vim.handleKey(cm, key, origin); + } else { + var old = cloneVimState(vim); + cm.operation(function() { + cm.ace.forEachSelection(function() { + var sel = cm.ace.selection; + cm.state.vim.lastHPos = sel.$desiredColumn == null ? sel.lead.column : sel.$desiredColumn; + isHandled = handleKey(cm, key, origin); + sel.$desiredColumn = cm.state.vim.lastHPos == -1 ? null : cm.state.vim.lastHPos; + if (cm.virtualSelectionMode()) { + cm.state.vim = cloneVimState(old); + } + }); + if (cm.curOp.cursorActivity && !isHandled) + cm.curOp.cursorActivity = false; + }, true); + } + return isHandled; }; exports.CodeMirror = CodeMirror; var getVim = Vim.maybeInitVimState_; exports.handler = { - cm: null, drawCursor: function(style, pixelPos, config, sel, session) { - var vim = this.cm.state.vim; + var vim = this.state.vim || {}; var w = config.characterWidth; var h = config.lineHeight; var top = pixelPos.top; @@ -5698,7 +5750,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ var name = lookupKey(hashId, key, e || {}); if (vim.status == null) vim.status = ""; - var isHandled = CodeMirror.Vim.handleKey(cm, name, 'user'); + var isHandled = multiSelectHandleKey(cm, name, 'user'); + vim = getVim(cm); // may be changed by multiSelectHandleKey if (isHandled && vim.status != null) vim.status += name; else if (vim.status == null) @@ -5713,25 +5766,27 @@ dom.importCssString(".normal-mode .ace_cursor{\ if (!editor.state) editor.state = {}; var cm = new CodeMirror(editor); editor.state.cm = cm; - editor.$vimModeHandler = Object.create(this); - editor.$vimModeHandler.cm = editor.state.cm; - var vim = CodeMirror.Vim.maybeInitVimState_(cm); + editor.$vimModeHandler = this; CodeMirror.keyMap.vim.attach(cm); - vim.status = null; + getVim(cm).status = null; cm.on('vim-command-done', function() { - vim.status = null; + if (cm.virtualSelectionMode()) return; + getVim(cm).status = null; cm.ace._signal("changeStatus"); + cm.ace.session.markUndoGroup(); }); cm.on("changeStatus", function() { cm.ace.renderer.updateCursor(); cm.ace._signal("changeStatus"); }); cm.on("vim-mode-change", function() { - cm.ace.renderer.setStyle("normal-mode", !vim.insertMode); + if (cm.virtualSelectionMode()) return; + cm.ace.renderer.setStyle("normal-mode", !getVim(cm).insertMode); cm._signal("changeStatus"); }); - cm.ace.renderer.setStyle("normal-mode", !vim.insertMode); - editor.renderer.$cursorLayer.drawCursor = this.drawCursor.bind(editor.$vimModeHandler); + cm.ace.renderer.setStyle("normal-mode", !getVim(cm).insertMode); + editor.renderer.$cursorLayer.drawCursor = this.drawCursor.bind(cm); + renderVirtualNumbers.attach(editor); }, detach: function(editor) { var cm = editor.state.cm; @@ -5741,6 +5796,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ editor.$vimModeHandler = null; editor.renderer.$cursorLayer.drawCursor = null; editor.renderer.setStyle("normal-mode", false); + renderVirtualNumbers.detach(editor); }, getStatusText: function(editor) { var cm = editor.state.cm; @@ -5760,4 +5816,68 @@ dom.importCssString(".normal-mode .ace_cursor{\ return status; } } + var renderVirtualNumbers = { + getText: function(session, row) { + return (Math.abs(session.selection.lead.row - row) || (row + 1 + (row < 9? "\xb7" : "" ))) + "" + }, + getWidth: function(session, lastLineNumber, config) { + return session.getLength().toString().length * config.characterWidth; + }, + update: function(e, editor) { + editor.renderer.$loop.schedule(editor.renderer.CHANGE_GUTTER) + }, + attach: function(editor) { + editor.renderer.$gutterLayer.$renderer = this; + editor.on("changeSelection", this.update); + }, + detach: function(editor) { + editor.renderer.$gutterLayer.$renderer = null; + editor.off("changeSelection", this.update); + } + }; + Vim.defineOption({ + name: "wrap", + set: function(value, cm) { + if (cm) {cm.ace.setOption("wrap", value)} + }, + type: "boolean" + }, false); + defaultKeymap.push( + { keys: 'zc', type: 'action', action: 'fold', actionArgs: { open: false } }, + { keys: 'zC', type: 'action', action: 'fold', actionArgs: { open: false, all: true } }, + { keys: 'zo', type: 'action', action: 'fold', actionArgs: { open: true, } }, + { keys: 'zO', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, + { keys: 'za', type: 'action', action: 'fold', actionArgs: { toggle: true } }, + { keys: 'zA', type: 'action', action: 'fold', actionArgs: { toggle: true, all: true } }, + { keys: 'zf', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, + { keys: 'zd', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, + + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAbove" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelow" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAboveSkipCurrent" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelowSkipCurrent" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreBefore" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreAfter" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectNextBefore" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectNextAfter" } } + ); + actions.aceCommand = function(cm, actionArgs, vim) { + cm.vimCmd = actionArgs; + if (cm.ace.inVirtualSelectionMode) + cm.ace.on("beforeEndOperation", delayedExecAceCommand); + else + delayedExecAceCommand(null, cm.ace) + }; + function delayedExecAceCommand(op, ace) { + ace.off("beforeEndOperation", delayedExecAceCommand); + var cmd = ace.state.cm.vimCmd; + if (cmd) { + ace.execCommand(cmd.name, cmd.args); + } + ace.curOp = ace.prevOp; + } + actions.fold = function(cm, actionArgs, vim) { + cm.ace.execCommand(['toggleFoldWidget', 'toggleFoldWidget', 'foldOther', 'unfoldall' + ][(actionArgs.all ? 2 : 0) + (actionArgs.open ? 1 : 0)]); + } }); From f9de0a56614354c230e9768b58b33217f0f21599 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 11 Nov 2014 13:02:30 +0400 Subject: [PATCH 067/315] use ctrl-c and mac repeat handling from old vim mode --- lib/ace/keyboard/vim2.js | 147 +++++++++++++++++++++++++++++---------- 1 file changed, 112 insertions(+), 35 deletions(-) diff --git a/lib/ace/keyboard/vim2.js b/lib/ace/keyboard/vim2.js index 4b709888..0e860db1 100644 --- a/lib/ace/keyboard/vim2.js +++ b/lib/ace/keyboard/vim2.js @@ -91,6 +91,7 @@ define(function(require, exports, module) { var KEYS = require("../lib/keys"); var event = require("../lib/event"); var Search = require("../search").Search; + var useragent = require("../lib/useragent"); var SearchHighlight = require("../search_highlight").SearchHighlight; var multiSelectCommands = require("../commands/multi_select_commands"); require("../multi_select"); @@ -5719,6 +5720,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ exports.CodeMirror = CodeMirror; var getVim = Vim.maybeInitVimState_; exports.handler = { + $id: "ace/keyboard/vim", drawCursor: function(style, pixelPos, config, sel, session) { var vim = this.state.vim || {}; var w = config.characterWidth; @@ -5742,25 +5744,42 @@ dom.importCssString(".normal-mode .ace_cursor{\ style.height = h + "px"; }, handleKeyboard: function(data, hashId, key, keyCode, e) { - var cm = data.editor.state.cm; - var vim = getVim(cm); - if (keyCode == -1) return; - if (hashId == -1 || hashId & 1 || hashId === 0 && key.length > 1) { - var insertMode = vim.insertMode; - var name = lookupKey(hashId, key, e || {}); - if (vim.status == null) - vim.status = ""; - var isHandled = multiSelectHandleKey(cm, name, 'user'); - vim = getVim(cm); // may be changed by multiSelectHandleKey - if (isHandled && vim.status != null) - vim.status += name; - else if (vim.status == null) - vim.status = ""; - cm._signal("changeStatus"); - if (!isHandled && (hashId != -1 || insertMode)) - return; - return {command: "null", passEvent: !isHandled}; + var editor = data.editor; + var cm = editor.state.cm; + var vim = getVim(cm); + if (keyCode == -1) return; + + if (key == "c" && hashId == 1) { // key == "ctrl-c" + if (!useragent.isMac && editor.getCopyText()) { + editor.once("copy", function() { + editor.selection.clearSelection(); + }); + return {command: "null", passEvent: true}; } + return {command: coreCommands.stop}; + } else if (!vim.insertMode) { + if (useragent.isMac && this.handleMacRepeat(data, hashId, key)) { + hashId = -1; + key = data.inputChar; + } + } + + if (hashId == -1 || hashId & 1 || hashId === 0 && key.length > 1) { + var insertMode = vim.insertMode; + var name = lookupKey(hashId, key, e || {}); + if (vim.status == null) + vim.status = ""; + var isHandled = multiSelectHandleKey(cm, name, 'user'); + vim = getVim(cm); // may be changed by multiSelectHandleKey + if (isHandled && vim.status != null) + vim.status += name; + else if (vim.status == null) + vim.status = ""; + cm._signal("changeStatus"); + if (!isHandled && (hashId != -1 || insertMode)) + return; + return {command: "null", passEvent: !isHandled}; + } }, attach: function(editor) { if (!editor.state) editor.state = {}; @@ -5786,7 +5805,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ }); cm.ace.renderer.setStyle("normal-mode", !getVim(cm).insertMode); editor.renderer.$cursorLayer.drawCursor = this.drawCursor.bind(cm); - renderVirtualNumbers.attach(editor); + // renderVirtualNumbers.attach(editor); + this.updateMacCompositionHandlers(editor, true); }, detach: function(editor) { var cm = editor.state.cm; @@ -5796,24 +5816,79 @@ dom.importCssString(".normal-mode .ace_cursor{\ editor.$vimModeHandler = null; editor.renderer.$cursorLayer.drawCursor = null; editor.renderer.setStyle("normal-mode", false); - renderVirtualNumbers.detach(editor); + // renderVirtualNumbers.detach(editor); + this.updateMacCompositionHandlers(editor, false); }, getStatusText: function(editor) { - var cm = editor.state.cm; - var vim = getVim(cm); - if (vim.insertMode) - return "INSERT"; - var status = ""; - if (vim.visualMode) { - status += "VISUAL"; - if (vim.visualLine) - status += " LINE"; - if (vim.visualBlock) - status += " BLOCK"; + var cm = editor.state.cm; + var vim = getVim(cm); + if (vim.insertMode) + return "INSERT"; + var status = ""; + if (vim.visualMode) { + status += "VISUAL"; + if (vim.visualLine) + status += " LINE"; + if (vim.visualBlock) + status += " BLOCK"; + } + if (vim.status) + status += (status ? " " : "") + vim.status; + return status; + }, + // workaround for j not repeating with `defaults write -g ApplePressAndHoldEnabled -bool true` + handleMacRepeat: function(data, hashId, key) { + if (hashId == -1) { + // record key + data.inputChar = key; + data.lastEvent = "input"; + } else if (data.inputChar && data.$lastHash == hashId && data.$lastKey == key) { + // check for repeated keypress + if (data.lastEvent == "input") { + data.lastEvent = "input1"; + } else if (data.lastEvent == "input1") { + // simulate textinput + return true; } - if (vim.status) - status += (status ? " " : "") + vim.status; - return status; + } else { + // reset + data.$lastHash = hashId; + data.$lastKey = key; + data.lastEvent = "keypress"; + } + }, + // on mac, with some keyboard layouts (e.g swedish) ^ starts composition, we don't need it in normal mode + updateMacCompositionHandlers: function(editor, enable) { + var onCompositionUpdateOverride = function(text) { + if (util.currentMode !== "insert") { + var el = this.textInput.getElement(); + el.blur(); + el.focus(); + el.value = text; + } else { + this.onCompositionUpdateOrig(text); + } + }; + var onCompositionStartOverride = function(text) { + if (util.currentMode === "insert") { + this.onCompositionStartOrig(text); + } + }; + if (enable) { + if (!editor.onCompositionUpdateOrig) { + editor.onCompositionUpdateOrig = editor.onCompositionUpdate; + editor.onCompositionUpdate = onCompositionUpdateOverride; + editor.onCompositionStartOrig = editor.onCompositionStart; + editor.onCompositionStart = onCompositionStartOverride; + } + } else { + if (editor.onCompositionUpdateOrig) { + editor.onCompositionUpdate = editor.onCompositionUpdateOrig; + editor.onCompositionUpdateOrig = null; + editor.onCompositionStart = editor.onCompositionStartOrig; + editor.onCompositionStartOrig = null; + } + } } } var renderVirtualNumbers = { @@ -5879,5 +5954,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ actions.fold = function(cm, actionArgs, vim) { cm.ace.execCommand(['toggleFoldWidget', 'toggleFoldWidget', 'foldOther', 'unfoldall' ][(actionArgs.all ? 2 : 0) + (actionArgs.open ? 1 : 0)]); - } + }, + + Vim.map("Y", "yy"); }); From a185414f6487ee37dcae953074f6b10ecb86cfba Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 11 Nov 2014 13:06:37 +0400 Subject: [PATCH 068/315] remove old vim mode --- demo/kitchen-sink/demo.js | 1 - lib/ace/keyboard/vim.js | 6121 +++++++++++++++++++++++- lib/ace/keyboard/vim/commands.js | 618 --- lib/ace/keyboard/vim/maps/aliases.js | 94 - lib/ace/keyboard/vim/maps/motions.js | 681 --- lib/ace/keyboard/vim/maps/operators.js | 201 - lib/ace/keyboard/vim/maps/util.js | 132 - lib/ace/keyboard/vim/registers.js | 42 - lib/ace/keyboard/vim2.js | 5960 ----------------------- lib/ace/keyboard/vim2_test.js | 3710 -------------- lib/ace/keyboard/vim_test.js | 4170 ++++++++++++++-- tool/update_deps.js | 2 +- 12 files changed, 9618 insertions(+), 12114 deletions(-) delete mode 100644 lib/ace/keyboard/vim/commands.js delete mode 100644 lib/ace/keyboard/vim/maps/aliases.js delete mode 100644 lib/ace/keyboard/vim/maps/motions.js delete mode 100644 lib/ace/keyboard/vim/maps/operators.js delete mode 100644 lib/ace/keyboard/vim/maps/util.js delete mode 100644 lib/ace/keyboard/vim/registers.js delete mode 100644 lib/ace/keyboard/vim2.js delete mode 100644 lib/ace/keyboard/vim2_test.js diff --git a/demo/kitchen-sink/demo.js b/demo/kitchen-sink/demo.js index efc2e6f8..c7beb3d0 100644 --- a/demo/kitchen-sink/demo.js +++ b/demo/kitchen-sink/demo.js @@ -254,7 +254,6 @@ commands.addCommand({ var keybindings = { ace: null, // Null = use "default" keymapping vim: require("ace/keyboard/vim").handler, - vim2: require("ace/keyboard/vim2").handler, emacs: "ace/keyboard/emacs", // This is a way to define simple keyboard remappings custom: new HashHandler({ diff --git a/lib/ace/keyboard/vim.js b/lib/ace/keyboard/vim.js index deea8d2f..0e860db1 100644 --- a/lib/ace/keyboard/vim.js +++ b/lib/ace/keyboard/vim.js @@ -1,199 +1,5960 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +/** + * Supported keybindings: * - * Copyright (c) 2010, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * Motion: + * h, j, k, l + * gj, gk + * e, E, w, W, b, B, ge, gE + * f, F, t, T + * $, ^, 0, -, +, _ + * gg, G + * % + * ', ` * - * ***** END LICENSE BLOCK ***** */ + * Operator: + * d, y, c + * dd, yy, cc + * g~, g~g~ + * >, <, >>, << + * + * Operator-Motion: + * x, X, D, Y, C, ~ + * + * Action: + * a, i, s, A, I, S, o, O + * zz, z., z, zt, zb, z- + * J + * u, Ctrl-r + * m + * r + * + * Modes: + * ESC - leave insert mode, visual mode, and clear input state. + * Ctrl-[, Ctrl-c - same as ESC. + * + * Registers: unnamed, -, a-z, A-Z, 0-9 + * (Does not respect the special case for number registers when delete + * operator is made with these commands: %, (, ), , /, ?, n, N, {, } ) + * TODO: Implement the remaining registers. + * Marks: a-z, A-Z, and 0-9 + * TODO: Implement the remaining special marks. They have more complex + * behavior. + * + * Events: + * 'vim-mode-change' - raised on the editor anytime the current mode changes, + * Event object: {mode: "visual", subMode: "linewise"} + * + * Code structure: + * 1. Default keymap + * 2. Variable declarations and short basic helpers + * 3. Instance (External API) implementation + * 4. Internal state tracking objects (input state, counter) implementation + * and instanstiation + * 5. Key handler (the main command dispatcher) implementation + * 6. Motion, operator, and action implementations + * 7. Helper functions for the key handler, motions, operators, and actions + * 8. Set up Vim to work as a keymap for CodeMirror. + */ define(function(require, exports, module) { -"use strict"; + 'use strict'; -var cmds = require("./vim/commands"); -var coreCommands = cmds.coreCommands; -var util = require("./vim/maps/util"); -var useragent = require("../lib/useragent"); - -var startCommands = { - "i": { - command: coreCommands.start - }, - "I": { - command: coreCommands.startBeginning - }, - "a": { - command: coreCommands.append - }, - "A": { - command: coreCommands.appendEnd - }, - "ctrl-f": { - command: "gotopagedown" - }, - "ctrl-b": { - command: "gotopageup" + /* function log() { + var d = ""; + function format(p) { + if (typeof p != "object") + return p + "" + if ("line" in p) { + return p.line + ":" + p.ch + } + if ("anchor" in p) { + return format(p.anchor) + "->" + format(p.head) + } + if (Array.isArray(p)) + return "[" + p.map(function(x) {return format(x)})+"]" + return JSON.stringify(p) } -}; + for (var i = 0; i < arguments.length; i++) { + var p = arguments[i] + var f = format(p) + d+= f+" " + } + console.log(d) + } */ + var Range = require("../range").Range; + var EventEmitter = require("../lib/event_emitter").EventEmitter; + var dom = require("../lib/dom"); + var oop = require("../lib/oop"); + var KEYS = require("../lib/keys"); + var event = require("../lib/event"); + var Search = require("../search").Search; + var useragent = require("../lib/useragent"); + var SearchHighlight = require("../search_highlight").SearchHighlight; + var multiSelectCommands = require("../commands/multi_select_commands"); + require("../multi_select"); -exports.handler = { - $id: "ace/keyboard/vim", + var CodeMirror = function(ace) { + this.ace = ace; + this.state = {}; + this.marks = {}; + this.$uid = 0; + this.onChange = this.onChange.bind(this); + this.onSelectionChange = this.onSelectionChange.bind(this); + this.onBeforeEndOperation = this.onBeforeEndOperation.bind(this); + this.ace.on('change', this.onChange); + this.ace.on('changeSelection', this.onSelectionChange); + this.ace.on('beforeEndOperation', this.onBeforeEndOperation); + }; + CodeMirror.Pos = function(line, ch) { + if (!(this instanceof Pos)) return new Pos(line, ch); + this.line = line; this.ch = ch; + }; + CodeMirror.defineOption = function(name, val, setter) {}; + CodeMirror.commands = { + redo: function(cm) { cm.ace.redo(); }, + undo: function(cm) { cm.ace.undo(); }, + newlineAndIndent: function(cm) { cm.ace.insert("\n"); }, + }; + CodeMirror.keyMap = {}; + CodeMirror.addClass = CodeMirror.rmClass = + CodeMirror.e_stop = function() {}; + CodeMirror.keyName = function(e) { + if (e.key) return e.key; + var key = (KEYS[e.keyCode] || ""); + if (key.length == 1) key = key.toUpperCase(); + key = event.getModifierString(e).replace(/(^|-)\w/g, function(m) { + return m.toUpperCase(); + }) + key; + return key; + }; + CodeMirror.keyMap['default'] = function(key) { + return function(cm) { + var cmd = cm.ace.commands.commandKeyBinding[key.toLowerCase()]; + return cmd && cm.ace.execCommand(cmd) !== false; + }; + }; + CodeMirror.lookupKey = function lookupKey(key, map, handle) { + if (typeof map == "string") + map = CodeMirror.keyMap[map]; + var found = typeof map == "function" ? map(key) : map[key]; + if (found === false) return "nothing"; + if (found === "...") return "multi"; + if (found != null && handle(found)) return "handled"; + + if (map.fallthrough) { + if (!Array.isArray(map.fallthrough)) + return lookupKey(key, map.fallthrough, handle); + for (var i = 0; i < map.fallthrough.length; i++) { + var result = lookupKey(key, map.fallthrough[i], handle); + if (result) return result; + } + } + }; + + CodeMirror.signal = function(o, name, e) { return o._signal(name, e) }; + CodeMirror.on = event.addListener; + CodeMirror.off = event.removeListener; +(function() { + oop.implement(CodeMirror.prototype, EventEmitter); + + this.destroy = function() { + this.ace.off('change', this.onChange); + this.ace.off('changeSelection', this.onSelectionChange); + this.ace.off('beforeEndOperation', this.onBeforeEndOperation); + this.removeOverlay(); + }; + this.virtualSelectionMode = function() { + return this.ace.inVirtualSelectionMode && this.ace.selection.index + }; + this.onChange = function(delta) { + var oldDelta = delta.data; + delta = { + start: oldDelta.range.start, + end: oldDelta.range.end, + action: oldDelta.action, + lines: oldDelta.lines || [oldDelta.text] + };// v1.2 api compatibility + if (delta.action[0] == 'i') { + var change = { text: delta.lines }; + var curOp = this.curOp = this.curOp || {}; + if (!curOp.changeHandlers) + curOp.changeHandlers = this._eventRegistry["change"] && this._eventRegistry["change"].slice(); + if (this.virtualSelectionMode()) return; + if (!curOp.lastChange) { + curOp.lastChange = curOp.change = change; + } else { + curOp.lastChange.next = curOp.lastChange = change; + } + } + this.$updateMarkers(delta); + }; + this.onSelectionChange = function() { + var curOp = this.curOp = this.curOp || {}; + if (!curOp.cursorActivityHandlers) + curOp.cursorActivityHandlers = this._eventRegistry["cursorActivity"] && this._eventRegistry["cursorActivity"].slice(); + this.curOp.cursorActivity = true; + if (this.ace.inMultiSelectMode) { + this.ace.keyBinding.removeKeyboardHandler(multiSelectCommands.keyboardHandler); + } + }; + this.operation = function(fn, force) { + if (!force && this.curOp || force && this.curOp && this.curOp.force) { + return fn(); + } + if (force || !this.ace.curOp) { + if (this.curOp) + this.onBeforeEndOperation(); + } + if (!this.ace.curOp) { + var prevOp = this.ace.prevOp; + this.ace.startOperation({ + command: { name: "vim", scrollIntoView: "cursor" } + }); + } + var curOp = this.curOp = this.curOp || {}; + this.curOp.force = force; + var result = fn(); + if (this.ace.curOp && this.ace.curOp.command.name == "vim") { + this.ace.endOperation(); + if (!curOp.cursorActivity && !curOp.lastChange && prevOp) + this.ace.prevOp = prevOp; + } + if (force || !this.ace.curOp) { + if (this.curOp) + this.onBeforeEndOperation(); + } + return result; + }; + this.onBeforeEndOperation = function() { + var op = this.curOp; + if (op) { + if (op.change) { this.signal("change", op.change, op); } + if (op && op.cursorActivity) { this.signal("cursorActivity", null, op); } + this.curOp = null; + } + }; + + this.signal = function(eventName, e, handlers) { + var listeners = handlers ? handlers[eventName + "Handlers"] + : (this._eventRegistry || {})[eventName]; + if (!listeners) + return; + listeners = listeners.slice(); + for (var i=0; i 0) { + point.row += rowShift; + point.column += point.row == end.row ? colShift : 0; + continue; + } + if (!isInsert && cmp2 <= 0) { + point.row = start.row; + point.column = start.column; + if (cmp2 === 0) + point.bias = 1 + } + } + }; + var Marker = function(cm, id, row, column) { + this.cm = cm; + this.id = id; + this.row = row; + this.column = column; + cm.marks[this.id] = this; + }; + Marker.prototype.clear = function() { delete this.cm.marks[this.id] }; + Marker.prototype.find = function() { return toCmPos(this) }; + this.setBookmark = function(cursor, options) { + var bm = new Marker(this, this.$uid++, cursor.line, cursor.ch); + if (!options || !options.insertLeft) + bm.$insertRight = true; + this.marks[bm.id] = bm; + return bm; + }; + this.moveH = function(increment, unit) { + if (unit == 'char') { + var sel = this.ace.selection; + sel.clearSelection(); + sel.moveCursorBy(0, increment); + } + }; + this.findPosV = function(start, amaount, unit, goalColumn) { + if (unit == 'line') { + var screenPos = this.ace.session.documentToScreenPosition(start.line, start.ch); + if (goalColumn != null) + screenPos.column = goalColumn; + screenPos.row += amaount; + // not what codemirror does but vim mode needs only it + screenPos.row = Math.min(Math.max(0, screenPos.row), this.ace.session.getScreenLength() - 1); + var pos = this.ace.session.screenToDocumentPosition(screenPos.row, screenPos.column); + return toCmPos(pos); + } else { + debugger; + } + }; + this.charCoords = function(pos, mode) { + if (mode == 'div' || !mode) { + var sc = this.ace.session.documentToScreenPosition(pos.line, pos.ch); + return {left: sc.column, top: sc.row}; + }if (mode == 'local') { + var renderer = this.ace.renderer; + var sc = this.ace.session.documentToScreenPosition(pos.line, pos.ch); + var lh = renderer.layerConfig.lineHeight; + var cw = renderer.layerConfig.characterWidth; + var top = lh * sc.row; + return {left: sc.column * cw, top: top, bottom: top + lh}; + } + }; + this.coordsChar = function(pos, mode) { + var renderer = this.ace.renderer; + if (mode == 'local') { + var row = Math.max(0, Math.floor(pos.top / renderer.lineHeight)); + var col = Math.max(0, Math.floor(pos.left / renderer.characterWidth)); + var ch = renderer.session.screenToDocumentPosition(row, col); + return toCmPos(ch); + } else if (mode == 'div') { + throw "not implemented"; + } + }; + this.openDialog = function() { + debugger + }; + this.getSearchCursor = function(query, pos, caseFold) { + var caseSensitive = false; + var isRegexp = false; + if (query instanceof RegExp && !query.global) { + caseSensitive = !query.ignoreCase; + query = query.source; + isRegexp = true; + } + var search = new Search(); + if (pos.ch == undefined) pos.ch = Number.MAX_VALUE; + var acePos = {row: pos.line, column: pos.ch}; + var cm = this; + var last = null; + return { + findNext: function() { return this.find(false) }, + findPrevious: function() {return this.find(true) }, + find: function(back) { + search.setOptions({ + needle: query, + caseSensitive: caseSensitive, + wrap: false, + backwards: back, + regExp: isRegexp, + start: last || acePos + }); + var range = search.find(cm.ace.session); + if (range && range.isEmpty()) { + if (cm.getLine(range.start.row).length == range.start.column) { + search.$options.start = range; + range = search.find(cm.ace.session); + } + } + last = range; + return last; + }, + from: function() { return last && toCmPos(last.start) }, + to: function() { return last && toCmPos(last.end) }, + replace: function(text) { + if (last) { + last.end = cm.ace.session.doc.replace(last, text); + } + } + }; + }; + this.scrollTo = function(x, y) { + var renderer = this.ace.renderer; + var config = renderer.layerConfig; + var maxHeight = config.maxHeight; + maxHeight -= (renderer.$size.scrollerHeight - renderer.lineHeight) * renderer.$scrollPastEnd; + if (y != null) this.ace.session.setScrollTop(Math.max(0, Math.min(y, maxHeight))); + if (x != null) this.ace.session.setScrollLeft(Math.max(0, Math.min(x, config.width))); + }; + this.scrollInfo = function() { return 0; }; + this.scrollIntoView = function(pos, margin) { + if (pos) + this.ace.renderer.scrollCursorIntoView(toAcePos(pos), null, margin); + }; + this.getLine = function(row) { return this.ace.session.getLine(row) }; + this.getRange = function(s, e) { + return this.ace.session.getTextRange(new Range(s.line, s.ch, e.line, e.ch)); + }; + this.replaceRange = function(text, s, e) { + if (!e) e = s; + return this.ace.session.replace(new Range(s.line, s.ch, e.line, e.ch), text); + }; + this.replaceSelections = function(p) { + var sel = this.ace.selection; + if (this.ace.inVirtualSelectionMode) { + this.ace.session.replace(sel.getRange(), p[0] || ""); + return; + } + sel.inVirtualSelectionMode = true; + var ranges = sel.rangeList.ranges; + if (!ranges.length) ranges = [this.ace.multiSelect.getRange()]; + for (var i = ranges.length; i--;) + this.ace.session.replace(ranges[i], p[i] || ""); + sel.inVirtualSelectionMode = false; + }; + this.getSelection = function() { + return this.ace.getSelectedText(); + }; + this.getSelections = function() { + return this.listSelections().map(function(x) { + return this.getRange(x.anchor, x.head); + }, this); + }; + this.getInputField = function() { + return this.ace.textInput.getElement(); + }; + this.getWrapperElement = function() { + return this.ace.containter; + }; + var optMap = { + indentWithTabs: "useSoftTabs", + indentUnit: "tabSize", + firstLineNumber: "firstLineNumber" + }; + this.setOption = function(name, val) { + this.state[name] = val; + switch (name) { + case 'indentWithTabs': + name = optMap[name]; + val = !val; + break; + default: + name = optMap[name]; + } + if (name) + this.ace.setOption(name, val); + }; + this.getOption = function(name, val) { + var aceOpt = optMap[name]; + if (aceOpt) + val = this.ace.getOption(aceOpt); + switch (name) { + case 'indentWithTabs': + name = optMap[name]; + return !val; + } + return aceOpt ? val : this.state[name]; + }; + this.toggleOverwrite = function(on) { + this.state.overwrite = on; + return this.ace.setOverwrite(on); + }; + this.addOverlay = function(o) { + if (!this.$searchHighlight || !this.$searchHighlight.session) { + var highlight = new SearchHighlight(null, "ace_highlight-marker", "text"); + var marker = this.ace.session.addDynamicMarker(highlight); + highlight.id = marker.id; + highlight.session = this.ace.session; + highlight.destroy = function(o) { + highlight.session.off("change", highlight.updateOnChange); + highlight.session.off("changeEditor", highlight.destroy); + highlight.session.removeMarker(highlight.id); + highlight.session = null; + }; + highlight.updateOnChange = function(delta) { + delta = delta.data.range;// v1.2 api compatibility + var row = delta.start.row; + if (row == delta.end.row) highlight.cache[row] = undefined; + else highlight.cache.splice(row, highlight.cache.length); + } + highlight.session.on("changeEditor", highlight.destroy); + highlight.session.on("change", highlight.updateOnChange); + } + var re = new RegExp(o.query.source, "gmi"); + console.log(re) + this.$searchHighlight = o.highlight = highlight; + this.$searchHighlight.setRegexp(re); + this.ace.renderer.updateBackMarkers(); + }; + this.removeOverlay = function(o) { + if (this.$searchHighlight && this.$searchHighlight.session) { + this.$searchHighlight.destroy(); + } + }; + this.getScrollInfo = function() { + var renderer = this.ace.renderer; + var config = renderer.layerConfig; + return { + left: renderer.scrollLeft, + top: renderer.scrollTop, + height: config.maxHeight, + width: config.width, + clientHeight: config.height, + clientWidth: config.width + }; + }; + this.getValue = function() { + return this.ace.getValue(); + }; + this.setValue = function(v) { + return this.ace.setValue(v); + }; + this.getTokenTypeAt = function(pos) { + var token = this.ace.session.getTokenAt(pos.line, pos.ch); + return token && /comment|string/.test(token.type) ? "string" : ""; + }; + this.findMatchingBracket = function(pos) { + var m = this.ace.session.findMatchingBracket(toAcePos(pos)); + return {to: m && toCmPos(m)}; + }; + this.indentLine = function(line, method) { + if (method === true) + this.ace.session.indentRows(line, line, "\t"); + else if (method === false) + this.ace.session.outdentRows(new Range(line, 0, line, 0)); + }; + this.indexFromPos = function(pos) { + return this.ace.session.doc.positionToIndex(toAcePos(pos)); + }; + this.posFromIndex = function(index) { + return toCmPos(this.ace.session.doc.indexToPosition(index)); + }; + this.focus = function(index) { + return this.ace.focus(); + }; + this.blur = function(index) { + return this.ace.blur(); + }; + this.defaultTextHeight = function(index) { + return this.ace.renderer.layerConfig.lineHeight; + }; + this.scanForBracket = function(pos, dir, _, options) { + var re = options.bracketRegex.source; + if (dir == 1) { + var m = this.ace.session.$findClosingBracket(re.slice(1, 2), toAcePos(pos), /paren|text/); + } else { + var m = this.ace.session.$findOpeningBracket(re.slice(-2, -1), {row: pos.line, column: pos.ch + 1}, /paren|text/); + } + return m && {pos: toCmPos(m)}; + }; + this.refresh = function() { + return this.ace.resize(true); + }; +}).call(CodeMirror.prototype); + function toAcePos(cmPos) { + return {row: cmPos.line, column: cmPos.ch}; + } + function toCmPos(acePos) { + return new Pos(acePos.row, acePos.column); + } + + var StringStream = CodeMirror.StringStream = function(string, tabSize) { + this.pos = this.start = 0; + this.string = string; + this.tabSize = tabSize || 8; + this.lastColumnPos = this.lastColumnValue = 0; + this.lineStart = 0; + }; + + StringStream.prototype = { + eol: function() {return this.pos >= this.string.length;}, + sol: function() {return this.pos == this.lineStart;}, + peek: function() {return this.string.charAt(this.pos) || undefined;}, + next: function() { + if (this.pos < this.string.length) + return this.string.charAt(this.pos++); + }, + eat: function(match) { + var ch = this.string.charAt(this.pos); + if (typeof match == "string") var ok = ch == match; + else var ok = ch && (match.test ? match.test(ch) : match(ch)); + if (ok) {++this.pos; return ch;} + }, + eatWhile: function(match) { + var start = this.pos; + while (this.eat(match)){} + return this.pos > start; + }, + eatSpace: function() { + var start = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; + return this.pos > start; + }, + skipToEnd: function() {this.pos = this.string.length;}, + skipTo: function(ch) { + var found = this.string.indexOf(ch, this.pos); + if (found > -1) {this.pos = found; return true;} + }, + backUp: function(n) {this.pos -= n;}, + column: function() { + throw "not implemented"; + }, + indentation: function() { + throw "not implemented"; + }, + match: function(pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; + var substr = this.string.substr(this.pos, pattern.length); + if (cased(substr) == cased(pattern)) { + if (consume !== false) this.pos += pattern.length; + return true; + } + } else { + var match = this.string.slice(this.pos).match(pattern); + if (match && match.index > 0) return null; + if (match && consume !== false) this.pos += match[0].length; + return match; + } + }, + current: function(){return this.string.slice(this.start, this.pos);}, + hideFirstChars: function(n, inner) { + this.lineStart += n; + try { return inner(); } + finally { this.lineStart -= n; } + } + }; + +// todo replace with showCommandLine +CodeMirror.defineExtension = function(name, fn) { + CodeMirror.prototype[name] = fn; +}; +dom.importCssString(".normal-mode .ace_cursor{\ + border: 0!important;\ + background-color: red;\ + opacity: 0.5;\ +}.ace_dialog {\ + position: absolute;\ + left: 0; right: 0;\ + background: white;\ + z-index: 15;\ + padding: .1em .8em;\ + overflow: hidden;\ + color: #333;\ +}\ +.ace_dialog-top {\ + border-bottom: 1px solid #eee;\ + top: 0;\ +}\ +.ace_dialog-bottom {\ + border-top: 1px solid #eee;\ + bottom: 0;\ +}\ +.ace_dialog input {\ + border: none;\ + outline: none;\ + background: transparent;\ + width: 20em;\ + color: inherit;\ + font-family: monospace;\ +}", "vimMode"); +(function() { + function dialogDiv(cm, template, bottom) { + var wrap = cm.ace.container; + var dialog; + dialog = wrap.appendChild(document.createElement("div")); + if (bottom) + dialog.className = "ace_dialog ace_dialog-bottom"; + else + dialog.className = "ace_dialog ace_dialog-top"; + + if (typeof template == "string") { + dialog.innerHTML = template; + } else { // Assuming it's a detached DOM element. + dialog.appendChild(template); + } + return dialog; + } + + function closeNotification(cm, newVal) { + if (cm.state.currentNotificationClose) + cm.state.currentNotificationClose(); + cm.state.currentNotificationClose = newVal; + } + + CodeMirror.defineExtension("openDialog", function(template, callback, options) { + if (this.virtualSelectionMode()) return; + if (!options) options = {}; + + closeNotification(this, null); + + var dialog = dialogDiv(this, template, options.bottom); + var closed = false, me = this; + function close(newVal) { + if (typeof newVal == 'string') { + inp.value = newVal; + } else { + if (closed) return; + closed = true; + dialog.parentNode.removeChild(dialog); + me.focus(); + + if (options.onClose) options.onClose(dialog); + } + } + + var inp = dialog.getElementsByTagName("input")[0], button; + if (inp) { + if (options.value) { + inp.value = options.value; + inp.select(); + } + + if (options.onInput) + CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); + if (options.onKeyUp) + CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); + + CodeMirror.on(inp, "keydown", function(e) { + if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } + if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { + inp.blur(); + CodeMirror.e_stop(e); + close(); + } + if (e.keyCode == 13) callback(inp.value); + }); + + if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close); + + inp.focus(); + } else if (button = dialog.getElementsByTagName("button")[0]) { + CodeMirror.on(button, "click", function() { + close(); + me.focus(); + }); + + if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); + + button.focus(); + } + return close; + }); + + CodeMirror.defineExtension("openNotification", function(template, options) { + if (this.virtualSelectionMode()) return; + closeNotification(this, close); + var dialog = dialogDiv(this, template, options && options.bottom); + var closed = false, doneTimer; + var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; + + function close() { + if (closed) return; + closed = true; + clearTimeout(doneTimer); + dialog.parentNode.removeChild(dialog); + } + + CodeMirror.on(dialog, 'click', function(e) { + CodeMirror.e_preventDefault(e); + close(); + }); + + if (duration) + doneTimer = setTimeout(close, duration); + + return close; + }); +})(); + + + var defaultKeymap = [ + // Key to key mapping. This goes first to make it possible to override + // existing mappings. + { keys: '', type: 'keyToKey', toKeys: 'h' }, + { keys: '', type: 'keyToKey', toKeys: 'l' }, + { keys: '', type: 'keyToKey', toKeys: 'k' }, + { keys: '', type: 'keyToKey', toKeys: 'j' }, + { keys: '', type: 'keyToKey', toKeys: 'l' }, + { keys: '', type: 'keyToKey', toKeys: 'h' }, + { keys: '', type: 'keyToKey', toKeys: 'W' }, + { keys: '', type: 'keyToKey', toKeys: 'B' }, + { keys: '', type: 'keyToKey', toKeys: 'w' }, + { keys: '', type: 'keyToKey', toKeys: 'b' }, + { keys: '', type: 'keyToKey', toKeys: 'j' }, + { keys: '', type: 'keyToKey', toKeys: 'k' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, + { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, + { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' }, + { keys: 's', type: 'keyToKey', toKeys: 'xi', context: 'visual'}, + { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' }, + { keys: 'S', type: 'keyToKey', toKeys: 'dcc', context: 'visual' }, + { keys: '', type: 'keyToKey', toKeys: '0' }, + { keys: '', type: 'keyToKey', toKeys: '$' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' }, + // Motions + { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }}, + { keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true }}, + { keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true }}, + { keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true }}, + { keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true }}, + { keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false }}, + { keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false }}, + { keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true }}, + { keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true }}, + { keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }}, + { keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }}, + { keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true }}, + { keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true }}, + { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }}, + { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }}, + { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }}, + { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }}, + { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }}, + { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }}, + { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }}, + { keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }}, + { keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }}, + { keys: '0', type: 'motion', motion: 'moveToStartOfLine' }, + { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true }}, + { keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar:true }}, + { keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }}, + { keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true }}, + { keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true }}, + { keys: 'f', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true , inclusive: true }}, + { keys: 'F', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false }}, + { keys: 't', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true }}, + { keys: 'T', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false }}, + { keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true }}, + { keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false }}, + { keys: '\'', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true, linewise: true}}, + { keys: '`', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true}}, + { keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } }, + { keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } }, + { keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } }, + { keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } }, + // the next two aren't motions but must come before more general motion declarations + { keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}}, + { keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}}, + { keys: ']', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true}}, + { keys: '[', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true}}, + { keys: '|', type: 'motion', motion: 'moveToColumn'}, + { keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context:'visual'}, + { keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'}, + // Operators + { keys: 'd', type: 'operator', operator: 'delete' }, + { keys: 'y', type: 'operator', operator: 'yank' }, + { keys: 'c', type: 'operator', operator: 'change' }, + { keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true }}, + { keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false }}, + { keys: 'g~', type: 'operator', operator: 'changeCase' }, + { keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, isEdit: true }, + { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true }, + { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }}, + { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }}, + // Operator-Motion dual commands + { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }}, + { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }}, + { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, operatorMotionArgs: { visualLine: true }}, + { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, operatorMotionArgs: { visualLine: true }}, + { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, operatorMotionArgs: { visualLine: true }}, + { keys: '~', type: 'operatorMotion', operator: 'changeCase', operatorArgs: { shouldMoveCursor: true }, motion: 'moveByCharacters', motionArgs: { forward: true }}, + { keys: '', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' }, + // Actions + { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }}, + { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }}, + { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }}, + { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }}, + { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' }, + { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, + { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, + { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' }, + { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank' }}, + { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' }, + { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, + { keys: 'v', type: 'action', action: 'toggleVisualMode' }, + { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }}, + { keys: '', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, + { keys: 'gv', type: 'action', action: 'reselectLastSelection' }, + { keys: 'J', type: 'action', action: 'joinLines', isEdit: true }, + { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }}, + { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }}, + { keys: 'r', type: 'action', action: 'replace', isEdit: true }, + { keys: '@', type: 'action', action: 'replayMacro' }, + { keys: 'q', type: 'action', action: 'enterMacroRecordMode' }, + // Handle Replace-mode as a special case of insert mode. + { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }}, + { keys: 'u', type: 'action', action: 'undo', context: 'normal' }, + { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true }, + { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true }, + { keys: '', type: 'action', action: 'redo' }, + { keys: 'm', type: 'action', action: 'setMark' }, + { keys: '"', type: 'action', action: 'setRegister' }, + { keys: 'zz', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }}, + { keys: 'z.', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: 'zt', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }}, + { keys: 'z', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: 'z-', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }}, + { keys: 'zb', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: '.', type: 'action', action: 'repeatLastEdit' }, + { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}}, + { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}}, + // Text object motions + { keys: 'a', type: 'motion', motion: 'textObjectManipulation' }, + { keys: 'i', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }}, + // Search + { keys: '/', type: 'search', searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }}, + { keys: '?', type: 'search', searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }}, + { keys: '*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, + { keys: '#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, + { keys: 'g*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }}, + { keys: 'g#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }}, + // Ex command + { keys: ':', type: 'ex' } + ]; + + var Pos = CodeMirror.Pos; + + var modifierCodes = [16, 17, 18, 91]; + var specialKey = {Enter:'CR',Backspace:'BS',Delete:'Del'}; + var mac = /Mac/.test(navigator.platform); + var Vim = function() { return vimApi; } //{ + function lookupKey(e) { + var keyCode = e.keyCode; + if (modifierCodes.indexOf(keyCode) != -1) { return; } + var hasModifier = e.ctrlKey || e.metaKey; + var key = CodeMirror.keyNames[keyCode]; + key = specialKey[key] || key; + var name = ''; + if (e.ctrlKey) { name += 'C-'; } + if (e.altKey) { name += 'A-'; } + if (mac && e.metaKey || (!hasModifier && e.shiftKey) && key.length < 2) { + // Shift key bindings can only specified for special characters. + return; + } else if (e.shiftKey && !/^[A-Za-z]$/.test(key)) { + name += 'S-'; + } + if (key.length == 1) { key = key.toLowerCase(); } + name += key; + if (name.length > 1) { name = '<' + name + '>'; } + return name; + } + // Keys with modifiers are handled using keydown due to limitations of + // keypress event. + function handleKeyDown(cm, e) { + var name = lookupKey(e); + if (!name) { return; } + + CodeMirror.signal(cm, 'vim-keypress', name); + if (CodeMirror.Vim.handleKey(cm, name, 'user')) { + CodeMirror.e_stop(e); + } + } + // Keys without modifiers are handled using keypress to work best with + // non-standard keyboard layouts. + function handleKeyPress(cm, e) { + var code = e.charCode || e.keyCode; + if (e.ctrlKey || e.metaKey || e.altKey || + e.shiftKey && code < 32) { return; } + var name = String.fromCharCode(code); + + CodeMirror.signal(cm, 'vim-keypress', name); + if (CodeMirror.Vim.handleKey(cm, name, 'user')) { + CodeMirror.e_stop(e); + } + } + + function enterVimMode(cm) { + cm.setOption('disableInput', true); + cm.setOption('showCursorWhenSelecting', false); + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + cm.on('cursorActivity', onCursorActivity); + maybeInitVimState(cm); + CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); + cm.on('keypress', handleKeyPress); + cm.on('keydown', handleKeyDown); + CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); + } + + function leaveVimMode(cm) { + cm.setOption('disableInput', false); + cm.off('cursorActivity', onCursorActivity); + CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); + cm.state.vim = null; + cm.off('keypress', handleKeyPress); + cm.off('keydown', handleKeyDown); + } + + function detachVimMap(cm, next) { + if (this == CodeMirror.keyMap.vim) + CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor"); + + if (!next || next.attach != attachVimMap) + leaveVimMode(cm, false); + } + function attachVimMap(cm, prev) { + if (this == CodeMirror.keyMap.vim) + CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); + + if (!prev || prev.attach != attachVimMap) + enterVimMode(cm); + } + + // Deprecated, simply setting the keymap works again. + CodeMirror.defineOption('vimMode', false, function(cm, val, prev) { + if (val && cm.getOption("keyMap") != "vim") + cm.setOption("keyMap", "vim"); + else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap"))) + cm.setOption("keyMap", "default"); + }); + function getOnPasteFn(cm) { + var vim = cm.state.vim; + if (!vim.onPasteFn) { + vim.onPasteFn = function() { + if (!vim.insertMode) { + cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); + actions.enterInsertMode(cm, {}, vim); + } + }; + } + return vim.onPasteFn; + } + + var numberRegex = /[\d]/; + var wordRegexp = [(/\w/), (/[^\w\s]/)], bigWordRegexp = [(/\S/)]; + function makeKeyRange(start, size) { + var keys = []; + for (var i = start; i < start + size; i++) { + keys.push(String.fromCharCode(i)); + } + return keys; + } + var upperCaseAlphabet = makeKeyRange(65, 26); + var lowerCaseAlphabet = makeKeyRange(97, 26); + var numbers = makeKeyRange(48, 10); + var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']); + var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']); + + function isLine(cm, line) { + return line >= cm.firstLine() && line <= cm.lastLine(); + } + function isLowerCase(k) { + return (/^[a-z]$/).test(k); + } + function isMatchableSymbol(k) { + return '()[]{}'.indexOf(k) != -1; + } + function isNumber(k) { + return numberRegex.test(k); + } + function isUpperCase(k) { + return (/^[A-Z]$/).test(k); + } + function isWhiteSpaceString(k) { + return (/^\s*$/).test(k); + } + function inArray(val, arr) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] == val) { + return true; + } + } + return false; + } + + var options = {}; + function defineOption(name, defaultValue, type) { + if (defaultValue === undefined) { throw Error('defaultValue is required'); } + if (!type) { type = 'string'; } + var opt = name; + if (typeof name == "string") + opt = { + type: type, + defaultValue: defaultValue + }; + else + name = opt.name; + options[name] = opt; + setOption(name, defaultValue); + } + + function setOption(name, value, cm) { + var option = options[name]; + if (!option) { + throw Error('Unknown option: ' + name); + } + if (option.type == 'boolean') { + if (value && value !== true) { + throw Error('Invalid argument: ' + name + '=' + value); + } else if (value !== false) { + // Boolean options are set to true if value is not defined. + value = true; + } + } + option.value = value; + if (option.set) option.set(value, cm); + } + + function getOption(name) { + var option = options[name]; + if (!option) { + throw Error('Unknown option: ' + name); + } + return option.value; + } + + var createCircularJumpList = function() { + var size = 100; + var pointer = -1; + var head = 0; + var tail = 0; + var buffer = new Array(size); + function add(cm, oldCur, newCur) { + var current = pointer % size; + var curMark = buffer[current]; + function useNextSlot(cursor) { + var next = ++pointer % size; + var trashMark = buffer[next]; + if (trashMark) { + trashMark.clear(); + } + buffer[next] = cm.setBookmark(cursor); + } + if (curMark) { + var markPos = curMark.find(); + // avoid recording redundant cursor position + if (markPos && !cursorEqual(markPos, oldCur)) { + useNextSlot(oldCur); + } + } else { + useNextSlot(oldCur); + } + useNextSlot(newCur); + head = pointer; + tail = pointer - size + 1; + if (tail < 0) { + tail = 0; + } + } + function move(cm, offset) { + pointer += offset; + if (pointer > head) { + pointer = head; + } else if (pointer < tail) { + pointer = tail; + } + var mark = buffer[(size + pointer) % size]; + // skip marks that are temporarily removed from text buffer + if (mark && !mark.find()) { + var inc = offset > 0 ? 1 : -1; + var newCur; + var oldCur = cm.getCursor(); + do { + pointer += inc; + mark = buffer[(size + pointer) % size]; + // skip marks that are the same as current position + if (mark && + (newCur = mark.find()) && + !cursorEqual(oldCur, newCur)) { + break; + } + } while (pointer < head && pointer > tail); + } + return mark; + } + return { + cachedCursor: undefined, //used for # and * jumps + add: add, + move: move + }; + }; + + // Returns an object to track the changes associated insert mode. It + // clones the object that is passed in, or creates an empty object one if + // none is provided. + var createInsertModeChanges = function(c) { + if (c) { + // Copy construction + return { + changes: c.changes, + expectCursorActivityForChange: c.expectCursorActivityForChange + }; + } + return { + // Change list + changes: [], + // Set to true on change, false on cursorActivity. + expectCursorActivityForChange: false + }; + }; + + function MacroModeState() { + this.latestRegister = undefined; + this.isPlaying = false; + this.isRecording = false; + this.replaySearchQueries = []; + this.onRecordingDone = undefined; + this.lastInsertModeChanges = createInsertModeChanges(); + } + MacroModeState.prototype = { + exitMacroRecordMode: function() { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.onRecordingDone) { + macroModeState.onRecordingDone(); // close dialog + } + macroModeState.onRecordingDone = undefined; + macroModeState.isRecording = false; + }, + enterMacroRecordMode: function(cm, registerName) { + var register = + vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.clear(); + this.latestRegister = registerName; + if (cm.openDialog) { + this.onRecordingDone = cm.openDialog( + '(recording)['+registerName+']', null, {bottom:true}); + } + this.isRecording = true; + } + } + }; + + function maybeInitVimState(cm) { + if (!cm.state.vim) { + // Store instance state in the CodeMirror object. + cm.state.vim = { + inputState: new InputState(), + // Vim's input state that triggered the last edit, used to repeat + // motions and operators with '.'. + lastEditInputState: undefined, + // Vim's action command before the last edit, used to repeat actions + // with '.' and insert mode repeat. + lastEditActionCommand: undefined, + // When using jk for navigation, if you move from a longer line to a + // shorter line, the cursor may clip to the end of the shorter line. + // If j is pressed again and cursor goes to the next line, the + // cursor should go back to its horizontal position on the longer + // line if it can. This is to keep track of the horizontal position. + lastHPos: -1, + // Doing the same with screen-position for gj/gk + lastHSPos: -1, + // The last motion command run. Cleared if a non-motion command gets + // executed in between. + lastMotion: null, + marks: {}, + // Mark for rendering fake cursor for visual mode. + fakeCursor: null, + insertMode: false, + // Repeat count for changes made in insert mode, triggered by key + // sequences like 3,i. Only exists when insertMode is true. + insertModeRepeat: undefined, + visualMode: false, + // If we are in visual line mode. No effect if visualMode is false. + visualLine: false, + visualBlock: false, + lastSelection: null, + lastPastedText: null + }; + } + return cm.state.vim; + } + var vimGlobalState; + function resetVimGlobalState() { + vimGlobalState = { + // The current search query. + searchQuery: null, + // Whether we are searching backwards. + searchIsReversed: false, + // Replace part of the last substituted pattern + lastSubstituteReplacePart: undefined, + jumpList: createCircularJumpList(), + macroModeState: new MacroModeState, + // Recording latest f, t, F or T motion command. + lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''}, + registerController: new RegisterController({}), + // search history buffer + searchHistoryController: new HistoryController({}), + // ex Command history buffer + exCommandHistoryController : new HistoryController({}) + }; + for (var optionName in options) { + var option = options[optionName]; + option.value = option.defaultValue; + } + } + + var lastInsertModeKeyTimer; + var vimApi= { + buildKeyMap: function() { + // TODO: Convert keymap into dictionary format for fast lookup. + }, + // Testing hook, though it might be useful to expose the register + // controller anyways. + getRegisterController: function() { + return vimGlobalState.registerController; + }, + // Testing hook. + resetVimGlobalState_: resetVimGlobalState, + + // Testing hook. + getVimGlobalState_: function() { + return vimGlobalState; + }, + + // Testing hook. + maybeInitVimState_: maybeInitVimState, + + InsertModeKey: InsertModeKey, + map: function(lhs, rhs, ctx) { + // Add user defined key bindings. + exCommandDispatcher.map(lhs, rhs, ctx); + }, + setOption: setOption, + getOption: getOption, + defineOption: defineOption, + defineEx: function(name, prefix, func){ + if (name.indexOf(prefix) !== 0) { + throw new Error('(Vim.defineEx) "'+prefix+'" is not a prefix of "'+name+'", command not registered'); + } + exCommands[name]=func; + exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'}; + }, + // This is the outermost function called by CodeMirror, after keys have + // been mapped to their Vim equivalents. + handleKey: function(cm, key, origin) { + var vim = maybeInitVimState(cm); + function handleMacroRecording() { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isRecording) { + if (key == 'q') { + macroModeState.exitMacroRecordMode(); + clearInputState(cm); + return true; + } + if (origin != 'mapping') { + logKey(macroModeState, key); + } + } + } + function handleEsc() { + if (key == '') { + // Clear input state and get back to normal mode. + clearInputState(cm); + if (vim.visualMode) { + exitVisualMode(cm); + } else if (vim.insertMode) { + exitInsertMode(cm); + } + return true; + } + } + function doKeyToKey(keys) { + // TODO: prevent infinite recursion. + var match; + while (keys) { + // Pull off one command key, which is either a single character + // or a special sequence wrapped in '<' and '>', e.g. ''. + match = (/<\w+-.+?>|<\w+>|./).exec(keys); + key = match[0]; + keys = keys.substring(match.index + key.length); + CodeMirror.Vim.handleKey(cm, key, 'mapping'); + } + } + + function handleKeyInsertMode() { + if (handleEsc()) { return true; } + var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; + var keysAreChars = key.length == 1; + var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); + // Need to check all key substrings in insert mode. + while (keys.length > 1 && match.type != 'full') { + var keys = vim.inputState.keyBuffer = keys.slice(1); + var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); + if (thisMatch.type != 'none') { match = thisMatch; } + } + if (match.type == 'none') { clearInputState(cm); return false; } + else if (match.type == 'partial') { + if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } + lastInsertModeKeyTimer = window.setTimeout( + function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } }, + getOption('insertModeEscKeysTimeout')); + return !keysAreChars; + } + + if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } + if (keysAreChars) { + var here = cm.getCursor(); + cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input'); + } + clearInputState(cm); + var command = match.command; + if (command.type == 'keyToKey') { + doKeyToKey(command.toKeys); + } else { + commandDispatcher.processCommand(cm, vim, command); + } + return true; + } + + function handleKeyNonInsertMode() { + if (handleMacroRecording() || handleEsc()) { return true; }; + + var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; + if (/^[1-9]\d*$/.test(keys)) { return true; } + + var keysMatcher = /^(\d*)(.*)$/.exec(keys); + if (!keysMatcher) { clearInputState(cm); return false; } + var context = vim.visualMode ? 'visual' : + 'normal'; + var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context); + if (match.type == 'none') { clearInputState(cm); return false; } + else if (match.type == 'partial') { return true; } + + vim.inputState.keyBuffer = ''; + var command = match.command; + var keysMatcher = /^(\d*)(.*)$/.exec(keys); + if (keysMatcher[1] && keysMatcher[1] != '0') { + vim.inputState.pushRepeatDigit(keysMatcher[1]); + } + if (command.type == 'keyToKey') { + doKeyToKey(command.toKeys); + } else { + commandDispatcher.processCommand(cm, vim, command); + } + return true; + } + + return cm.operation(function() { + cm.curOp.isVimOp = true; + try { + if (vim.insertMode) { return handleKeyInsertMode(); } + else { return handleKeyNonInsertMode(); } + } catch (e) { + // clear VIM state in case it's in a bad state. + cm.state.vim = undefined; + throw e; + } + }); + }, + handleEx: function(cm, input) { + exCommandDispatcher.processCommand(cm, input); + } + }; + + // Represents the current input state. + function InputState() { + this.prefixRepeat = []; + this.motionRepeat = []; + + this.operator = null; + this.operatorArgs = null; + this.motion = null; + this.motionArgs = null; + this.keyBuffer = []; // For matching multi-key commands. + this.registerName = null; // Defaults to the unnamed register. + } + InputState.prototype.pushRepeatDigit = function(n) { + if (!this.operator) { + this.prefixRepeat = this.prefixRepeat.concat(n); + } else { + this.motionRepeat = this.motionRepeat.concat(n); + } + }; + InputState.prototype.getRepeat = function() { + var repeat = 0; + if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) { + repeat = 1; + if (this.prefixRepeat.length > 0) { + repeat *= parseInt(this.prefixRepeat.join(''), 10); + } + if (this.motionRepeat.length > 0) { + repeat *= parseInt(this.motionRepeat.join(''), 10); + } + } + return repeat; + }; + + function clearInputState(cm, reason) { + cm.state.vim.inputState = new InputState(); + CodeMirror.signal(cm, 'vim-command-done', reason); + } + + /* + * Register stores information about copy and paste registers. Besides + * text, a register must store whether it is linewise (i.e., when it is + * pasted, should it insert itself into a new line, or should the text be + * inserted at the cursor position.) + */ + function Register(text, linewise, blockwise) { + this.clear(); + this.keyBuffer = [text || '']; + this.insertModeChanges = []; + this.searchQueries = []; + this.linewise = !!linewise; + this.blockwise = !!blockwise; + } + Register.prototype = { + setText: function(text, linewise, blockwise) { + this.keyBuffer = [text || '']; + this.linewise = !!linewise; + this.blockwise = !!blockwise; + }, + pushText: function(text, linewise) { + // if this register has ever been set to linewise, use linewise. + if (linewise) { + if (!this.linewise) { + this.keyBuffer.push('\n'); + } + this.linewise = true; + } + this.keyBuffer.push(text); + }, + pushInsertModeChanges: function(changes) { + this.insertModeChanges.push(createInsertModeChanges(changes)); + }, + pushSearchQuery: function(query) { + this.searchQueries.push(query); + }, + clear: function() { + this.keyBuffer = []; + this.insertModeChanges = []; + this.searchQueries = []; + this.linewise = false; + }, + toString: function() { + return this.keyBuffer.join(''); + } + }; + + /* + * vim registers allow you to keep many independent copy and paste buffers. + * See http://usevim.com/2012/04/13/registers/ for an introduction. + * + * RegisterController keeps the state of all the registers. An initial + * state may be passed in. The unnamed register '"' will always be + * overridden. + */ + function RegisterController(registers) { + this.registers = registers; + this.unnamedRegister = registers['"'] = new Register(); + registers['.'] = new Register(); + registers[':'] = new Register(); + registers['/'] = new Register(); + } + RegisterController.prototype = { + pushText: function(registerName, operator, text, linewise, blockwise) { + if (linewise && text.charAt(0) == '\n') { + text = text.slice(1) + '\n'; + } + if (linewise && text.charAt(text.length - 1) !== '\n'){ + text += '\n'; + } + // Lowercase and uppercase registers refer to the same register. + // Uppercase just means append. + var register = this.isValidRegister(registerName) ? + this.getRegister(registerName) : null; + // if no register/an invalid register was specified, things go to the + // default registers + if (!register) { + switch (operator) { + case 'yank': + // The 0 register contains the text from the most recent yank. + this.registers['0'] = new Register(text, linewise, blockwise); + break; + case 'delete': + case 'change': + if (text.indexOf('\n') == -1) { + // Delete less than 1 line. Update the small delete register. + this.registers['-'] = new Register(text, linewise); + } else { + // Shift down the contents of the numbered registers and put the + // deleted text into register 1. + this.shiftNumericRegisters_(); + this.registers['1'] = new Register(text, linewise); + } + break; + } + // Make sure the unnamed register is set to what just happened + this.unnamedRegister.setText(text, linewise, blockwise); + return; + } + + // If we've gotten to this point, we've actually specified a register + var append = isUpperCase(registerName); + if (append) { + register.pushText(text, linewise); + } else { + register.setText(text, linewise, blockwise); + } + // The unnamed register always has the same value as the last used + // register. + this.unnamedRegister.setText(register.toString(), linewise); + }, + // Gets the register named @name. If one of @name doesn't already exist, + // create it. If @name is invalid, return the unnamedRegister. + getRegister: function(name) { + if (!this.isValidRegister(name)) { + return this.unnamedRegister; + } + name = name.toLowerCase(); + if (!this.registers[name]) { + this.registers[name] = new Register(); + } + return this.registers[name]; + }, + isValidRegister: function(name) { + return name && inArray(name, validRegisters); + }, + shiftNumericRegisters_: function() { + for (var i = 9; i >= 2; i--) { + this.registers[i] = this.getRegister('' + (i - 1)); + } + } + }; + function HistoryController() { + this.historyBuffer = []; + this.iterator; + this.initialPrefix = null; + } + HistoryController.prototype = { + // the input argument here acts a user entered prefix for a small time + // until we start autocompletion in which case it is the autocompleted. + nextMatch: function (input, up) { + var historyBuffer = this.historyBuffer; + var dir = up ? -1 : 1; + if (this.initialPrefix === null) this.initialPrefix = input; + for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i+= dir) { + var element = historyBuffer[i]; + for (var j = 0; j <= element.length; j++) { + if (this.initialPrefix == element.substring(0, j)) { + this.iterator = i; + return element; + } + } + } + // should return the user input in case we reach the end of buffer. + if (i >= historyBuffer.length) { + this.iterator = historyBuffer.length; + return this.initialPrefix; + } + // return the last autocompleted query or exCommand as it is. + if (i < 0 ) return input; + }, + pushInput: function(input) { + var index = this.historyBuffer.indexOf(input); + if (index > -1) this.historyBuffer.splice(index, 1); + if (input.length) this.historyBuffer.push(input); + }, + reset: function() { + this.initialPrefix = null; + this.iterator = this.historyBuffer.length; + } + }; + var commandDispatcher = { + matchCommand: function(keys, keyMap, inputState, context) { + var matches = commandMatches(keys, keyMap, context, inputState); + if (!matches.full && !matches.partial) { + return {type: 'none'}; + } else if (!matches.full && matches.partial) { + return {type: 'partial'}; + } + + var bestMatch; + for (var i = 0; i < matches.full.length; i++) { + var match = matches.full[i]; + if (!bestMatch) { + bestMatch = match; + } + } + if (bestMatch.keys.slice(-11) == '') { + inputState.selectedCharacter = lastChar(keys); + } + return {type: 'full', command: bestMatch}; + }, + processCommand: function(cm, vim, command) { + vim.inputState.repeatOverride = command.repeatOverride; + switch (command.type) { + case 'motion': + this.processMotion(cm, vim, command); + break; + case 'operator': + this.processOperator(cm, vim, command); + break; + case 'operatorMotion': + this.processOperatorMotion(cm, vim, command); + break; + case 'action': + this.processAction(cm, vim, command); + break; + case 'search': + this.processSearch(cm, vim, command); + clearInputState(cm); + break; + case 'ex': + case 'keyToEx': + this.processEx(cm, vim, command); + clearInputState(cm); + break; + default: + break; + } + }, + processMotion: function(cm, vim, command) { + vim.inputState.motion = command.motion; + vim.inputState.motionArgs = copyArgs(command.motionArgs); + this.evalInput(cm, vim); + }, + processOperator: function(cm, vim, command) { + var inputState = vim.inputState; + if (inputState.operator) { + if (inputState.operator == command.operator) { + // Typing an operator twice like 'dd' makes the operator operate + // linewise + inputState.motion = 'expandToLine'; + inputState.motionArgs = { linewise: true }; + this.evalInput(cm, vim); + return; + } else { + // 2 different operators in a row doesn't make sense. + clearInputState(cm); + } + } + inputState.operator = command.operator; + inputState.operatorArgs = copyArgs(command.operatorArgs); + if (vim.visualMode) { + // Operating on a selection in visual mode. We don't need a motion. + this.evalInput(cm, vim); + } + }, + processOperatorMotion: function(cm, vim, command) { + var visualMode = vim.visualMode; + var operatorMotionArgs = copyArgs(command.operatorMotionArgs); + if (operatorMotionArgs) { + // Operator motions may have special behavior in visual mode. + if (visualMode && operatorMotionArgs.visualLine) { + vim.visualLine = true; + } + } + this.processOperator(cm, vim, command); + if (!visualMode) { + this.processMotion(cm, vim, command); + } + }, + processAction: function(cm, vim, command) { + var inputState = vim.inputState; + var repeat = inputState.getRepeat(); + var repeatIsExplicit = !!repeat; + var actionArgs = copyArgs(command.actionArgs) || {}; + if (inputState.selectedCharacter) { + actionArgs.selectedCharacter = inputState.selectedCharacter; + } + // Actions may or may not have motions and operators. Do these first. + if (command.operator) { + this.processOperator(cm, vim, command); + } + if (command.motion) { + this.processMotion(cm, vim, command); + } + if (command.motion || command.operator) { + this.evalInput(cm, vim); + } + actionArgs.repeat = repeat || 1; + actionArgs.repeatIsExplicit = repeatIsExplicit; + actionArgs.registerName = inputState.registerName; + clearInputState(cm); + vim.lastMotion = null; + if (command.isEdit) { + this.recordLastEdit(vim, inputState, command); + } + actions[command.action](cm, actionArgs, vim); + }, + processSearch: function(cm, vim, command) { + if (!cm.getSearchCursor) { + // Search depends on SearchCursor. + return; + } + var forward = command.searchArgs.forward; + var wholeWordOnly = command.searchArgs.wholeWordOnly; + getSearchState(cm).setReversed(!forward); + var promptPrefix = (forward) ? '/' : '?'; + var originalQuery = getSearchState(cm).getQuery(); + var originalScrollPos = cm.getScrollInfo(); + function handleQuery(query, ignoreCase, smartCase) { + vimGlobalState.searchHistoryController.pushInput(query); + vimGlobalState.searchHistoryController.reset(); + try { + updateSearchQuery(cm, query, ignoreCase, smartCase); + } catch (e) { + showConfirm(cm, 'Invalid regex: ' + query); + return; + } + commandDispatcher.processMotion(cm, vim, { + type: 'motion', + motion: 'findNext', + motionArgs: { forward: true, toJumplist: command.searchArgs.toJumplist } + }); + } + function onPromptClose(query) { + cm.scrollTo(originalScrollPos.left, originalScrollPos.top); + handleQuery(query, true /** ignoreCase */, true /** smartCase */); + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isRecording) { + logSearchQuery(macroModeState, query); + } + } + function onPromptKeyUp(e, query, close) { + var keyName = CodeMirror.keyName(e), up; + if (keyName == 'Up' || keyName == 'Down') { + up = keyName == 'Up' ? true : false; + query = vimGlobalState.searchHistoryController.nextMatch(query, up) || ''; + close(query); + } else { + if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') + vimGlobalState.searchHistoryController.reset(); + } + var parsedQuery; + try { + parsedQuery = updateSearchQuery(cm, query, + true /** ignoreCase */, true /** smartCase */); + } catch (e) { + // Swallow bad regexes for incremental search. + } + if (parsedQuery) { + cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30); + } else { + clearSearchHighlight(cm); + cm.scrollTo(originalScrollPos.left, originalScrollPos.top); + } + } + function onPromptKeyDown(e, query, close) { + var keyName = CodeMirror.keyName(e); + if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') { + vimGlobalState.searchHistoryController.pushInput(query); + vimGlobalState.searchHistoryController.reset(); + updateSearchQuery(cm, originalQuery); + clearSearchHighlight(cm); + cm.scrollTo(originalScrollPos.left, originalScrollPos.top); + CodeMirror.e_stop(e); + close(); + cm.focus(); + } + } + switch (command.searchArgs.querySrc) { + case 'prompt': + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isPlaying) { + var query = macroModeState.replaySearchQueries.shift(); + handleQuery(query, true /** ignoreCase */, false /** smartCase */); + } else { + showPrompt(cm, { + onClose: onPromptClose, + prefix: promptPrefix, + desc: searchPromptDesc, + onKeyUp: onPromptKeyUp, + onKeyDown: onPromptKeyDown + }); + } + break; + case 'wordUnderCursor': + var word = expandWordUnderCursor(cm, false /** inclusive */, + true /** forward */, false /** bigWord */, + true /** noSymbol */); + var isKeyword = true; + if (!word) { + word = expandWordUnderCursor(cm, false /** inclusive */, + true /** forward */, false /** bigWord */, + false /** noSymbol */); + isKeyword = false; + } + if (!word) { + return; + } + var query = cm.getLine(word.start.line).substring(word.start.ch, + word.end.ch); + if (isKeyword && wholeWordOnly) { + query = '\\b' + query + '\\b'; + } else { + query = escapeRegex(query); + } + + // cachedCursor is used to save the old position of the cursor + // when * or # causes vim to seek for the nearest word and shift + // the cursor before entering the motion. + vimGlobalState.jumpList.cachedCursor = cm.getCursor(); + cm.setCursor(word.start); + + handleQuery(query, true /** ignoreCase */, false /** smartCase */); + break; + } + }, + processEx: function(cm, vim, command) { + function onPromptClose(input) { + // Give the prompt some time to close so that if processCommand shows + // an error, the elements don't overlap. + vimGlobalState.exCommandHistoryController.pushInput(input); + vimGlobalState.exCommandHistoryController.reset(); + exCommandDispatcher.processCommand(cm, input); + } + function onPromptKeyDown(e, input, close) { + var keyName = CodeMirror.keyName(e), up; + if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') { + vimGlobalState.exCommandHistoryController.pushInput(input); + vimGlobalState.exCommandHistoryController.reset(); + CodeMirror.e_stop(e); + close(); + cm.focus(); + } + if (keyName == 'Up' || keyName == 'Down') { + up = keyName == 'Up' ? true : false; + input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || ''; + close(input); + } else { + if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') + vimGlobalState.exCommandHistoryController.reset(); + } + } + if (command.type == 'keyToEx') { + // Handle user defined Ex to Ex mappings + exCommandDispatcher.processCommand(cm, command.exArgs.input); + } else { + if (vim.visualMode) { + showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>', + onKeyDown: onPromptKeyDown}); + } else { + showPrompt(cm, { onClose: onPromptClose, prefix: ':', + onKeyDown: onPromptKeyDown}); + } + } + }, + evalInput: function(cm, vim) { + // If the motion comand is set, execute both the operator and motion. + // Otherwise return. + var inputState = vim.inputState; + var motion = inputState.motion; + var motionArgs = inputState.motionArgs || {}; + var operator = inputState.operator; + var operatorArgs = inputState.operatorArgs || {}; + var registerName = inputState.registerName; + var selectionEnd = copyCursor(cm.getCursor('head')); + var selectionStart = copyCursor(cm.getCursor('anchor')); + // The difference between cur and selection cursors are that cur is + // being operated on and ignores that there is a selection. + var curStart = copyCursor(selectionEnd); + var curOriginal = copyCursor(curStart); + var curEnd; + var repeat; + if (operator) { + this.recordLastEdit(vim, inputState); + } + if (inputState.repeatOverride !== undefined) { + // If repeatOverride is specified, that takes precedence over the + // input state's repeat. Used by Ex mode and can be user defined. + repeat = inputState.repeatOverride; + } else { + repeat = inputState.getRepeat(); + } + if (repeat > 0 && motionArgs.explicitRepeat) { + motionArgs.repeatIsExplicit = true; + } else if (motionArgs.noRepeat || + (!motionArgs.explicitRepeat && repeat === 0)) { + repeat = 1; + motionArgs.repeatIsExplicit = false; + } + if (inputState.selectedCharacter) { + // If there is a character input, stick it in all of the arg arrays. + motionArgs.selectedCharacter = operatorArgs.selectedCharacter = + inputState.selectedCharacter; + } + motionArgs.repeat = repeat; + clearInputState(cm); + if (motion) { + var motionResult = motions[motion](cm, motionArgs, vim); + vim.lastMotion = motions[motion]; + if (!motionResult) { + return; + } + if (motionArgs.toJumplist) { + var jumpList = vimGlobalState.jumpList; + // if the current motion is # or *, use cachedCursor + var cachedCursor = jumpList.cachedCursor; + if (cachedCursor) { + recordJumpPosition(cm, cachedCursor, motionResult); + delete jumpList.cachedCursor; + } else { + recordJumpPosition(cm, curOriginal, motionResult); + } + } + if (motionResult instanceof Array) { + curStart = motionResult[0]; + curEnd = motionResult[1]; + } else { + curEnd = motionResult; + } + // TODO: Handle null returns from motion commands better. + if (!curEnd) { + curEnd = Pos(curStart.line, curStart.ch); + } + if (vim.visualMode) { + // Check if the selection crossed over itself. Will need to shift + // the start point if that happened. + // offset is set to -1 or 1 to shift the curEnd + // left or right + var offset = 0; + if (cursorIsBefore(selectionStart, selectionEnd) && + (cursorEqual(selectionStart, curEnd) || + cursorIsBefore(curEnd, selectionStart))) { + // The end of the selection has moved from after the start to + // before the start. We will shift the start right by 1. + selectionStart.ch += 1; + offset = -1; + } else if (cursorIsBefore(selectionEnd, selectionStart) && + (cursorEqual(selectionStart, curEnd) || + cursorIsBefore(selectionStart, curEnd))) { + // The opposite happened. We will shift the start left by 1. + selectionStart.ch -= 1; + offset = 1; + } + // in case of visual Block selectionStart and curEnd + // may not be on the same line, + // Also, In case of v_o this should not happen. + if (!vim.visualBlock && !(motionResult instanceof Array)) { + curEnd.ch += offset; + } + if (vim.lastHPos != Infinity) { + vim.lastHPos = curEnd.ch; + } + selectionEnd = curEnd; + selectionStart = (motionResult instanceof Array) ? curStart : selectionStart; + if (vim.visualLine) { + if (cursorIsBefore(selectionStart, selectionEnd)) { + selectionStart.ch = 0; + + var lastLine = cm.lastLine(); + if (selectionEnd.line > lastLine) { + selectionEnd.line = lastLine; + } + selectionEnd.ch = lineLength(cm, selectionEnd.line); + } else { + selectionEnd.ch = 0; + selectionStart.ch = lineLength(cm, selectionStart.line); + } + } else if (vim.visualBlock) { + // Select a block and + // return the diagonally opposite end. + selectionStart = selectBlock(cm, selectionEnd); + } + if (!vim.visualBlock) { + cm.setSelection(selectionStart, selectionEnd); + } + updateMark(cm, vim, '<', + cursorIsBefore(selectionStart, selectionEnd) ? selectionStart + : selectionEnd); + updateMark(cm, vim, '>', + cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd + : selectionStart); + } else if (!operator) { + curEnd = clipCursorToContent(cm, curEnd); + cm.setCursor(curEnd.line, curEnd.ch); + } + } + + if (operator) { + var inverted = false; + vim.lastMotion = null; + var lastSelection = vim.lastSelection; + operatorArgs.repeat = repeat; // Indent in visual mode needs this. + if (vim.visualMode) { + curStart = selectionStart; + curEnd = selectionEnd; + motionArgs.inclusive = true; + operatorArgs.shouldMoveCursor = false; + } + // Swap start and end if motion was backward. + if (curEnd && cursorIsBefore(curEnd, curStart)) { + var tmp = curStart; + curStart = curEnd; + curEnd = tmp; + inverted = true; + } else if (!curEnd) { + curEnd = copyCursor(curStart); + } + if (motionArgs.inclusive && !vim.visualMode) { + // Move the selection end one to the right to include the last + // character. + curEnd.ch++; + } + if (operatorArgs.selOffset) { + // Replaying a visual mode operation + curEnd.line = curStart.line + operatorArgs.selOffset.line; + if (operatorArgs.selOffset.line) {curEnd.ch = operatorArgs.selOffset.ch; } + else { curEnd.ch = curStart.ch + operatorArgs.selOffset.ch; } + // In case of blockwise visual + if (lastSelection && lastSelection.visualBlock) { + var block = lastSelection.visualBlock; + var width = block.width; + var height = block.height; + curEnd = Pos(curStart.line + height, curStart.ch + width); + // selectBlock creates a 'proper' rectangular block. + // We do not want that in all cases, so we manually set selections. + var selections = []; + for (var i = curStart.line; i < curEnd.line; i++) { + var anchor = Pos(i, curStart.ch); + var head = Pos(i, curEnd.ch); + var range = {anchor: anchor, head: head}; + selections.push(range); + } + cm.setSelections(selections); + var blockSelected = true; + } + } else if (vim.visualMode) { + var selOffset = Pos(); + selOffset.line = curEnd.line - curStart.line; + if (selOffset.line) { selOffset.ch = curEnd.ch; } + else { selOffset.ch = curEnd.ch - curStart.ch; } + operatorArgs.selOffset = selOffset; + } + var linewise = motionArgs.linewise || + (vim.visualMode && vim.visualLine) || + operatorArgs.linewise; + if (linewise) { + // Expand selection to entire line. + expandSelectionToLine(cm, curStart, curEnd); + } else if (motionArgs.forward) { + // Clip to trailing newlines only if the motion goes forward. + clipToLine(cm, curStart, curEnd); + } + operatorArgs.registerName = registerName; + // Keep track of linewise as it affects how paste and change behave. + operatorArgs.linewise = linewise; + if (!vim.visualBlock && !blockSelected) { + cm.setSelection(curStart, curEnd); + } + operators[operator](cm, operatorArgs, vim, curStart, + curEnd, curOriginal); + if (vim.visualMode) { + exitVisualMode(cm); + } + } + }, + recordLastEdit: function(vim, inputState, actionCommand) { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isPlaying) { return; } + vim.lastEditInputState = inputState; + vim.lastEditActionCommand = actionCommand; + macroModeState.lastInsertModeChanges.changes = []; + macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false; + } + }; + + /** + * typedef {Object{line:number,ch:number}} Cursor An object containing the + * position of the cursor. + */ + // All of the functions below return Cursor objects. + var motions = { + moveToTopLine: function(cm, motionArgs) { + var line = getUserVisibleLines(cm).top + motionArgs.repeat -1; + return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); + }, + moveToMiddleLine: function(cm) { + var range = getUserVisibleLines(cm); + var line = Math.floor((range.top + range.bottom) * 0.5); + return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); + }, + moveToBottomLine: function(cm, motionArgs) { + var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1; + return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); + }, + expandToLine: function(cm, motionArgs) { + // Expands forward to end of line, and then to next line if repeat is + // >1. Does not handle backward motion! + var cur = cm.getCursor(); + return Pos(cur.line + motionArgs.repeat - 1, Infinity); + }, + findNext: function(cm, motionArgs) { + var state = getSearchState(cm); + var query = state.getQuery(); + if (!query) { + return; + } + var prev = !motionArgs.forward; + // If search is initiated with ? instead of /, negate direction. + prev = (state.isReversed()) ? !prev : prev; + highlightSearchMatches(cm, query); + return findNext(cm, prev/** prev */, query, motionArgs.repeat); + }, + goToMark: function(cm, motionArgs, vim) { + var mark = vim.marks[motionArgs.selectedCharacter]; + if (mark) { + var pos = mark.find(); + return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos; + } + return null; + }, + moveToOtherHighlightedEnd: function(cm, motionArgs, vim) { + var ranges = cm.listSelections(); + var curEnd = cm.getCursor('head'); + var curStart = ranges[0].anchor; + var curIndex = cursorEqual(ranges[0].head, curEnd) ? ranges.length-1 : 0; + if (motionArgs.sameLine && vim.visualBlock) { + curStart = Pos(curEnd.line, ranges[curIndex].anchor.ch); + curEnd = Pos(ranges[curIndex].head.line, curEnd.ch); + } else { + curStart = ranges[curIndex].anchor; + } + cm.setCursor(curEnd); + return ([curEnd, curStart]); + }, + jumpToMark: function(cm, motionArgs, vim) { + var best = cm.getCursor(); + for (var i = 0; i < motionArgs.repeat; i++) { + var cursor = best; + for (var key in vim.marks) { + if (!isLowerCase(key)) { + continue; + } + var mark = vim.marks[key].find(); + var isWrongDirection = (motionArgs.forward) ? + cursorIsBefore(mark, cursor) : cursorIsBefore(cursor, mark); + + if (isWrongDirection) { + continue; + } + if (motionArgs.linewise && (mark.line == cursor.line)) { + continue; + } + + var equal = cursorEqual(cursor, best); + var between = (motionArgs.forward) ? + cursorIsBetween(cursor, mark, best) : + cursorIsBetween(best, mark, cursor); + + if (equal || between) { + best = mark; + } + } + } + + if (motionArgs.linewise) { + // Vim places the cursor on the first non-whitespace character of + // the line if there is one, else it places the cursor at the end + // of the line, regardless of whether a mark was found. + best = Pos(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line))); + } + return best; + }, + moveByCharacters: function(cm, motionArgs) { + var cur = cm.getCursor(); + var repeat = motionArgs.repeat; + var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat; + return Pos(cur.line, ch); + }, + moveByLines: function(cm, motionArgs, vim) { + var cur = cm.getCursor(); + var endCh = cur.ch; + // Depending what our last motion was, we may want to do different + // things. If our last motion was moving vertically, we want to + // preserve the HPos from our last horizontal move. If our last motion + // was going to the end of a line, moving vertically we should go to + // the end of the line, etc. + switch (vim.lastMotion) { + case this.moveByLines: + case this.moveByDisplayLines: + case this.moveByScroll: + case this.moveToColumn: + case this.moveToEol: + endCh = vim.lastHPos; + break; + default: + vim.lastHPos = endCh; + } + var repeat = motionArgs.repeat+(motionArgs.repeatOffset||0); + var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat; + var first = cm.firstLine(); + var last = cm.lastLine(); + // Vim cancels linewise motions that start on an edge and move beyond + // that edge. It does not cancel motions that do not start on an edge. + if ((line < first && cur.line == first) || + (line > last && cur.line == last)) { + return; + } + if (motionArgs.toFirstChar){ + endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line)); + vim.lastHPos = endCh; + } + vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left; + return Pos(line, endCh); + }, + moveByDisplayLines: function(cm, motionArgs, vim) { + var cur = cm.getCursor(); + switch (vim.lastMotion) { + case this.moveByDisplayLines: + case this.moveByScroll: + case this.moveByLines: + case this.moveToColumn: + case this.moveToEol: + break; + default: + vim.lastHSPos = cm.charCoords(cur,'div').left; + } + var repeat = motionArgs.repeat; + var res=cm.findPosV(cur,(motionArgs.forward ? repeat : -repeat),'line',vim.lastHSPos); + if (res.hitSide) { + if (motionArgs.forward) { + var lastCharCoords = cm.charCoords(res, 'div'); + var goalCoords = { top: lastCharCoords.top + 8, left: vim.lastHSPos }; + var res = cm.coordsChar(goalCoords, 'div'); + } else { + var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div'); + resCoords.left = vim.lastHSPos; + res = cm.coordsChar(resCoords, 'div'); + } + } + vim.lastHPos = res.ch; + return res; + }, + moveByPage: function(cm, motionArgs) { + // CodeMirror only exposes functions that move the cursor page down, so + // doing this bad hack to move the cursor and move it back. evalInput + // will move the cursor to where it should be in the end. + var curStart = cm.getCursor(); + var repeat = motionArgs.repeat; + return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page'); + }, + moveByParagraph: function(cm, motionArgs) { + var line = cm.getCursor().line; + var repeat = motionArgs.repeat; + var inc = motionArgs.forward ? 1 : -1; + for (var i = 0; i < repeat; i++) { + if ((!motionArgs.forward && line === cm.firstLine() ) || + (motionArgs.forward && line == cm.lastLine())) { + break; + } + line += inc; + while (line !== cm.firstLine() && line != cm.lastLine() && cm.getLine(line)) { + line += inc; + } + } + return Pos(line, 0); + }, + moveByScroll: function(cm, motionArgs, vim) { + var scrollbox = cm.getScrollInfo(); + var curEnd = null; + var repeat = motionArgs.repeat; + if (!repeat) { + repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight()); + } + var orig = cm.charCoords(cm.getCursor(), 'local'); + motionArgs.repeat = repeat; + var curEnd = motions.moveByDisplayLines(cm, motionArgs, vim); + if (!curEnd) { + return null; + } + var dest = cm.charCoords(curEnd, 'local'); + cm.scrollTo(null, scrollbox.top + dest.top - orig.top); + return curEnd; + }, + moveByWords: function(cm, motionArgs) { + return moveToWord(cm, motionArgs.repeat, !!motionArgs.forward, + !!motionArgs.wordEnd, !!motionArgs.bigWord); + }, + moveTillCharacter: function(cm, motionArgs) { + var repeat = motionArgs.repeat; + var curEnd = moveToCharacter(cm, repeat, motionArgs.forward, + motionArgs.selectedCharacter); + var increment = motionArgs.forward ? -1 : 1; + recordLastCharacterSearch(increment, motionArgs); + if (!curEnd) return null; + curEnd.ch += increment; + return curEnd; + }, + moveToCharacter: function(cm, motionArgs) { + var repeat = motionArgs.repeat; + recordLastCharacterSearch(0, motionArgs); + return moveToCharacter(cm, repeat, motionArgs.forward, + motionArgs.selectedCharacter) || cm.getCursor(); + }, + moveToSymbol: function(cm, motionArgs) { + var repeat = motionArgs.repeat; + return findSymbol(cm, repeat, motionArgs.forward, + motionArgs.selectedCharacter) || cm.getCursor(); + }, + moveToColumn: function(cm, motionArgs, vim) { + var repeat = motionArgs.repeat; + // repeat is equivalent to which column we want to move to! + vim.lastHPos = repeat - 1; + vim.lastHSPos = cm.charCoords(cm.getCursor(),'div').left; + return moveToColumn(cm, repeat); + }, + moveToEol: function(cm, motionArgs, vim) { + var cur = cm.getCursor(); + vim.lastHPos = Infinity; + var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity); + var end=cm.clipPos(retval); + end.ch--; + vim.lastHSPos = cm.charCoords(end,'div').left; + return retval; + }, + moveToFirstNonWhiteSpaceCharacter: function(cm) { + // Go to the start of the line where the text begins, or the end for + // whitespace-only lines + var cursor = cm.getCursor(); + return Pos(cursor.line, + findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))); + }, + moveToMatchedSymbol: function(cm) { + var cursor = cm.getCursor(); + var line = cursor.line; + var ch = cursor.ch; + var lineText = cm.getLine(line); + var symbol; + do { + symbol = lineText.charAt(ch++); + if (symbol && isMatchableSymbol(symbol)) { + var style = cm.getTokenTypeAt(Pos(line, ch)); + if (style !== "string" && style !== "comment") { + break; + } + } + } while (symbol); + if (symbol) { + var matched = cm.findMatchingBracket(Pos(line, ch)); + return matched.to; + } else { + return cursor; + } + }, + moveToStartOfLine: function(cm) { + var cursor = cm.getCursor(); + return Pos(cursor.line, 0); + }, + moveToLineOrEdgeOfDocument: function(cm, motionArgs) { + var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine(); + if (motionArgs.repeatIsExplicit) { + lineNum = motionArgs.repeat - cm.getOption('firstLineNumber'); + } + return Pos(lineNum, + findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))); + }, + textObjectManipulation: function(cm, motionArgs) { + // TODO: lots of possible exceptions that can be thrown here. Try da( + // outside of a () block. + + // TODO: adding <> >< to this map doesn't work, presumably because + // they're operators + var mirroredPairs = {'(': ')', ')': '(', + '{': '}', '}': '{', + '[': ']', ']': '['}; + var selfPaired = {'\'': true, '"': true}; + + var character = motionArgs.selectedCharacter; + // 'b' refers to '()' block. + // 'B' refers to '{}' block. + if (character == 'b') { + character = '('; + } else if (character == 'B') { + character = '{'; + } + + // Inclusive is the difference between a and i + // TODO: Instead of using the additional text object map to perform text + // object operations, merge the map into the defaultKeyMap and use + // motionArgs to define behavior. Define separate entries for 'aw', + // 'iw', 'a[', 'i[', etc. + var inclusive = !motionArgs.textObjectInner; + + var tmp; + if (mirroredPairs[character]) { + tmp = selectCompanionObject(cm, character, inclusive); + } else if (selfPaired[character]) { + tmp = findBeginningAndEnd(cm, character, inclusive); + } else if (character === 'W') { + tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, + true /** bigWord */); + } else if (character === 'w') { + tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, + false /** bigWord */); + } else if (character === 'p') { + tmp = expandParagraphUnderCursor(cm, inclusive, true /** forward */, + false /** bigWord */); + } else { + // No text object defined for this, don't move. + return null; + } + + if (!cm.state.vim.visualMode) { + return [tmp.start, tmp.end]; + } else { + return expandSelection(cm, tmp.start, tmp.end); + } + }, + + repeatLastCharacterSearch: function(cm, motionArgs) { + var lastSearch = vimGlobalState.lastChararacterSearch; + var repeat = motionArgs.repeat; + var forward = motionArgs.forward === lastSearch.forward; + var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1); + cm.moveH(-increment, 'char'); + motionArgs.inclusive = forward ? true : false; + var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter); + if (!curEnd) { + cm.moveH(increment, 'char'); + return cm.getCursor(); + } + curEnd.ch += increment; + return curEnd; + } + }; + + var operators = { + change: function(cm, operatorArgs, vim) { + var selections = cm.listSelections(); + var start = selections[0], end = selections[selections.length-1]; + var curStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; + var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; + var text = cm.getSelection(); + var visualBlock = vim.visualBlock; + if (vim.lastSelection && !vim.visualMode) { + visualBlock = vim.lastSelection.visualBlock ? true : visualBlock; + } + var lastInsertModeChanges = vimGlobalState.macroModeState.lastInsertModeChanges; + lastInsertModeChanges.inVisualBlock = visualBlock; + var replacement = new Array(selections.length).join('1').split('1'); + // save the selectionEnd mark + var selectionEnd = vim.marks[">"] && vim.marks[">"].find(); + if (!selectionEnd) { + selectionEnd = cm.getCursor("head"); + } + vimGlobalState.registerController.pushText( + operatorArgs.registerName, 'change', text, + operatorArgs.linewise); + if (operatorArgs.linewise) { + // 'C' in visual block extends the block till eol for all lines + if (visualBlock){ + var startLine = curStart.line; + while (startLine <= curEnd.line) { + var endCh = lineLength(cm, startLine); + var head = Pos(startLine, endCh); + var anchor = Pos(startLine, curStart.ch); + startLine++; + cm.replaceRange('', anchor, head); + } + } else { + // Push the next line back down, if there is a next line. + replacement = '\n'; + if (curEnd.line == curStart.line && curEnd.line == cm.lastLine()) { + replacement = ''; + } + cm.replaceRange(replacement, curStart, curEnd); + cm.indentLine(curStart.line, 'smart'); + // null ch so setCursor moves to end of line. + curStart.ch = null; + cm.setCursor(curStart); + } + } else { + // Exclude trailing whitespace if the range is not all whitespace. + var text = cm.getRange(curStart, curEnd); + if (!isWhiteSpaceString(text)) { + var match = (/\s+$/).exec(text); + if (match) { + curEnd = offsetCursor(curEnd, 0, - match[0].length); + } + } + if (visualBlock) { + cm.replaceSelections(replacement); + } else { + cm.setCursor(curStart); + cm.replaceRange('', curStart, curEnd); + } + } + vim.marks['>'] = cm.setBookmark(selectionEnd); + actions.enterInsertMode(cm, {}, cm.state.vim); + }, + // delete is a javascript keyword. + 'delete': function(cm, operatorArgs, vim) { + var selections = cm.listSelections(); + var start = selections[0], end = selections[selections.length-1]; + var curStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; + var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; + // Save the '>' mark before cm.replaceRange clears it. + var selectionEnd, selectionStart; + var blockwise = vim.visualBlock; + if (vim.visualMode) { + selectionEnd = vim.marks['>'].find(); + selectionStart = vim.marks['<'].find(); + } else if (vim.lastSelection) { + selectionEnd = vim.lastSelection.curStartMark.find(); + selectionStart = vim.lastSelection.curEndMark.find(); + blockwise = vim.lastSelection.visualBlock; + } + var text = cm.getSelection(); + vimGlobalState.registerController.pushText( + operatorArgs.registerName, 'delete', text, + operatorArgs.linewise, blockwise); + var replacement = new Array(selections.length).join('1').split('1'); + // If the ending line is past the last line, inclusive, instead of + // including the trailing \n, include the \n before the starting line + if (operatorArgs.linewise && + curEnd.line == cm.lastLine() && curStart.line == curEnd.line) { + if (curEnd.line == 0) { + curStart.ch = 0; + } + else { + var tmp = copyCursor(curEnd); + curStart.line--; + curStart.ch = lineLength(cm, curStart.line); + curEnd = tmp; + } + cm.replaceRange('', curStart, curEnd); + } else { + cm.replaceSelections(replacement); + } + // restore the saved bookmark + if (selectionEnd) { + var curStartMark = cm.setBookmark(selectionStart); + var curEndMark = cm.setBookmark(selectionEnd); + if (vim.visualMode) { + vim.marks['<'] = curStartMark; + vim.marks['>'] = curEndMark; + } else { + vim.lastSelection.curStartMark = curStartMark; + vim.lastSelection.curEndMark = curEndMark; + } + } + if (operatorArgs.linewise) { + cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + } else { + cm.setCursor(curStart); + } + }, + indent: function(cm, operatorArgs, vim, curStart, curEnd) { + var startLine = curStart.line; + var endLine = curEnd.line; + // In visual mode, n> shifts the selection right n times, instead of + // shifting n lines right once. + var repeat = (vim.visualMode) ? operatorArgs.repeat : 1; + if (operatorArgs.linewise) { + // The only way to delete a newline is to delete until the start of + // the next line, so in linewise mode evalInput will include the next + // line. We don't want this in indent, so we go back a line. + endLine--; + } + for (var i = startLine; i <= endLine; i++) { + for (var j = 0; j < repeat; j++) { + cm.indentLine(i, operatorArgs.indentRight); + } + } + cm.setCursor(curStart); + cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + }, + changeCase: function(cm, operatorArgs, _vim, _curStart, _curEnd, _curOriginal) { + var selections = cm.getSelections(); + var ranges = cm.listSelections(); + var swapped = []; + var toLower = operatorArgs.toLower; + for (var j = 0; j < selections.length; j++) { + var toSwap = selections[j]; + var text = ''; + if (toLower === true) { + text = toSwap.toLowerCase(); + } else if (toLower === false) { + text = toSwap.toUpperCase(); + } else { + for (var i = 0; i < toSwap.length; i++) { + var character = toSwap.charAt(i); + text += isUpperCase(character) ? character.toLowerCase() : + character.toUpperCase(); + } + } + swapped.push(text); + } + cm.replaceSelections(swapped); + var curStart = ranges[0].anchor; + var curEnd = ranges[0].head; + if (!operatorArgs.shouldMoveCursor) { + cm.setCursor(cursorIsBefore(curStart, curEnd) ? curStart : curEnd); + } + }, + yank: function(cm, operatorArgs, vim, _curStart, _curEnd, curOriginal) { + var text = cm.getSelection(); + vimGlobalState.registerController.pushText( + operatorArgs.registerName, 'yank', + text, operatorArgs.linewise, vim.visualBlock); + cm.setCursor(curOriginal); + } + }; + + var actions = { + jumpListWalk: function(cm, actionArgs, vim) { + if (vim.visualMode) { + return; + } + var repeat = actionArgs.repeat; + var forward = actionArgs.forward; + var jumpList = vimGlobalState.jumpList; + + var mark = jumpList.move(cm, forward ? repeat : -repeat); + var markPos = mark ? mark.find() : undefined; + markPos = markPos ? markPos : cm.getCursor(); + cm.setCursor(markPos); + }, + scroll: function(cm, actionArgs, vim) { + if (vim.visualMode) { + return; + } + var repeat = actionArgs.repeat || 1; + var lineHeight = cm.defaultTextHeight(); + var top = cm.getScrollInfo().top; + var delta = lineHeight * repeat; + var newPos = actionArgs.forward ? top + delta : top - delta; + var cursor = copyCursor(cm.getCursor()); + var cursorCoords = cm.charCoords(cursor, 'local'); + if (actionArgs.forward) { + if (newPos > cursorCoords.top) { + cursor.line += (newPos - cursorCoords.top) / lineHeight; + cursor.line = Math.ceil(cursor.line); + cm.setCursor(cursor); + cursorCoords = cm.charCoords(cursor, 'local'); + cm.scrollTo(null, cursorCoords.top); + } else { + // Cursor stays within bounds. Just reposition the scroll window. + cm.scrollTo(null, newPos); + } + } else { + var newBottom = newPos + cm.getScrollInfo().clientHeight; + if (newBottom < cursorCoords.bottom) { + cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight; + cursor.line = Math.floor(cursor.line); + cm.setCursor(cursor); + cursorCoords = cm.charCoords(cursor, 'local'); + cm.scrollTo( + null, cursorCoords.bottom - cm.getScrollInfo().clientHeight); + } else { + // Cursor stays within bounds. Just reposition the scroll window. + cm.scrollTo(null, newPos); + } + } + }, + scrollToCursor: function(cm, actionArgs) { + var lineNum = cm.getCursor().line; + var charCoords = cm.charCoords(Pos(lineNum, 0), 'local'); + var height = cm.getScrollInfo().clientHeight; + var y = charCoords.top; + var lineHeight = charCoords.bottom - y; + switch (actionArgs.position) { + case 'center': y = y - (height / 2) + lineHeight; + break; + case 'bottom': y = y - height + lineHeight*1.4; + break; + case 'top': y = y + lineHeight*0.4; + break; + } + cm.scrollTo(null, y); + }, + replayMacro: function(cm, actionArgs, vim) { + var registerName = actionArgs.selectedCharacter; + var repeat = actionArgs.repeat; + var macroModeState = vimGlobalState.macroModeState; + if (registerName == '@') { + registerName = macroModeState.latestRegister; + } + while(repeat--){ + executeMacroRegister(cm, vim, macroModeState, registerName); + } + }, + enterMacroRecordMode: function(cm, actionArgs) { + var macroModeState = vimGlobalState.macroModeState; + var registerName = actionArgs.selectedCharacter; + macroModeState.enterMacroRecordMode(cm, registerName); + }, + enterInsertMode: function(cm, actionArgs, vim) { + if (cm.getOption('readOnly')) { return; } + vim.insertMode = true; + vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1; + var insertAt = (actionArgs) ? actionArgs.insertAt : null; + if (vim.visualMode) { + var selections = getSelectedAreaRange(cm, vim); + var selectionStart = selections[0]; + var selectionEnd = selections[1]; + } + if (insertAt == 'eol') { + var cursor = cm.getCursor(); + cursor = Pos(cursor.line, lineLength(cm, cursor.line)); + cm.setCursor(cursor); + } else if (insertAt == 'charAfter') { + cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); + } else if (insertAt == 'firstNonBlank') { + if (vim.visualMode && !vim.visualBlock) { + if (selectionEnd.line < selectionStart.line) { + cm.setCursor(selectionEnd); + } else { + selectionStart = Pos(selectionStart.line, 0); + cm.setCursor(selectionStart); + } + cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + } else if (vim.visualBlock) { + selectionEnd = Pos(selectionEnd.line, selectionStart.ch); + cm.setCursor(selectionStart); + selectBlock(cm, selectionEnd); + } else { + cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + } + } else if (insertAt == 'endOfSelectedArea') { + if (vim.visualBlock) { + selectionStart = Pos(selectionStart.line, selectionEnd.ch); + cm.setCursor(selectionStart); + selectBlock(cm, selectionEnd); + } else if (selectionEnd && selectionEnd.line < selectionStart.line) { + selectionEnd = Pos(selectionStart.line, 0); + cm.setCursor(selectionEnd); + } + } else if (insertAt == 'inplace') { + if (vim.visualMode){ + return; + } + } + cm.setOption('keyMap', 'vim-insert'); + cm.setOption('disableInput', false); + if (actionArgs && actionArgs.replace) { + // Handle Replace-mode as a special case of insert mode. + cm.toggleOverwrite(true); + cm.setOption('keyMap', 'vim-replace'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); + } else { + cm.setOption('keyMap', 'vim-insert'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); + } + if (!vimGlobalState.macroModeState.isPlaying) { + // Only record if not replaying. + cm.on('change', onChange); + CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); + } + if (vim.visualMode) { + exitVisualMode(cm); + } + }, + toggleVisualMode: function(cm, actionArgs, vim) { + var repeat = actionArgs.repeat; + var curStart = cm.getCursor(); + var curEnd; + var selections = cm.listSelections(); + // TODO: The repeat should actually select number of characters/lines + // equal to the repeat times the size of the previous visual + // operation. + if (!vim.visualMode) { + vim.visualMode = true; + vim.visualLine = !!actionArgs.linewise; + vim.visualBlock = !!actionArgs.blockwise; + if (vim.visualLine) { + curStart.ch = 0; + curEnd = clipCursorToContent( + cm, Pos(curStart.line + repeat - 1, lineLength(cm, curStart.line)), + true /** includeLineBreak */); + } else { + curEnd = clipCursorToContent( + cm, Pos(curStart.line, curStart.ch + repeat), + true /** includeLineBreak */); + } + cm.setSelection(curStart, curEnd); + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""}); + } else { + curStart = cm.getCursor('anchor'); + curEnd = cm.getCursor('head'); + if (vim.visualLine) { + if (actionArgs.blockwise) { + // This means Ctrl-V pressed in linewise visual + vim.visualBlock = true; + selectBlock(cm, curEnd); + CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'blockwise'}); + } else if (!actionArgs.linewise) { + // v pressed in linewise, switch to characterwise visual mode + CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual'}); + } else { + exitVisualMode(cm); + } + vim.visualLine = false; + } else if (vim.visualBlock) { + if (actionArgs.linewise) { + // Shift-V pressed in blockwise visual mode + vim.visualLine = true; + curStart = Pos(selections[0].anchor.line, 0); + curEnd = Pos(selections[selections.length-1].anchor.line, lineLength(cm, selections[selections.length-1].anchor.line)); + cm.setSelection(curStart, curEnd); + CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'linewise'}); + } else if (!actionArgs.blockwise) { + // v pressed in blockwise mode, Switch to characterwise + if (curEnd != selections[0].head) { + curStart = selections[0].anchor; + } else { + curStart = selections[selections.length-1].anchor; + } + cm.setSelection(curStart, curEnd); + CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual'}); + } else { + exitVisualMode(cm); + } + vim.visualBlock = false; + } else if (actionArgs.linewise) { + // Shift-V pressed in characterwise visual mode. Switch to linewise + // visual mode instead of exiting visual mode. + vim.visualLine = true; + curStart.ch = cursorIsBefore(curStart, curEnd) ? 0 : + lineLength(cm, curStart.line); + curEnd.ch = cursorIsBefore(curStart, curEnd) ? + lineLength(cm, curEnd.line) : 0; + cm.setSelection(curStart, curEnd); + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: "linewise"}); + } else if (actionArgs.blockwise) { + vim.visualBlock = true; + selectBlock(cm, curEnd); + CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'blockwise'}); + } else { + exitVisualMode(cm); + } + } + updateMark(cm, vim, '<', cursorIsBefore(curStart, curEnd) ? curStart + : curEnd); + updateMark(cm, vim, '>', cursorIsBefore(curStart, curEnd) ? curEnd + : curStart); + }, + reselectLastSelection: function(cm, _actionArgs, vim) { + var curStart = vim.marks['<'].find(); + var curEnd = vim.marks['>'].find(); + var lastSelection = vim.lastSelection; + if (lastSelection) { + // Set the selections as per last selection + var selectionStart = lastSelection.curStartMark.find(); + var selectionEnd = lastSelection.curEndMark.find(); + var blockwise = lastSelection.visualBlock; + // update last selection + updateLastSelection(cm, vim, curStart, curEnd); + if (blockwise) { + cm.setCursor(selectionStart); + selectionStart = selectBlock(cm, selectionEnd); + } else { + cm.setSelection(selectionStart, selectionEnd); + selectionStart = cm.getCursor('anchor'); + selectionEnd = cm.getCursor('head'); + } + if (vim.visualMode) { + updateMark(cm, vim, '<', cursorIsBefore(selectionStart, selectionEnd) ? selectionStart + : selectionEnd); + updateMark(cm, vim, '>', cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd + : selectionStart); + } + // Last selection is updated now + vim.visualMode = true; + if (lastSelection.visualLine) { + vim.visualLine = true; + vim.visualBlock = false; + } else if (lastSelection.visualBlock) { + vim.visualLine = false; + vim.visualBlock = true; + } else { + vim.visualBlock = vim.visualLine = false; + } + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""}); + } + }, + joinLines: function(cm, actionArgs, vim) { + var curStart, curEnd; + if (vim.visualMode) { + curStart = cm.getCursor('anchor'); + curEnd = cm.getCursor('head'); + curEnd.ch = lineLength(cm, curEnd.line) - 1; + } else { + // Repeat is the number of lines to join. Minimum 2 lines. + var repeat = Math.max(actionArgs.repeat, 2); + curStart = cm.getCursor(); + curEnd = clipCursorToContent(cm, Pos(curStart.line + repeat - 1, + Infinity)); + } + var finalCh = 0; + cm.operation(function() { + for (var i = curStart.line; i < curEnd.line; i++) { + finalCh = lineLength(cm, curStart.line); + var tmp = Pos(curStart.line + 1, + lineLength(cm, curStart.line + 1)); + var text = cm.getRange(curStart, tmp); + text = text.replace(/\n\s*/g, ' '); + cm.replaceRange(text, curStart, tmp); + } + var curFinalPos = Pos(curStart.line, finalCh); + cm.setCursor(curFinalPos); + }); + }, + newLineAndEnterInsertMode: function(cm, actionArgs, vim) { + vim.insertMode = true; + var insertAt = copyCursor(cm.getCursor()); + if (insertAt.line === cm.firstLine() && !actionArgs.after) { + // Special case for inserting newline before start of document. + cm.replaceRange('\n', Pos(cm.firstLine(), 0)); + cm.setCursor(cm.firstLine(), 0); + } else { + insertAt.line = (actionArgs.after) ? insertAt.line : + insertAt.line - 1; + insertAt.ch = lineLength(cm, insertAt.line); + cm.setCursor(insertAt); + var newlineFn = CodeMirror.commands.newlineAndIndentContinueComment || + CodeMirror.commands.newlineAndIndent; + newlineFn(cm); + } + this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim); + }, + paste: function(cm, actionArgs, vim) { + var cur = copyCursor(cm.getCursor()); + var register = vimGlobalState.registerController.getRegister( + actionArgs.registerName); + var text = register.toString(); + if (!text) { + return; + } + if (actionArgs.matchIndent) { + var tabSize = cm.getOption("tabSize"); + // length that considers tabs and tabSize + var whitespaceLength = function(str) { + var tabs = (str.split("\t").length - 1); + var spaces = (str.split(" ").length - 1); + return tabs * tabSize + spaces * 1; + }; + var currentLine = cm.getLine(cm.getCursor().line); + var indent = whitespaceLength(currentLine.match(/^\s*/)[0]); + // chomp last newline b/c don't want it to match /^\s*/gm + var chompedText = text.replace(/\n$/, ''); + var wasChomped = text !== chompedText; + var firstIndent = whitespaceLength(text.match(/^\s*/)[0]); + var text = chompedText.replace(/^\s*/gm, function(wspace) { + var newIndent = indent + (whitespaceLength(wspace) - firstIndent); + if (newIndent < 0) { + return ""; + } + else if (cm.getOption("indentWithTabs")) { + var quotient = Math.floor(newIndent / tabSize); + return Array(quotient + 1).join('\t'); + } + else { + return Array(newIndent + 1).join(' '); + } + }); + text += wasChomped ? "\n" : ""; + } + if (actionArgs.repeat > 1) { + var text = Array(actionArgs.repeat + 1).join(text); + } + var linewise = register.linewise; + var blockwise = register.blockwise; + if (linewise) { + if(vim.visualMode) { + text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n'; + } else if (actionArgs.after) { + // Move the newline at the end to the start instead, and paste just + // before the newline character of the line we are on right now. + text = '\n' + text.slice(0, text.length - 1); + cur.ch = lineLength(cm, cur.line); + } else { + cur.ch = 0; + } + } else { + if (blockwise) { + text = text.split('\n'); + for (var i = 0; i < text.length; i++) { + text[i] = (text[i] == '') ? ' ' : text[i]; + } + } + cur.ch += actionArgs.after ? 1 : 0; + } + var curPosFinal; + var idx; + if (vim.visualMode) { + // save the pasted text for reselection if the need arises + vim.lastPastedText = text; + var lastSelectionCurEnd; + var selectedArea = getSelectedAreaRange(cm, vim); + var selectionStart = selectedArea[0]; + var selectionEnd = selectedArea[1]; + var selectedText = cm.getSelection(); + var selections = cm.listSelections(); + var emptyStrings = new Array(selections.length).join('1').split('1'); + // save the curEnd marker before it get cleared due to cm.replaceRange. + if (vim.lastSelection) { + lastSelectionCurEnd = vim.lastSelection.curEndMark.find(); + } + // push the previously selected text to unnamed register + vimGlobalState.registerController.unnamedRegister.setText(selectedText); + if (blockwise) { + // first delete the selected text + cm.replaceSelections(emptyStrings); + // Set new selections as per the block length of the yanked text + selectionEnd = Pos(selectionStart.line + text.length-1, selectionStart.ch); + cm.setCursor(selectionStart); + selectBlock(cm, selectionEnd); + cm.replaceSelections(text); + curPosFinal = selectionStart; + } else if (vim.visualBlock) { + cm.replaceSelections(emptyStrings); + cm.setCursor(selectionStart); + cm.replaceRange(text, selectionStart, selectionStart); + curPosFinal = selectionStart; + } else { + cm.replaceRange(text, selectionStart, selectionEnd); + curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1); + } + // restore the the curEnd marker + if(lastSelectionCurEnd) { + vim.lastSelection.curEndMark = cm.setBookmark(lastSelectionCurEnd); + } + if (linewise) { + curPosFinal.ch=0; + } + } else { + if (blockwise) { + cm.setCursor(cur); + for (var i = 0; i < text.length; i++) { + var line = cur.line+i; + if (line > cm.lastLine()) { + cm.replaceRange('\n', Pos(line, 0)); + } + var lastCh = lineLength(cm, line); + if (lastCh < cur.ch) { + extendLineToColumn(cm, line, cur.ch); + } + } + cm.setCursor(cur); + selectBlock(cm, Pos(cur.line + text.length-1, cur.ch)); + cm.replaceSelections(text); + curPosFinal = cur; + } else { + cm.replaceRange(text, cur); + // Now fine tune the cursor to where we want it. + if (linewise && actionArgs.after) { + curPosFinal = Pos( + cur.line + 1, + findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1))); + } else if (linewise && !actionArgs.after) { + curPosFinal = Pos( + cur.line, + findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line))); + } else if (!linewise && actionArgs.after) { + idx = cm.indexFromPos(cur); + curPosFinal = cm.posFromIndex(idx + text.length - 1); + } else { + idx = cm.indexFromPos(cur); + curPosFinal = cm.posFromIndex(idx + text.length); + } + } + } + cm.setCursor(curPosFinal); + if (vim.visualMode) { + exitVisualMode(cm); + } + }, + undo: function(cm, actionArgs) { + cm.operation(function() { + repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)(); + cm.setCursor(cm.getCursor('anchor')); + }); + }, + redo: function(cm, actionArgs) { + repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)(); + }, + setRegister: function(_cm, actionArgs, vim) { + vim.inputState.registerName = actionArgs.selectedCharacter; + }, + setMark: function(cm, actionArgs, vim) { + var markName = actionArgs.selectedCharacter; + updateMark(cm, vim, markName, cm.getCursor()); + }, + replace: function(cm, actionArgs, vim) { + var replaceWith = actionArgs.selectedCharacter; + var curStart = cm.getCursor(); + var replaceTo; + var curEnd; + var selections = cm.listSelections(); + if (vim.visualMode) { + curStart = cm.getCursor('start'); + curEnd = cm.getCursor('end'); + } else { + var line = cm.getLine(curStart.line); + replaceTo = curStart.ch + actionArgs.repeat; + if (replaceTo > line.length) { + replaceTo=line.length; + } + curEnd = Pos(curStart.line, replaceTo); + } + if (replaceWith=='\n') { + if (!vim.visualMode) cm.replaceRange('', curStart, curEnd); + // special case, where vim help says to replace by just one line-break + (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm); + } else { + var replaceWithStr = cm.getRange(curStart, curEnd); + //replace all characters in range by selected, but keep linebreaks + replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith); + if (vim.visualBlock) { + // Tabs are split in visua block before replacing + var spaces = new Array(cm.getOption("tabSize")+1).join(' '); + replaceWithStr = cm.getSelection(); + replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n'); + cm.replaceSelections(replaceWithStr); + } else { + cm.replaceRange(replaceWithStr, curStart, curEnd); + } + if (vim.visualMode) { + curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ? + selections[0].anchor : selections[0].head; + cm.setCursor(curStart); + exitVisualMode(cm); + } else { + cm.setCursor(offsetCursor(curEnd, 0, -1)); + } + } + }, + incrementNumberToken: function(cm, actionArgs) { + var cur = cm.getCursor(); + var lineStr = cm.getLine(cur.line); + var re = /-?\d+/g; + var match; + var start; + var end; + var numberStr; + var token; + while ((match = re.exec(lineStr)) !== null) { + token = match[0]; + start = match.index; + end = start + token.length; + if (cur.ch < end)break; + } + if (!actionArgs.backtrack && (end <= cur.ch))return; + if (token) { + var increment = actionArgs.increase ? 1 : -1; + var number = parseInt(token) + (increment * actionArgs.repeat); + var from = Pos(cur.line, start); + var to = Pos(cur.line, end); + numberStr = number.toString(); + cm.replaceRange(numberStr, from, to); + } else { + return; + } + cm.setCursor(Pos(cur.line, start + numberStr.length - 1)); + }, + repeatLastEdit: function(cm, actionArgs, vim) { + var lastEditInputState = vim.lastEditInputState; + if (!lastEditInputState) { return; } + var repeat = actionArgs.repeat; + if (repeat && actionArgs.repeatIsExplicit) { + vim.lastEditInputState.repeatOverride = repeat; + } else { + repeat = vim.lastEditInputState.repeatOverride || repeat; + } + repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */); + }, + exitInsertMode: exitInsertMode + }; + + /* + * Below are miscellaneous utility functions used by vim.js + */ + + /** + * Clips cursor to ensure that line is within the buffer's range + * If includeLineBreak is true, then allow cur.ch == lineLength. + */ + function clipCursorToContent(cm, cur, includeLineBreak) { + var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine() ); + var maxCh = lineLength(cm, line) - 1; + maxCh = (includeLineBreak) ? maxCh + 1 : maxCh; + var ch = Math.min(Math.max(0, cur.ch), maxCh); + return Pos(line, ch); + } + function copyArgs(args) { + var ret = {}; + for (var prop in args) { + if (args.hasOwnProperty(prop)) { + ret[prop] = args[prop]; + } + } + return ret; + } + function offsetCursor(cur, offsetLine, offsetCh) { + return Pos(cur.line + offsetLine, cur.ch + offsetCh); + } + function commandMatches(keys, keyMap, context, inputState) { + // Partial matches are not applied. They inform the key handler + // that the current key sequence is a subsequence of a valid key + // sequence, so that the key buffer is not cleared. + var match, partial = [], full = []; + for (var i = 0; i < keyMap.length; i++) { + var command = keyMap[i]; + if (context == 'insert' && command.context != 'insert' || + command.context && command.context != context || + inputState.operator && command.type == 'action' || + !(match = commandMatch(keys, command.keys))) { continue; } + if (match == 'partial') { partial.push(command); } + if (match == 'full') { full.push(command); } + } + return { + partial: partial.length && partial, + full: full.length && full + }; + } + function commandMatch(pressed, mapped) { + if (mapped.slice(-11) == '') { + // Last character matches anything. + var prefixLen = mapped.length - 11; + var pressedPrefix = pressed.slice(0, prefixLen); + var mappedPrefix = mapped.slice(0, prefixLen); + return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' : + mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false; + } else { + return pressed == mapped ? 'full' : + mapped.indexOf(pressed) == 0 ? 'partial' : false; + } + } + function lastChar(keys) { + var match = /^.*(<[\w\-]+>)$/.exec(keys); + var selectedCharacter = match ? match[1] : keys.slice(-1); + if (selectedCharacter.length > 1){ + switch(selectedCharacter){ + case '': + selectedCharacter='\n'; + break; + case '': + selectedCharacter=' '; + break; + default: + break; + } + } + return selectedCharacter; + } + function repeatFn(cm, fn, repeat) { + return function() { + for (var i = 0; i < repeat; i++) { + fn(cm); + } + }; + } + function copyCursor(cur) { + return Pos(cur.line, cur.ch); + } + function cursorEqual(cur1, cur2) { + return cur1.ch == cur2.ch && cur1.line == cur2.line; + } + function cursorIsBefore(cur1, cur2) { + if (cur1.line < cur2.line) { + return true; + } + if (cur1.line == cur2.line && cur1.ch < cur2.ch) { + return true; + } + return false; + } + function cursorMin(cur1, cur2) { + return cursorIsBefore(cur1, cur2) ? cur1 : cur2; + } + function cursorMax(cur1, cur2) { + return cursorIsBefore(cur1, cur2) ? cur2 : cur1; + } + function cursorIsBetween(cur1, cur2, cur3) { + // returns true if cur2 is between cur1 and cur3. + var cur1before2 = cursorIsBefore(cur1, cur2); + var cur2before3 = cursorIsBefore(cur2, cur3); + return cur1before2 && cur2before3; + } + function lineLength(cm, lineNum) { + return cm.getLine(lineNum).length; + } + function reverse(s){ + return s.split('').reverse().join(''); + } + function trim(s) { + if (s.trim) { + return s.trim(); + } + return s.replace(/^\s+|\s+$/g, ''); + } + function escapeRegex(s) { + return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1'); + } + function extendLineToColumn(cm, lineNum, column) { + var endCh = lineLength(cm, lineNum); + var spaces = new Array(column-endCh+1).join(' '); + cm.setCursor(Pos(lineNum, endCh)); + cm.replaceRange(spaces, cm.getCursor()); + } + // This functions selects a rectangular block + // of text with selectionEnd as any of its corner + // Height of block: + // Difference in selectionEnd.line and first/last selection.line + // Width of the block: + // Distance between selectionEnd.ch and any(first considered here) selection.ch + function selectBlock(cm, selectionEnd) { + var selections = [], ranges = cm.listSelections(); + var head = copyCursor(cm.clipPos(selectionEnd)); + var isClipped = !cursorEqual(selectionEnd, head); + var curHead = cm.getCursor('head'); + var primIndex = getIndex(ranges, curHead); + var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor); + var max = ranges.length - 1; + var index = max - primIndex > primIndex ? max : 0; + var base = ranges[index].anchor; + + var firstLine = Math.min(base.line, head.line); + var lastLine = Math.max(base.line, head.line); + var baseCh = base.ch, headCh = head.ch; + + var dir = ranges[index].head.ch - baseCh; + var newDir = headCh - baseCh; + if (dir > 0 && newDir <= 0) { + baseCh++; + if (!isClipped) { headCh--; } + } else if (dir < 0 && newDir >= 0) { + baseCh--; + if (!wasClipped) { headCh++; } + } else if (dir < 0 && newDir == -1) { + baseCh--; + headCh++; + } + for (var line = firstLine; line <= lastLine; line++) { + var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)}; + selections.push(range); + } + primIndex = head.line == lastLine ? selections.length - 1 : 0; + cm.setSelections(selections, primIndex); + selectionEnd.ch = headCh; + base.ch = baseCh; + return base; + } + // getIndex returns the index of the cursor in the selections. + function getIndex(ranges, cursor, end) { + for (var i = 0; i < ranges.length; i++) { + var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor); + var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor); + if (atAnchor || atHead) { + return i; + } + } + return -1; + } + function getSelectedAreaRange(cm, vim) { + var lastSelection = vim.lastSelection; + var getCurrentSelectedAreaRange = function() { + var selections = cm.listSelections(); + var start = selections[0]; + var end = selections[selections.length-1]; + var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; + var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; + return [selectionStart, selectionEnd]; + }; + var getLastSelectedAreaRange = function() { + var selectionStart = cm.getCursor(); + var selectionEnd = cm.getCursor(); + var block = lastSelection.visualBlock; + if (block) { + var width = block.width; + var height = block.height; + selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width); + var selections = []; + // selectBlock creates a 'proper' rectangular block. + // We do not want that in all cases, so we manually set selections. + for (var i = selectionStart.line; i < selectionEnd.line; i++) { + var anchor = Pos(i, selectionStart.ch); + var head = Pos(i, selectionEnd.ch); + var range = {anchor: anchor, head: head}; + selections.push(range); + } + cm.setSelections(selections); + } else { + var start = lastSelection.curStartMark.find(); + var end = lastSelection.curEndMark.find(); + var line = end.line - start.line; + var ch = end.ch - start.ch; + selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch}; + if (lastSelection.visualLine) { + selectionStart = Pos(selectionStart.line, 0); + selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line)); + } + cm.setSelection(selectionStart, selectionEnd); + } + return [selectionStart, selectionEnd]; + }; + if (!vim.visualMode) { + // In case of replaying the action. + return getLastSelectedAreaRange(); + } else { + return getCurrentSelectedAreaRange(); + } + } + function updateLastSelection(cm, vim, selectionStart, selectionEnd) { + if (!selectionStart || !selectionEnd) { + selectionStart = vim.marks['<'].find() || cm.getCursor('anchor'); + selectionEnd = vim.marks['>'].find() || cm.getCursor('head'); + } + // To accommodate the effect of lastPastedText in the last selection + if (vim.lastPastedText) { + selectionEnd = cm.posFromIndex(cm.indexFromPos(selectionStart) + vim.lastPastedText.length); + vim.lastPastedText = null; + } + var ranges = cm.listSelections(); + // This check ensures to set the cursor + // position where we left off in previous selection + var swap = getIndex(ranges, selectionStart, 'head') > -1; + if (vim.visualBlock) { + var height = Math.abs(selectionStart.line - selectionEnd.line)+1; + var width = Math.abs(selectionStart.ch - selectionEnd.ch); + var block = {height: height, width: width}; + } + // can't use selection state here because yank has already reset its cursor + // Also, Bookmarks make the visual selections robust to edit operations + vim.lastSelection = {'curStartMark': cm.setBookmark(swap ? selectionEnd : selectionStart), + 'curEndMark': cm.setBookmark(swap ? selectionStart : selectionEnd), + 'visualMode': vim.visualMode, + 'visualLine': vim.visualLine, + 'visualBlock': block}; + } + function expandSelection(cm, start, end) { + var head = cm.getCursor('head'); + var anchor = cm.getCursor('anchor'); + var tmp; + if (cursorIsBefore(end, start)) { + tmp = end; + end = start; + start = tmp; + } + if (cursorIsBefore(head, anchor)) { + head = cursorMin(start, head); + anchor = cursorMax(anchor, end); + } else { + anchor = cursorMin(start, anchor); + head = cursorMax(head, end); + } + return [anchor, head]; + } + function getHead(cm) { + var cur = cm.getCursor('head'); + if (cm.getSelection().length == 1) { + // Small corner case when only 1 character is selected. The "real" + // head is the left of head and anchor. + cur = cursorMin(cur, cm.getCursor('anchor')); + } + return cur; + } + + function exitVisualMode(cm) { + var vim = cm.state.vim; + var selectionStart = cm.getCursor('anchor'); + var selectionEnd = cm.getCursor('head'); + // hack to place the cursor at the right place + // in case of visual block + if (vim.visualBlock && (cursorIsBefore(selectionStart, selectionEnd))) { + selectionEnd.ch--; + } + updateLastSelection(cm, vim); + vim.visualMode = false; + vim.visualLine = false; + vim.visualBlock = false; + if (!cursorEqual(selectionStart, selectionEnd)) { + cm.setCursor(clipCursorToContent(cm, selectionEnd)); + } + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + if (vim.fakeCursor) { + vim.fakeCursor.clear(); + } + } + + // Remove any trailing newlines from the selection. For + // example, with the caret at the start of the last word on the line, + // 'dw' should word, but not the newline, while 'w' should advance the + // caret to the first character of the next line. + function clipToLine(cm, curStart, curEnd) { + var selection = cm.getRange(curStart, curEnd); + // Only clip if the selection ends with trailing newline + whitespace + if (/\n\s*$/.test(selection)) { + var lines = selection.split('\n'); + // We know this is all whitepsace. + lines.pop(); + + // Cases: + // 1. Last word is an empty line - do not clip the trailing '\n' + // 2. Last word is not an empty line - clip the trailing '\n' + var line; + // Find the line containing the last word, and clip all whitespace up + // to it. + for (var line = lines.pop(); lines.length > 0 && line && isWhiteSpaceString(line); line = lines.pop()) { + curEnd.line--; + curEnd.ch = 0; + } + // If the last word is not an empty line, clip an additional newline + if (line) { + curEnd.line--; + curEnd.ch = lineLength(cm, curEnd.line); + } else { + curEnd.ch = 0; + } + } + } + + // Expand the selection to line ends. + function expandSelectionToLine(_cm, curStart, curEnd) { + curStart.ch = 0; + curEnd.ch = 0; + curEnd.line++; + } + + function findFirstNonWhiteSpaceCharacter(text) { + if (!text) { + return 0; + } + var firstNonWS = text.search(/\S/); + return firstNonWS == -1 ? text.length : firstNonWS; + } + + function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) { + var cur = getHead(cm); + var line = cm.getLine(cur.line); + var idx = cur.ch; + + // Seek to first word or non-whitespace character, depending on if + // noSymbol is true. + var textAfterIdx = line.substring(idx); + var firstMatchedChar; + if (noSymbol) { + firstMatchedChar = textAfterIdx.search(/\w/); + } else { + firstMatchedChar = textAfterIdx.search(/\S/); + } + if (firstMatchedChar == -1) { + return null; + } + idx += firstMatchedChar; + textAfterIdx = line.substring(idx); + var textBeforeIdx = line.substring(0, idx); + + var matchRegex; + // Greedy matchers for the "word" we are trying to expand. + if (bigWord) { + matchRegex = /^\S+/; + } else { + if ((/\w/).test(line.charAt(idx))) { + matchRegex = /^\w+/; + } else { + matchRegex = /^[^\w\s]+/; + } + } + + var wordAfterRegex = matchRegex.exec(textAfterIdx); + var wordStart = idx; + var wordEnd = idx + wordAfterRegex[0].length; + // TODO: Find a better way to do this. It will be slow on very long lines. + var revTextBeforeIdx = reverse(textBeforeIdx); + var wordBeforeRegex = matchRegex.exec(revTextBeforeIdx); + if (wordBeforeRegex) { + wordStart -= wordBeforeRegex[0].length; + } + + if (inclusive) { + // If present, trim all whitespace after word. + // Otherwise, trim all whitespace before word. + var textAfterWordEnd = line.substring(wordEnd); + var whitespacesAfterWord = textAfterWordEnd.match(/^\s*/)[0].length; + if (whitespacesAfterWord > 0) { + wordEnd += whitespacesAfterWord; + } else { + var revTrim = revTextBeforeIdx.length - wordStart; + var textBeforeWordStart = revTextBeforeIdx.substring(revTrim); + var whitespacesBeforeWord = textBeforeWordStart.match(/^\s*/)[0].length; + wordStart -= whitespacesBeforeWord; + } + } + + return { start: Pos(cur.line, wordStart), + end: Pos(cur.line, wordEnd) }; + } + + function recordJumpPosition(cm, oldCur, newCur) { + if (!cursorEqual(oldCur, newCur)) { + vimGlobalState.jumpList.add(cm, oldCur, newCur); + } + } + + function recordLastCharacterSearch(increment, args) { + vimGlobalState.lastChararacterSearch.increment = increment; + vimGlobalState.lastChararacterSearch.forward = args.forward; + vimGlobalState.lastChararacterSearch.selectedCharacter = args.selectedCharacter; + } + + var symbolToMode = { + '(': 'bracket', ')': 'bracket', '{': 'bracket', '}': 'bracket', + '[': 'section', ']': 'section', + '*': 'comment', '/': 'comment', + 'm': 'method', 'M': 'method', + '#': 'preprocess' + }; + var findSymbolModes = { + bracket: { + isComplete: function(state) { + if (state.nextCh === state.symb) { + state.depth++; + if (state.depth >= 1)return true; + } else if (state.nextCh === state.reverseSymb) { + state.depth--; + } + return false; + } + }, + section: { + init: function(state) { + state.curMoveThrough = true; + state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}'; + }, + isComplete: function(state) { + return state.index === 0 && state.nextCh === state.symb; + } + }, + comment: { + isComplete: function(state) { + var found = state.lastCh === '*' && state.nextCh === '/'; + state.lastCh = state.nextCh; + return found; + } + }, + // TODO: The original Vim implementation only operates on level 1 and 2. + // The current implementation doesn't check for code block level and + // therefore it operates on any levels. + method: { + init: function(state) { + state.symb = (state.symb === 'm' ? '{' : '}'); + state.reverseSymb = state.symb === '{' ? '}' : '{'; + }, + isComplete: function(state) { + if (state.nextCh === state.symb)return true; + return false; + } + }, + preprocess: { + init: function(state) { + state.index = 0; + }, + isComplete: function(state) { + if (state.nextCh === '#') { + var token = state.lineText.match(/#(\w+)/)[1]; + if (token === 'endif') { + if (state.forward && state.depth === 0) { + return true; + } + state.depth++; + } else if (token === 'if') { + if (!state.forward && state.depth === 0) { + return true; + } + state.depth--; + } + if (token === 'else' && state.depth === 0)return true; + } + return false; + } + } + }; + function findSymbol(cm, repeat, forward, symb) { + var cur = copyCursor(cm.getCursor()); + var increment = forward ? 1 : -1; + var endLine = forward ? cm.lineCount() : -1; + var curCh = cur.ch; + var line = cur.line; + var lineText = cm.getLine(line); + var state = { + lineText: lineText, + nextCh: lineText.charAt(curCh), + lastCh: null, + index: curCh, + symb: symb, + reverseSymb: (forward ? { ')': '(', '}': '{' } : { '(': ')', '{': '}' })[symb], + forward: forward, + depth: 0, + curMoveThrough: false + }; + var mode = symbolToMode[symb]; + if (!mode)return cur; + var init = findSymbolModes[mode].init; + var isComplete = findSymbolModes[mode].isComplete; + if (init) { init(state); } + while (line !== endLine && repeat) { + state.index += increment; + state.nextCh = state.lineText.charAt(state.index); + if (!state.nextCh) { + line += increment; + state.lineText = cm.getLine(line) || ''; + if (increment > 0) { + state.index = 0; + } else { + var lineLen = state.lineText.length; + state.index = (lineLen > 0) ? (lineLen-1) : 0; + } + state.nextCh = state.lineText.charAt(state.index); + } + if (isComplete(state)) { + cur.line = line; + cur.ch = state.index; + repeat--; + } + } + if (state.nextCh || state.curMoveThrough) { + return Pos(line, state.index); + } + return cur; + } + + /* + * Returns the boundaries of the next word. If the cursor in the middle of + * the word, then returns the boundaries of the current word, starting at + * the cursor. If the cursor is at the start/end of a word, and we are going + * forward/backward, respectively, find the boundaries of the next word. + * + * @param {CodeMirror} cm CodeMirror object. + * @param {Cursor} cur The cursor position. + * @param {boolean} forward True to search forward. False to search + * backward. + * @param {boolean} bigWord True if punctuation count as part of the word. + * False if only [a-zA-Z0-9] characters count as part of the word. + * @param {boolean} emptyLineIsWord True if empty lines should be treated + * as words. + * @return {Object{from:number, to:number, line: number}} The boundaries of + * the word, or null if there are no more words. + */ + function findWord(cm, cur, forward, bigWord, emptyLineIsWord) { + var lineNum = cur.line; + var pos = cur.ch; + var line = cm.getLine(lineNum); + var dir = forward ? 1 : -1; + var regexps = bigWord ? bigWordRegexp : wordRegexp; + + if (emptyLineIsWord && line == '') { + lineNum += dir; + line = cm.getLine(lineNum); + if (!isLine(cm, lineNum)) { + return null; + } + pos = (forward) ? 0 : line.length; + } + + while (true) { + if (emptyLineIsWord && line == '') { + return { from: 0, to: 0, line: lineNum }; + } + var stop = (dir > 0) ? line.length : -1; + var wordStart = stop, wordEnd = stop; + // Find bounds of next word. + while (pos != stop) { + var foundWord = false; + for (var i = 0; i < regexps.length && !foundWord; ++i) { + if (regexps[i].test(line.charAt(pos))) { + wordStart = pos; + // Advance to end of word. + while (pos != stop && regexps[i].test(line.charAt(pos))) { + pos += dir; + } + wordEnd = pos; + foundWord = wordStart != wordEnd; + if (wordStart == cur.ch && lineNum == cur.line && + wordEnd == wordStart + dir) { + // We started at the end of a word. Find the next one. + continue; + } else { + return { + from: Math.min(wordStart, wordEnd + 1), + to: Math.max(wordStart, wordEnd), + line: lineNum }; + } + } + } + if (!foundWord) { + pos += dir; + } + } + // Advance to next/prev line. + lineNum += dir; + if (!isLine(cm, lineNum)) { + return null; + } + line = cm.getLine(lineNum); + pos = (dir > 0) ? 0 : line.length; + } + // Should never get here. + throw new Error('The impossible happened.'); + } + + /** + * @param {CodeMirror} cm CodeMirror object. + * @param {int} repeat Number of words to move past. + * @param {boolean} forward True to search forward. False to search + * backward. + * @param {boolean} wordEnd True to move to end of word. False to move to + * beginning of word. + * @param {boolean} bigWord True if punctuation count as part of the word. + * False if only alphabet characters count as part of the word. + * @return {Cursor} The position the cursor should move to. + */ + function moveToWord(cm, repeat, forward, wordEnd, bigWord) { + var cur = cm.getCursor(); + var curStart = copyCursor(cur); + var words = []; + if (forward && !wordEnd || !forward && wordEnd) { + repeat++; + } + // For 'e', empty lines are not considered words, go figure. + var emptyLineIsWord = !(forward && wordEnd); + for (var i = 0; i < repeat; i++) { + var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord); + if (!word) { + var eodCh = lineLength(cm, cm.lastLine()); + words.push(forward + ? {line: cm.lastLine(), from: eodCh, to: eodCh} + : {line: 0, from: 0, to: 0}); + break; + } + words.push(word); + cur = Pos(word.line, forward ? (word.to - 1) : word.from); + } + var shortCircuit = words.length != repeat; + var firstWord = words[0]; + var lastWord = words.pop(); + if (forward && !wordEnd) { + // w + if (!shortCircuit && (firstWord.from != curStart.ch || firstWord.line != curStart.line)) { + // We did not start in the middle of a word. Discard the extra word at the end. + lastWord = words.pop(); + } + return Pos(lastWord.line, lastWord.from); + } else if (forward && wordEnd) { + return Pos(lastWord.line, lastWord.to - 1); + } else if (!forward && wordEnd) { + // ge + if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) { + // We did not start in the middle of a word. Discard the extra word at the end. + lastWord = words.pop(); + } + return Pos(lastWord.line, lastWord.to); + } else { + // b + return Pos(lastWord.line, lastWord.from); + } + } + + function moveToCharacter(cm, repeat, forward, character) { + var cur = cm.getCursor(); + var start = cur.ch; + var idx; + for (var i = 0; i < repeat; i ++) { + var line = cm.getLine(cur.line); + idx = charIdxInLine(start, line, character, forward, true); + if (idx == -1) { + return null; + } + start = idx; + } + return Pos(cm.getCursor().line, idx); + } + + function moveToColumn(cm, repeat) { + // repeat is always >= 1, so repeat - 1 always corresponds + // to the column we want to go to. + var line = cm.getCursor().line; + return clipCursorToContent(cm, Pos(line, repeat - 1)); + } + + function updateMark(cm, vim, markName, pos) { + if (!inArray(markName, validMarks)) { + return; + } + if (vim.marks[markName]) { + vim.marks[markName].clear(); + } + vim.marks[markName] = cm.setBookmark(pos); + } + + function charIdxInLine(start, line, character, forward, includeChar) { + // Search for char in line. + // motion_options: {forward, includeChar} + // If includeChar = true, include it too. + // If forward = true, search forward, else search backwards. + // If char is not found on this line, do nothing + var idx; + if (forward) { + idx = line.indexOf(character, start + 1); + if (idx != -1 && !includeChar) { + idx -= 1; + } + } else { + idx = line.lastIndexOf(character, start - 1); + if (idx != -1 && !includeChar) { + idx += 1; + } + } + return idx; + } + + // TODO: perhaps this finagling of start and end positions belonds + // in codmirror/replaceRange? + function selectCompanionObject(cm, symb, inclusive) { + var cur = getHead(cm), start, end; + + var bracketRegexp = ({ + '(': /[()]/, ')': /[()]/, + '[': /[[\]]/, ']': /[[\]]/, + '{': /[{}]/, '}': /[{}]/})[symb]; + var openSym = ({ + '(': '(', ')': '(', + '[': '[', ']': '[', + '{': '{', '}': '{'})[symb]; + var curChar = cm.getLine(cur.line).charAt(cur.ch); + // Due to the behavior of scanForBracket, we need to add an offset if the + // cursor is on a matching open bracket. + var offset = curChar === openSym ? 1 : 0; + + start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, null, {'bracketRegex': bracketRegexp}); + end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, null, {'bracketRegex': bracketRegexp}); + + if (!start || !end) { + return { start: cur, end: cur }; + } + + start = start.pos; + end = end.pos; + + if ((start.line == end.line && start.ch > end.ch) + || (start.line > end.line)) { + var tmp = start; + start = end; + end = tmp; + } + + if (inclusive) { + end.ch += 1; + } else { + start.ch += 1; + } + + return { start: start, end: end }; + } + + // Takes in a symbol and a cursor and tries to simulate text objects that + // have identical opening and closing symbols + // TODO support across multiple lines + function findBeginningAndEnd(cm, symb, inclusive) { + var cur = copyCursor(getHead(cm)); + var line = cm.getLine(cur.line); + var chars = line.split(''); + var start, end, i, len; + var firstIndex = chars.indexOf(symb); + + // the decision tree is to always look backwards for the beginning first, + // but if the cursor is in front of the first instance of the symb, + // then move the cursor forward + if (cur.ch < firstIndex) { + cur.ch = firstIndex; + // Why is this line even here??? + // cm.setCursor(cur.line, firstIndex+1); + } + // otherwise if the cursor is currently on the closing symbol + else if (firstIndex < cur.ch && chars[cur.ch] == symb) { + end = cur.ch; // assign end to the current cursor + --cur.ch; // make sure to look backwards + } + + // if we're currently on the symbol, we've got a start + if (chars[cur.ch] == symb && !end) { + start = cur.ch + 1; // assign start to ahead of the cursor + } else { + // go backwards to find the start + for (i = cur.ch; i > -1 && !start; i--) { + if (chars[i] == symb) { + start = i + 1; + } + } + } + + // look forwards for the end symbol + if (start && !end) { + for (i = start, len = chars.length; i < len && !end; i++) { + if (chars[i] == symb) { + end = i; + } + } + } + + // nothing found + if (!start || !end) { + return { start: cur, end: cur }; + } + + // include the symbols + if (inclusive) { + --start; ++end; + } + + return { + start: Pos(cur.line, start), + end: Pos(cur.line, end) + }; + } + + // Search functions + defineOption('pcre', true, 'boolean'); + function SearchState() {} + SearchState.prototype = { + getQuery: function() { + return vimGlobalState.query; + }, + setQuery: function(query) { + vimGlobalState.query = query; + }, + getOverlay: function() { + return this.searchOverlay; + }, + setOverlay: function(overlay) { + this.searchOverlay = overlay; + }, + isReversed: function() { + return vimGlobalState.isReversed; + }, + setReversed: function(reversed) { + vimGlobalState.isReversed = reversed; + } + }; + function getSearchState(cm) { + var vim = cm.state.vim; + return vim.searchState_ || (vim.searchState_ = new SearchState()); + } + function dialog(cm, template, shortText, onClose, options) { + if (cm.openDialog) { + cm.openDialog(template, onClose, { bottom: true, value: options.value, + onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp }); + } + else { + onClose(prompt(shortText, '')); + } + } + function splitBySlash(argString) { + var slashes = findUnescapedSlashes(argString) || []; + if (!slashes.length) return []; + var tokens = []; + // in case of strings like foo/bar + if (slashes[0] !== 0) return; + for (var i = 0; i < slashes.length; i++) { + if (typeof slashes[i] == 'number') + tokens.push(argString.substring(slashes[i] + 1, slashes[i+1])); + } + return tokens; + } + + function findUnescapedSlashes(str) { + var escapeNextChar = false; + var slashes = []; + for (var i = 0; i < str.length; i++) { + var c = str.charAt(i); + if (!escapeNextChar && c == '/') { + slashes.push(i); + } + escapeNextChar = !escapeNextChar && (c == '\\'); + } + return slashes; + } + + // Translates a search string from ex (vim) syntax into javascript form. + function translateRegex(str) { + // When these match, add a '\' if unescaped or remove one if escaped. + var specials = '|(){'; + // Remove, but never add, a '\' for these. + var unescape = '}'; + var escapeNextChar = false; + var out = []; + for (var i = -1; i < str.length; i++) { + var c = str.charAt(i) || ''; + var n = str.charAt(i+1) || ''; + var specialComesNext = (n && specials.indexOf(n) != -1); + if (escapeNextChar) { + if (c !== '\\' || !specialComesNext) { + out.push(c); + } + escapeNextChar = false; + } else { + if (c === '\\') { + escapeNextChar = true; + // Treat the unescape list as special for removing, but not adding '\'. + if (n && unescape.indexOf(n) != -1) { + specialComesNext = true; + } + // Not passing this test means removing a '\'. + if (!specialComesNext || n === '\\') { + out.push(c); + } + } else { + out.push(c); + if (specialComesNext && n !== '\\') { + out.push('\\'); + } + } + } + } + return out.join(''); + } + + // Translates the replace part of a search and replace from ex (vim) syntax into + // javascript form. Similar to translateRegex, but additionally fixes back references + // (translates '\[0..9]' to '$[0..9]') and follows different rules for escaping '$'. + function translateRegexReplace(str) { + var escapeNextChar = false; + var out = []; + for (var i = -1; i < str.length; i++) { + var c = str.charAt(i) || ''; + var n = str.charAt(i+1) || ''; + if (escapeNextChar) { + // At any point in the loop, escapeNextChar is true if the previous + // character was a '\' and was not escaped. + out.push(c); + escapeNextChar = false; + } else { + if (c === '\\') { + escapeNextChar = true; + if ((isNumber(n) || n === '$')) { + out.push('$'); + } else if (n !== '/' && n !== '\\') { + out.push('\\'); + } + } else { + if (c === '$') { + out.push('$'); + } + out.push(c); + if (n === '/') { + out.push('\\'); + } + } + } + } + return out.join(''); + } + + // Unescape \ and / in the replace part, for PCRE mode. + function unescapeRegexReplace(str) { + var stream = new CodeMirror.StringStream(str); + var output = []; + while (!stream.eol()) { + // Search for \. + while (stream.peek() && stream.peek() != '\\') { + output.push(stream.next()); + } + if (stream.match('\\/', true)) { + // \/ => / + output.push('/'); + } else if (stream.match('\\\\', true)) { + // \\ => \ + output.push('\\'); + } else { + // Don't change anything + output.push(stream.next()); + } + } + return output.join(''); + } + + /** + * Extract the regular expression from the query and return a Regexp object. + * Returns null if the query is blank. + * If ignoreCase is passed in, the Regexp object will have the 'i' flag set. + * If smartCase is passed in, and the query contains upper case letters, + * then ignoreCase is overridden, and the 'i' flag will not be set. + * If the query contains the /i in the flag part of the regular expression, + * then both ignoreCase and smartCase are ignored, and 'i' will be passed + * through to the Regex object. + */ + function parseQuery(query, ignoreCase, smartCase) { + // First update the last search register + var lastSearchRegister = vimGlobalState.registerController.getRegister('/'); + lastSearchRegister.setText(query); + // Check if the query is already a regex. + if (query instanceof RegExp) { return query; } + // First try to extract regex + flags from the input. If no flags found, + // extract just the regex. IE does not accept flags directly defined in + // the regex string in the form /regex/flags + var slashes = findUnescapedSlashes(query); + var regexPart; + var forceIgnoreCase; + if (!slashes.length) { + // Query looks like 'regexp' + regexPart = query; + } else { + // Query looks like 'regexp/...' + regexPart = query.substring(0, slashes[0]); + var flagsPart = query.substring(slashes[0]); + forceIgnoreCase = (flagsPart.indexOf('i') != -1); + } + if (!regexPart) { + return null; + } + if (!getOption('pcre')) { + regexPart = translateRegex(regexPart); + } + if (smartCase) { + ignoreCase = (/^[^A-Z]*$/).test(regexPart); + } + var regexp = new RegExp(regexPart, + (ignoreCase || forceIgnoreCase) ? 'i' : undefined); + return regexp; + } + function showConfirm(cm, text) { + if (cm.openNotification) { + cm.openNotification('' + text + '', + {bottom: true, duration: 5000}); + } else { + alert(text); + } + } + function makePrompt(prefix, desc) { + var raw = ''; + if (prefix) { + raw += '' + prefix + ''; + } + raw += ' ' + + ''; + if (desc) { + raw += ''; + raw += desc; + raw += ''; + } + return raw; + } + var searchPromptDesc = '(Javascript regexp)'; + function showPrompt(cm, options) { + var shortText = (options.prefix || '') + ' ' + (options.desc || ''); + var prompt = makePrompt(options.prefix, options.desc); + dialog(cm, prompt, shortText, options.onClose, options); + } + function regexEqual(r1, r2) { + if (r1 instanceof RegExp && r2 instanceof RegExp) { + var props = ['global', 'multiline', 'ignoreCase', 'source']; + for (var i = 0; i < props.length; i++) { + var prop = props[i]; + if (r1[prop] !== r2[prop]) { + return false; + } + } + return true; + } + return false; + } + // Returns true if the query is valid. + function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) { + if (!rawQuery) { + return; + } + var state = getSearchState(cm); + var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase); + if (!query) { + return; + } + highlightSearchMatches(cm, query); + if (regexEqual(query, state.getQuery())) { + return query; + } + state.setQuery(query); + return query; + } + function searchOverlay(query) { + if (query.source.charAt(0) == '^') { + var matchSol = true; + } + return { + token: function(stream) { + if (matchSol && !stream.sol()) { + stream.skipToEnd(); + return; + } + var match = stream.match(query, false); + if (match) { + if (match[0].length == 0) { + // Matched empty string, skip to next. + stream.next(); + return 'searching'; + } + if (!stream.sol()) { + // Backtrack 1 to match \b + stream.backUp(1); + if (!query.exec(stream.next() + match[0])) { + stream.next(); + return null; + } + } + stream.match(query); + return 'searching'; + } + while (!stream.eol()) { + stream.next(); + if (stream.match(query, false)) break; + } + }, + query: query + }; + } + function highlightSearchMatches(cm, query) { + var overlay = getSearchState(cm).getOverlay(); + if (!overlay || query != overlay.query) { + if (overlay) { + cm.removeOverlay(overlay); + } + overlay = searchOverlay(query); + cm.addOverlay(overlay); + getSearchState(cm).setOverlay(overlay); + } + } + function findNext(cm, prev, query, repeat) { + if (repeat === undefined) { repeat = 1; } + return cm.operation(function() { + var pos = cm.getCursor(); + var cursor = cm.getSearchCursor(query, pos); + for (var i = 0; i < repeat; i++) { + var found = cursor.find(prev); + if (i == 0 && found && cursorEqual(cursor.from(), pos)) { found = cursor.find(prev); } + if (!found) { + // SearchCursor may have returned null because it hit EOF, wrap + // around and try again. + cursor = cm.getSearchCursor(query, + (prev) ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) ); + if (!cursor.find(prev)) { + return; + } + } + } + return cursor.from(); + }); + } + function clearSearchHighlight(cm) { + cm.removeOverlay(getSearchState(cm).getOverlay()); + getSearchState(cm).setOverlay(null); + } + /** + * Check if pos is in the specified range, INCLUSIVE. + * Range can be specified with 1 or 2 arguments. + * If the first range argument is an array, treat it as an array of line + * numbers. Match pos against any of the lines. + * If the first range argument is a number, + * if there is only 1 range argument, check if pos has the same line + * number + * if there are 2 range arguments, then check if pos is in between the two + * range arguments. + */ + function isInRange(pos, start, end) { + if (typeof pos != 'number') { + // Assume it is a cursor position. Get the line number. + pos = pos.line; + } + if (start instanceof Array) { + return inArray(pos, start); + } else { + if (end) { + return (pos >= start && pos <= end); + } else { + return pos == start; + } + } + } + function getUserVisibleLines(cm) { + var renderer = cm.ace.renderer; + return { + top: renderer.getFirstFullyVisibleRow(), + bottom: renderer.getLastFullyVisibleRow() + } + var scrollInfo = cm.getScrollInfo(); + var occludeToleranceTop = 6; + var occludeToleranceBottom = 10; + var from = cm.coordsChar({left:0, top: occludeToleranceTop + scrollInfo.top}, 'local'); + var bottomY = scrollInfo.clientHeight - occludeToleranceBottom + scrollInfo.top; + var to = cm.coordsChar({left:0, top: bottomY}, 'local'); + return {top: from.line, bottom: to.line}; + } + + // Ex command handling + // Care must be taken when adding to the default Ex command map. For any + // pair of commands that have a shared prefix, at least one of their + // shortNames must not match the prefix of the other command. + var defaultExCommandMap = [ + { name: 'map' }, + { name: 'imap', shortName: 'im' }, + { name: 'nmap', shortName: 'nm' }, + { name: 'vmap', shortName: 'vm' }, + { name: 'unmap' }, + { name: 'write', shortName: 'w' }, + { name: 'undo', shortName: 'u' }, + { name: 'redo', shortName: 'red' }, + { name: 'set', shortName: 'set' }, + { name: 'sort', shortName: 'sor' }, + { name: 'substitute', shortName: 's', possiblyAsync: true }, + { name: 'nohlsearch', shortName: 'noh' }, + { name: 'delmarks', shortName: 'delm' }, + { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true }, + { name: 'global', shortName: 'g' } + ]; + var ExCommandDispatcher = function() { + this.buildCommandMap_(); + }; + ExCommandDispatcher.prototype = { + processCommand: function(cm, input, opt_params) { + var vim = cm.state.vim; + var commandHistoryRegister = vimGlobalState.registerController.getRegister(':'); + var previousCommand = commandHistoryRegister.toString(); + if (vim.visualMode) { + exitVisualMode(cm); + } + var inputStream = new CodeMirror.StringStream(input); + // update ": with the latest command whether valid or invalid + commandHistoryRegister.setText(input); + var params = opt_params || {}; + params.input = input; + try { + this.parseInput_(cm, inputStream, params); + } catch(e) { + showConfirm(cm, e); + throw e; + } + var command; + var commandName; + if (!params.commandName) { + // If only a line range is defined, move to the line. + if (params.line !== undefined) { + commandName = 'move'; + } + } else { + command = this.matchCommand_(params.commandName); + if (command) { + commandName = command.name; + if (command.excludeFromCommandHistory) { + commandHistoryRegister.setText(previousCommand); + } + this.parseCommandArgs_(inputStream, params, command); + if (command.type == 'exToKey') { + // Handle Ex to Key mapping. + for (var i = 0; i < command.toKeys.length; i++) { + CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping'); + } + return; + } else if (command.type == 'exToEx') { + // Handle Ex to Ex mapping. + this.processCommand(cm, command.toInput); + return; + } + } + } + if (!commandName) { + showConfirm(cm, 'Not an editor command ":' + input + '"'); + return; + } + try { + exCommands[commandName](cm, params); + // Possibly asynchronous commands (e.g. substitute, which might have a + // user confirmation), are responsible for calling the callback when + // done. All others have it taken care of for them here. + if ((!command || !command.possiblyAsync) && params.callback) { + params.callback(); + } + } catch(e) { + showConfirm(cm, e); + throw e; + } + }, + parseInput_: function(cm, inputStream, result) { + inputStream.eatWhile(':'); + // Parse range. + if (inputStream.eat('%')) { + result.line = cm.firstLine(); + result.lineEnd = cm.lastLine(); + } else { + result.line = this.parseLineSpec_(cm, inputStream); + if (result.line !== undefined && inputStream.eat(',')) { + result.lineEnd = this.parseLineSpec_(cm, inputStream); + } + } + + // Parse command name. + var commandMatch = inputStream.match(/^(\w+)/); + if (commandMatch) { + result.commandName = commandMatch[1]; + } else { + result.commandName = inputStream.match(/.*/)[0]; + } + + return result; + }, + parseLineSpec_: function(cm, inputStream) { + var numberMatch = inputStream.match(/^(\d+)/); + if (numberMatch) { + return parseInt(numberMatch[1], 10) - 1; + } + switch (inputStream.next()) { + case '.': + return cm.getCursor().line; + case '$': + return cm.lastLine(); + case '\'': + var mark = cm.state.vim.marks[inputStream.next()]; + if (mark && mark.find()) { + return mark.find().line; + } + throw new Error('Mark not set'); + default: + inputStream.backUp(1); + return undefined; + } + }, + parseCommandArgs_: function(inputStream, params, command) { + if (inputStream.eol()) { + return; + } + params.argString = inputStream.match(/.*/)[0]; + // Parse command-line arguments + var delim = command.argDelimiter || /\s+/; + var args = trim(params.argString).split(delim); + if (args.length && args[0]) { + params.args = args; + } + }, + matchCommand_: function(commandName) { + // Return the command in the command map that matches the shortest + // prefix of the passed in command name. The match is guaranteed to be + // unambiguous if the defaultExCommandMap's shortNames are set up + // correctly. (see @code{defaultExCommandMap}). + for (var i = commandName.length; i > 0; i--) { + var prefix = commandName.substring(0, i); + if (this.commandMap_[prefix]) { + var command = this.commandMap_[prefix]; + if (command.name.indexOf(commandName) === 0) { + return command; + } + } + } + return null; + }, + buildCommandMap_: function() { + this.commandMap_ = {}; + for (var i = 0; i < defaultExCommandMap.length; i++) { + var command = defaultExCommandMap[i]; + var key = command.shortName || command.name; + this.commandMap_[key] = command; + } + }, + map: function(lhs, rhs, ctx) { + if (lhs != ':' && lhs.charAt(0) == ':') { + if (ctx) { throw Error('Mode not supported for ex mappings'); } + var commandName = lhs.substring(1); + if (rhs != ':' && rhs.charAt(0) == ':') { + // Ex to Ex mapping + this.commandMap_[commandName] = { + name: commandName, + type: 'exToEx', + toInput: rhs.substring(1), + user: true + }; + } else { + // Ex to key mapping + this.commandMap_[commandName] = { + name: commandName, + type: 'exToKey', + toKeys: rhs, + user: true + }; + } + } else { + if (rhs != ':' && rhs.charAt(0) == ':') { + // Key to Ex mapping. + var mapping = { + keys: lhs, + type: 'keyToEx', + exArgs: { input: rhs.substring(1) }, + user: true}; + if (ctx) { mapping.context = ctx; } + defaultKeymap.unshift(mapping); + } else { + // Key to key mapping + var mapping = { + keys: lhs, + type: 'keyToKey', + toKeys: rhs, + user: true + }; + if (ctx) { mapping.context = ctx; } + defaultKeymap.unshift(mapping); + } + } + }, + unmap: function(lhs, ctx) { + if (lhs != ':' && lhs.charAt(0) == ':') { + // Ex to Ex or Ex to key mapping + if (ctx) { throw Error('Mode not supported for ex mappings'); } + var commandName = lhs.substring(1); + if (this.commandMap_[commandName] && this.commandMap_[commandName].user) { + delete this.commandMap_[commandName]; + return; + } + } else { + // Key to Ex or key to key mapping + var keys = lhs; + for (var i = 0; i < defaultKeymap.length; i++) { + if (keys == defaultKeymap[i].keys + && defaultKeymap[i].context === ctx + && defaultKeymap[i].user) { + defaultKeymap.splice(i, 1); + return; + } + } + } + throw Error('No such mapping.'); + } + }; + + var exCommands = { + map: function(cm, params, ctx) { + var mapArgs = params.args; + if (!mapArgs || mapArgs.length < 2) { + if (cm) { + showConfirm(cm, 'Invalid mapping: ' + params.input); + } + return; + } + exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx); + }, + imap: function(cm, params) { this.map(cm, params, 'insert'); }, + nmap: function(cm, params) { this.map(cm, params, 'normal'); }, + vmap: function(cm, params) { this.map(cm, params, 'visual'); }, + unmap: function(cm, params, ctx) { + var mapArgs = params.args; + if (!mapArgs || mapArgs.length < 1) { + if (cm) { + showConfirm(cm, 'No such mapping: ' + params.input); + } + return; + } + exCommandDispatcher.unmap(mapArgs[0], ctx); + }, + move: function(cm, params) { + commandDispatcher.processCommand(cm, cm.state.vim, { + type: 'motion', + motion: 'moveToLineOrEdgeOfDocument', + motionArgs: { forward: false, explicitRepeat: true, + linewise: true }, + repeatOverride: params.line+1}); + }, + set: function(cm, params) { + var setArgs = params.args; + if (!setArgs || setArgs.length < 1) { + if (cm) { + showConfirm(cm, 'Invalid mapping: ' + params.input); + } + return; + } + var expr = setArgs[0].split('='); + var optionName = expr[0]; + var value = expr[1]; + var forceGet = false; + + if (optionName.charAt(optionName.length - 1) == '?') { + // If post-fixed with ?, then the set is actually a get. + if (value) { throw Error('Trailing characters: ' + params.argString); } + optionName = optionName.substring(0, optionName.length - 1); + forceGet = true; + } + if (value === undefined && optionName.substring(0, 2) == 'no') { + // To set boolean options to false, the option name is prefixed with + // 'no'. + optionName = optionName.substring(2); + value = false; + } + var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean'; + if (optionIsBoolean && value == undefined) { + // Calling set with a boolean option sets it to true. + value = true; + } + if (!optionIsBoolean && !value || forceGet) { + var oldValue = getOption(optionName); + // If no value is provided, then we assume this is a get. + if (oldValue === true || oldValue === false) { + showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName); + } else { + showConfirm(cm, ' ' + optionName + '=' + oldValue); + } + } else { + setOption(optionName, value, cm); + } + }, + registers: function(cm,params) { + var regArgs = params.args; + var registers = vimGlobalState.registerController.registers; + var regInfo = '----------Registers----------

    '; + if (!regArgs) { + for (var registerName in registers) { + var text = registers[registerName].toString(); + if (text.length) { + regInfo += '"' + registerName + ' ' + text + '
    '; + } + } + } else { + var registerName; + regArgs = regArgs.join(''); + for (var i = 0; i < regArgs.length; i++) { + registerName = regArgs.charAt(i); + if (!vimGlobalState.registerController.isValidRegister(registerName)) { + continue; + } + var register = registers[registerName] || new Register(); + regInfo += '"' + registerName + ' ' + register.toString() + '
    '; + } + } + showConfirm(cm, regInfo); + }, + sort: function(cm, params) { + var reverse, ignoreCase, unique, number; + function parseArgs() { + if (params.argString) { + var args = new CodeMirror.StringStream(params.argString); + if (args.eat('!')) { reverse = true; } + if (args.eol()) { return; } + if (!args.eatSpace()) { return 'Invalid arguments'; } + var opts = args.match(/[a-z]+/); + if (opts) { + opts = opts[0]; + ignoreCase = opts.indexOf('i') != -1; + unique = opts.indexOf('u') != -1; + var decimal = opts.indexOf('d') != -1 && 1; + var hex = opts.indexOf('x') != -1 && 1; + var octal = opts.indexOf('o') != -1 && 1; + if (decimal + hex + octal > 1) { return 'Invalid arguments'; } + number = decimal && 'decimal' || hex && 'hex' || octal && 'octal'; + } + if (args.eatSpace() && args.match(/\/.*\//)) { 'patterns not supported'; } + } + } + var err = parseArgs(); + if (err) { + showConfirm(cm, err + ': ' + params.argString); + return; + } + var lineStart = params.line || cm.firstLine(); + var lineEnd = params.lineEnd || params.line || cm.lastLine(); + if (lineStart == lineEnd) { return; } + var curStart = Pos(lineStart, 0); + var curEnd = Pos(lineEnd, lineLength(cm, lineEnd)); + var text = cm.getRange(curStart, curEnd).split('\n'); + var numberRegex = (number == 'decimal') ? /(-?)([\d]+)/ : + (number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i : + (number == 'octal') ? /([0-7]+)/ : null; + var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null; + var numPart = [], textPart = []; + if (number) { + for (var i = 0; i < text.length; i++) { + if (numberRegex.exec(text[i])) { + numPart.push(text[i]); + } else { + textPart.push(text[i]); + } + } + } else { + textPart = text; + } + function compareFn(a, b) { + if (reverse) { var tmp; tmp = a; a = b; b = tmp; } + if (ignoreCase) { a = a.toLowerCase(); b = b.toLowerCase(); } + var anum = number && numberRegex.exec(a); + var bnum = number && numberRegex.exec(b); + if (!anum) { return a < b ? -1 : 1; } + anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix); + bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix); + return anum - bnum; + } + numPart.sort(compareFn); + textPart.sort(compareFn); + text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart); + if (unique) { // Remove duplicate lines + var textOld = text; + var lastLine; + text = []; + for (var i = 0; i < textOld.length; i++) { + if (textOld[i] != lastLine) { + text.push(textOld[i]); + } + lastLine = textOld[i]; + } + } + cm.replaceRange(text.join('\n'), curStart, curEnd); + }, + global: function(cm, params) { + // a global command is of the form + // :[range]g/pattern/[cmd] + // argString holds the string /pattern/[cmd] + var argString = params.argString; + if (!argString) { + showConfirm(cm, 'Regular Expression missing from global'); + return; + } + // range is specified here + var lineStart = (params.line !== undefined) ? params.line : cm.firstLine(); + var lineEnd = params.lineEnd || params.line || cm.lastLine(); + // get the tokens from argString + var tokens = splitBySlash(argString); + var regexPart = argString, cmd; + if (tokens.length) { + regexPart = tokens[0]; + cmd = tokens.slice(1, tokens.length).join('/'); + } + if (regexPart) { + // If regex part is empty, then use the previous query. Otherwise + // use the regex part as the new query. + try { + updateSearchQuery(cm, regexPart, true /** ignoreCase */, + true /** smartCase */); + } catch (e) { + showConfirm(cm, 'Invalid regex: ' + regexPart); + return; + } + } + // now that we have the regexPart, search for regex matches in the + // specified range of lines + var query = getSearchState(cm).getQuery(); + var matchedLines = [], content = ''; + for (var i = lineStart; i <= lineEnd; i++) { + var matched = query.test(cm.getLine(i)); + if (matched) { + matchedLines.push(i+1); + content+= cm.getLine(i) + '
    '; + } + } + // if there is no [cmd], just display the list of matched lines + if (!cmd) { + showConfirm(cm, content); + return; + } + var index = 0; + var nextCommand = function() { + if (index < matchedLines.length) { + var command = matchedLines[index] + cmd; + exCommandDispatcher.processCommand(cm, command, { + callback: nextCommand + }); + } + index++; + }; + nextCommand(); + }, + substitute: function(cm, params) { + if (!cm.getSearchCursor) { + throw new Error('Search feature not available. Requires searchcursor.js or ' + + 'any other getSearchCursor implementation.'); + } + var argString = params.argString; + var tokens = argString ? splitBySlash(argString) : []; + var regexPart, replacePart = '', trailing, flagsPart, count; + var confirm = false; // Whether to confirm each replace. + var global = false; // True to replace all instances on a line, false to replace only 1. + if (tokens.length) { + regexPart = tokens[0]; + replacePart = tokens[1]; + if (replacePart !== undefined) { + if (getOption('pcre')) { + replacePart = unescapeRegexReplace(replacePart); + } else { + replacePart = translateRegexReplace(replacePart); + } + vimGlobalState.lastSubstituteReplacePart = replacePart; + } + trailing = tokens[2] ? tokens[2].split(' ') : []; + } else { + // either the argString is empty or its of the form ' hello/world' + // actually splitBySlash returns a list of tokens + // only if the string starts with a '/' + if (argString && argString.length) { + showConfirm(cm, 'Substitutions should be of the form ' + + ':s/pattern/replace/'); + return; + } + } + // After the 3rd slash, we can have flags followed by a space followed + // by count. + if (trailing) { + flagsPart = trailing[0]; + count = parseInt(trailing[1]); + if (flagsPart) { + if (flagsPart.indexOf('c') != -1) { + confirm = true; + flagsPart.replace('c', ''); + } + if (flagsPart.indexOf('g') != -1) { + global = true; + flagsPart.replace('g', ''); + } + regexPart = regexPart + '/' + flagsPart; + } + } + if (regexPart) { + // If regex part is empty, then use the previous query. Otherwise use + // the regex part as the new query. + try { + updateSearchQuery(cm, regexPart, true /** ignoreCase */, + true /** smartCase */); + } catch (e) { + showConfirm(cm, 'Invalid regex: ' + regexPart); + return; + } + } + replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart; + if (replacePart === undefined) { + showConfirm(cm, 'No previous substitute regular expression'); + return; + } + var state = getSearchState(cm); + var query = state.getQuery(); + var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line; + var lineEnd = params.lineEnd || lineStart; + if (count) { + lineStart = lineEnd; + lineEnd = lineStart + count - 1; + } + var startPos = clipCursorToContent(cm, Pos(lineStart, 0)); + var cursor = cm.getSearchCursor(query, startPos); + doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback); + }, + redo: CodeMirror.commands.redo, + undo: CodeMirror.commands.undo, + write: function(cm) { + if (CodeMirror.commands.save) { + // If a save command is defined, call it. + CodeMirror.commands.save(cm); + } else { + // Saves to text area if no save command is defined. + cm.save(); + } + }, + nohlsearch: function(cm) { + clearSearchHighlight(cm); + }, + delmarks: function(cm, params) { + if (!params.argString || !trim(params.argString)) { + showConfirm(cm, 'Argument required'); + return; + } + + var state = cm.state.vim; + var stream = new CodeMirror.StringStream(trim(params.argString)); + while (!stream.eol()) { + stream.eatSpace(); + + // Record the streams position at the beginning of the loop for use + // in error messages. + var count = stream.pos; + + if (!stream.match(/[a-zA-Z]/, false)) { + showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); + return; + } + + var sym = stream.next(); + // Check if this symbol is part of a range + if (stream.match('-', true)) { + // This symbol is part of a range. + + // The range must terminate at an alphabetic character. + if (!stream.match(/[a-zA-Z]/, false)) { + showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); + return; + } + + var startMark = sym; + var finishMark = stream.next(); + // The range must terminate at an alphabetic character which + // shares the same case as the start of the range. + if (isLowerCase(startMark) && isLowerCase(finishMark) || + isUpperCase(startMark) && isUpperCase(finishMark)) { + var start = startMark.charCodeAt(0); + var finish = finishMark.charCodeAt(0); + if (start >= finish) { + showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); + return; + } + + // Because marks are always ASCII values, and we have + // determined that they are the same case, we can use + // their char codes to iterate through the defined range. + for (var j = 0; j <= finish - start; j++) { + var mark = String.fromCharCode(start + j); + delete state.marks[mark]; + } + } else { + showConfirm(cm, 'Invalid argument: ' + startMark + '-'); + return; + } + } else { + // This symbol is a valid mark, and is not part of a range. + delete state.marks[sym]; + } + } + } + }; + + var exCommandDispatcher = new ExCommandDispatcher(); + + /** + * @param {CodeMirror} cm CodeMirror instance we are in. + * @param {boolean} confirm Whether to confirm each replace. + * @param {Cursor} lineStart Line to start replacing from. + * @param {Cursor} lineEnd Line to stop replacing at. + * @param {RegExp} query Query for performing matches with. + * @param {string} replaceWith Text to replace matches with. May contain $1, + * $2, etc for replacing captured groups using Javascript replace. + * @param {function()} callback A callback for when the replace is done. + */ + function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query, + replaceWith, callback) { + // Set up all the functions. + cm.state.vim.exMode = true; + var done = false; + var lastPos = searchCursor.from(); + function replaceAll() { + cm.operation(function() { + while (!done) { + replace(); + next(); + } + stop(); + }); + } + function replace() { + var text = cm.getRange(searchCursor.from(), searchCursor.to()); + var newText = text.replace(query, replaceWith); + searchCursor.replace(newText); + } + function next() { + var found; + // The below only loops to skip over multiple occurrences on the same + // line when 'global' is not true. + while(found = searchCursor.findNext() && + isInRange(searchCursor.from(), lineStart, lineEnd)) { + if (!global && lastPos && searchCursor.from().line == lastPos.line) { + continue; + } + cm.scrollIntoView(searchCursor.from(), 30); + cm.setSelection(searchCursor.from(), searchCursor.to()); + lastPos = searchCursor.from(); + done = false; + return; + } + done = true; + } + function stop(close) { + if (close) { close(); } + cm.focus(); + if (lastPos) { + cm.setCursor(lastPos); + var vim = cm.state.vim; + vim.exMode = false; + vim.lastHPos = vim.lastHSPos = lastPos.ch; + } + if (callback) { callback(); } + } + function onPromptKeyDown(e, _value, close) { + // Swallow all keys. + CodeMirror.e_stop(e); + var keyName = CodeMirror.keyName(e); + switch (keyName) { + case 'Y': + replace(); next(); break; + case 'N': + next(); break; + case 'A': + // replaceAll contains a call to close of its own. We don't want it + // to fire too early or multiple times. + var savedCallback = callback; + callback = undefined; + cm.operation(replaceAll); + callback = savedCallback; + break; + case 'L': + replace(); + // fall through and exit. + case 'Q': + case 'Esc': + case 'Ctrl-C': + case 'Ctrl-[': + stop(close); + break; + } + if (done) { stop(close); } + return true; + } + + // Actually do replace. + next(); + if (done) { + showConfirm(cm, 'No matches for ' + query.source); + return; + } + if (!confirm) { + replaceAll(); + if (callback) { callback(); }; + return; + } + showPrompt(cm, { + prefix: 'replace with ' + replaceWith + ' (y/n/a/q/l)', + onKeyDown: onPromptKeyDown + }); + } + + CodeMirror.keyMap.vim = { + attach: attachVimMap, + detach: detachVimMap + }; + + function exitInsertMode(cm) { + var vim = cm.state.vim; + var macroModeState = vimGlobalState.macroModeState; + var insertModeChangeRegister = vimGlobalState.registerController.getRegister('.'); + var isPlaying = macroModeState.isPlaying; + var lastChange = macroModeState.lastInsertModeChanges; + // In case of visual block, the insertModeChanges are not saved as a + // single word, so we convert them to a single word + // so as to update the ". register as expected in real vim. + var text = []; + if (!isPlaying) { + var selLength = lastChange.inVisualBlock ? vim.lastSelection.visualBlock.height : 1; + var changes = lastChange.changes; + var text = []; + var i = 0; + // In case of multiple selections in blockwise visual, + // the inserted text, for example: 'foo', is stored as + // 'f', 'f', InsertModeKey 'o', 'o', 'o', 'o'. (if you have a block with 2 lines). + // We push the contents of the changes array as per the following: + // 1. In case of InsertModeKey, just increment by 1. + // 2. In case of a character, jump by selLength (2 in the example). + while (i < changes.length) { + // This loop will convert 'ffoooo' to 'foo'. + text.push(changes[i]); + if (changes[i] instanceof InsertModeKey) { + i++; + } else { + i+= selLength; + } + } + lastChange.changes = text; + cm.off('change', onChange); + CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); + } + if (!isPlaying && vim.insertModeRepeat > 1) { + // Perform insert mode repeat for commands like 3,a and 3,o. + repeatLastEdit(cm, vim, vim.insertModeRepeat - 1, + true /** repeatForInsert */); + vim.lastEditInputState.repeatOverride = vim.insertModeRepeat; + } + delete vim.insertModeRepeat; + vim.insertMode = false; + cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1); + cm.setOption('keyMap', 'vim'); + cm.setOption('disableInput', true); + cm.toggleOverwrite(false); // exit replace mode if we were in it. + // update the ". register before exiting insert mode + insertModeChangeRegister.setText(lastChange.changes.join('')); + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + if (macroModeState.isRecording) { + logInsertModeChange(macroModeState); + } + } + + // The timeout in milliseconds for the two-character ESC keymap should be + // adjusted according to your typing speed to prevent false positives. + defineOption('insertModeEscKeysTimeout', 200, 'number'); + + CodeMirror.keyMap['vim-insert'] = { + // TODO: override navigation keys so that Esc will cancel automatic + // indentation from o, O, i_ + 'Ctrl-N': 'autocomplete', + 'Ctrl-P': 'autocomplete', + 'Enter': function(cm) { + var fn = CodeMirror.commands.newlineAndIndentContinueComment || + CodeMirror.commands.newlineAndIndent; + fn(cm); + }, + fallthrough: ['default'], + attach: attachVimMap, + detach: detachVimMap + }; + + CodeMirror.keyMap['await-second'] = { + fallthrough: ['vim-insert'], + attach: attachVimMap, + detach: detachVimMap + }; + + CodeMirror.keyMap['vim-replace'] = { + 'Backspace': 'goCharLeft', + fallthrough: ['vim-insert'], + attach: attachVimMap, + detach: detachVimMap + }; + + function executeMacroRegister(cm, vim, macroModeState, registerName) { + var register = vimGlobalState.registerController.getRegister(registerName); + var keyBuffer = register.keyBuffer; + var imc = 0; + macroModeState.isPlaying = true; + macroModeState.replaySearchQueries = register.searchQueries.slice(0); + for (var i = 0; i < keyBuffer.length; i++) { + var text = keyBuffer[i]; + var match, key; + while (text) { + // Pull off one command key, which is either a single character + // or a special sequence wrapped in '<' and '>', e.g. ''. + match = (/<\w+-.+?>|<\w+>|./).exec(text); + key = match[0]; + text = text.substring(match.index + key.length); + CodeMirror.Vim.handleKey(cm, key, 'macro'); + if (vim.insertMode) { + var changes = register.insertModeChanges[imc++].changes; + vimGlobalState.macroModeState.lastInsertModeChanges.changes = + changes; + repeatInsertModeChanges(cm, changes, 1); + exitInsertMode(cm); + } + } + }; + macroModeState.isPlaying = false; + } + + function logKey(macroModeState, key) { + if (macroModeState.isPlaying) { return; } + var registerName = macroModeState.latestRegister; + var register = vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.pushText(key); + } + } + + function logInsertModeChange(macroModeState) { + if (macroModeState.isPlaying) { return; } + var registerName = macroModeState.latestRegister; + var register = vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.pushInsertModeChanges(macroModeState.lastInsertModeChanges); + } + } + + function logSearchQuery(macroModeState, query) { + if (macroModeState.isPlaying) { return; } + var registerName = macroModeState.latestRegister; + var register = vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.pushSearchQuery(query); + } + } + + /** + * Listens for changes made in insert mode. + * Should only be active in insert mode. + */ + function onChange(_cm, changeObj) { + var macroModeState = vimGlobalState.macroModeState; + var lastChange = macroModeState.lastInsertModeChanges; + if (!macroModeState.isPlaying) { + while(changeObj) { + lastChange.expectCursorActivityForChange = true; + if (changeObj.origin == '+input' || changeObj.origin == 'paste' + || changeObj.origin === undefined /* only in testing */) { + var text = changeObj.text.join('\n'); + lastChange.changes.push(text); + } + // Change objects may be chained with next. + changeObj = changeObj.next; + } + } + } + + /** + * Listens for any kind of cursor activity on CodeMirror. + */ + function onCursorActivity(cm) { + var vim = cm.state.vim; + if (vim.insertMode) { + // Tracking cursor activity in insert mode (for macro support). + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isPlaying) { return; } + var lastChange = macroModeState.lastInsertModeChanges; + if (lastChange.expectCursorActivityForChange) { + lastChange.expectCursorActivityForChange = false; + } else { + // Cursor moved outside the context of an edit. Reset the change. + lastChange.changes = []; + } + } else { + handleExternalSelection(cm, vim); + } + if (vim.visualMode) { + var from, head; + from = head = cm.getCursor('head'); + var anchor = cm.getCursor('anchor'); + var to = Pos(head.line, from.ch + (cursorIsBefore(anchor, head) ? -1 : 1)); + if (cursorIsBefore(to, from)) { + var temp = from; + from = to; + to = temp; + } + if (vim.fakeCursor) { + vim.fakeCursor.clear(); + } + vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); + } + } + + function handleExternalSelection(cm, vim) { + var anchor = cm.getCursor('anchor'); + var head = cm.getCursor('head'); + // Enter or exit visual mode to match mouse selection. + if (vim.visualMode && cursorEqual(head, anchor) && lineLength(cm, head.line) > head.ch) { + exitVisualMode(cm); + } else if (!cm.curOp.isVimOp && !vim.visualMode && !vim.insertMode && cm.somethingSelected()) { + vim.visualMode = true; + vim.visualLine = false; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); + } + if (!cm.curOp.isVimOp) { + if (vim.visualMode) { + updateMark(cm, vim, '<', cursorMin(head, anchor)); + updateMark(cm, vim, '>', cursorMax(head, anchor)); + } else if (!vim.insertMode) { + // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse. + vim.lastHPos = cm.getCursor().ch; + } + } + } + + /** Wrapper for special keys pressed in insert mode */ + function InsertModeKey(keyName) { + this.keyName = keyName; + } + + /** + * Handles raw key down events from the text area. + * - Should only be active in insert mode. + * - For recording deletes in insert mode. + */ + function onKeyEventTargetKeyDown(e) { + var macroModeState = vimGlobalState.macroModeState; + var lastChange = macroModeState.lastInsertModeChanges; + var keyName = CodeMirror.keyName(e); + function onKeyFound() { + lastChange.changes.push(new InsertModeKey(keyName)); + return true; + } + if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) { + CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound); + } + } + + /** + * Repeats the last edit, which includes exactly 1 command and at most 1 + * insert. Operator and motion commands are read from lastEditInputState, + * while action commands are read from lastEditActionCommand. + * + * If repeatForInsert is true, then the function was called by + * exitInsertMode to repeat the insert mode changes the user just made. The + * corresponding enterInsertMode call was made with a count. + */ + function repeatLastEdit(cm, vim, repeat, repeatForInsert) { + var macroModeState = vimGlobalState.macroModeState; + macroModeState.isPlaying = true; + var isAction = !!vim.lastEditActionCommand; + var cachedInputState = vim.inputState; + function repeatCommand() { + if (isAction) { + commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand); + } else { + commandDispatcher.evalInput(cm, vim); + } + } + function repeatInsert(repeat) { + if (macroModeState.lastInsertModeChanges.changes.length > 0) { + // For some reason, repeat cw in desktop VIM does not repeat + // insert mode changes. Will conform to that behavior. + repeat = !vim.lastEditActionCommand ? 1 : repeat; + var changeObject = macroModeState.lastInsertModeChanges; + repeatInsertModeChanges(cm, changeObject.changes, repeat); + } + } + vim.inputState = vim.lastEditInputState; + if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) { + // o and O repeat have to be interlaced with insert repeats so that the + // insertions appear on separate lines instead of the last line. + for (var i = 0; i < repeat; i++) { + repeatCommand(); + repeatInsert(1); + } + } else { + if (!repeatForInsert) { + // Hack to get the cursor to end up at the right place. If I is + // repeated in insert mode repeat, cursor will be 1 insert + // change set left of where it should be. + repeatCommand(); + } + repeatInsert(repeat); + } + vim.inputState = cachedInputState; + if (vim.insertMode && !repeatForInsert) { + // Don't exit insert mode twice. If repeatForInsert is set, then we + // were called by an exitInsertMode call lower on the stack. + exitInsertMode(cm); + } + macroModeState.isPlaying = false; + }; + + function repeatInsertModeChanges(cm, changes, repeat) { + function keyHandler(binding) { + if (typeof binding == 'string') { + CodeMirror.commands[binding](cm); + } else { + binding(cm); + } + return true; + } + var curStart = cm.getCursor(); + var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; + if (inVisualBlock) { + // Set up block selection again for repeating the changes. + var vim = cm.state.vim; + var block = vim.lastSelection.visualBlock; + var curEnd = Pos(curStart.line + block.height-1, curStart.ch); + cm.setCursor(curStart); + selectBlock(cm, curEnd); + repeat = cm.listSelections().length; + cm.setCursor(curStart); + } + for (var i = 0; i < repeat; i++) { + for (var j = 0; j < changes.length; j++) { + var change = changes[j]; + if (change instanceof InsertModeKey) { + CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler); + } else { + var cur = cm.getCursor(); + cm.replaceRange(change, cur, cur); + } + } + if (inVisualBlock) { + curStart.line++; + cm.setCursor(curStart); + } + } + } + + resetVimGlobalState(); + //}; + // Initialize Vim and make it available as an API. + CodeMirror.Vim = Vim(); + + Vim = CodeMirror.Vim; + + specialKey = {'return':'CR',backspace:'BS','delete':'Del',esc:'Esc', + left:'Left',right:'Right',up:'Up',down:'Down',space: 'Space', + home:'Home',end:'End',pageup:'PageUp',pagedown:'PageDown', enter: 'CR' + }; + function lookupKey(hashId, key, e) { + if (key.length > 1 && key[0] == "n") { + key = key.replace("numpad", ""); + } + key = specialKey[key] || key; + var name = ''; + if (e.ctrlKey) { name += 'C-'; } + if (e.altKey) { name += 'A-'; } + if (e.shiftKey) { name += 'S-'; } + + name += key; + if (name.length > 1) { name = '<' + name + '>'; } + return name; + } + var handleKey = Vim.handleKey + Vim.handleKey = function(cm, key, origin) { + return cm.operation(function() { + return handleKey(cm, key, origin); + }, true); + } + function cloneVimState(state) { + var n = new state.constructor(); + Object.keys(state).forEach(function(key) { + var o = state[key]; + if (Array.isArray(o)) + o = o.slice(); + else if (o && typeof o == "object" && o.constructor != Object) + o = cloneVimState(o); + n[key] = o; + }); + return n; + } + function multiSelectHandleKey(cm, key, origin) { + var isHandled = false; + var vim = Vim.maybeInitVimState_(cm); + var visualBlock = vim.visualBlock || vim.wasInVisualBlock; + if (vim.wasInVisualBlock && !cm.ace.inMultiSelectMode) { + vim.wasInVisualBlock = false; + } else if (cm.ace.inMultiSelectMode && vim.visualBlock) { + vim.wasInVisualBlock = true; + } + + if (key == '' && !vim.insertMode && !vim.visualMode && cm.ace.inMultiSelectMode) { + cm.ace.exitMultiSelectMode(); + } else if (visualBlock || !cm.ace.inMultiSelectMode || cm.ace.inVirtualSelectionMode) { + isHandled = Vim.handleKey(cm, key, origin); + } else { + var old = cloneVimState(vim); + cm.operation(function() { + cm.ace.forEachSelection(function() { + var sel = cm.ace.selection; + cm.state.vim.lastHPos = sel.$desiredColumn == null ? sel.lead.column : sel.$desiredColumn; + isHandled = handleKey(cm, key, origin); + sel.$desiredColumn = cm.state.vim.lastHPos == -1 ? null : cm.state.vim.lastHPos; + if (cm.virtualSelectionMode()) { + cm.state.vim = cloneVimState(old); + } + }); + if (cm.curOp.cursorActivity && !isHandled) + cm.curOp.cursorActivity = false; + }, true); + } + return isHandled; + }; + exports.CodeMirror = CodeMirror; + var getVim = Vim.maybeInitVimState_; + exports.handler = { + $id: "ace/keyboard/vim", + drawCursor: function(style, pixelPos, config, sel, session) { + var vim = this.state.vim || {}; + var w = config.characterWidth; + var h = config.lineHeight; + var top = pixelPos.top; + var left = pixelPos.left; + if (!vim.insertMode) { + var isbackwards = !sel.cursor + ? session.selection.isBackwards() || session.selection.isEmpty() + : Range.comparePoints(sel.cursor, sel.start) <= 0 + if (!isbackwards && left > w) + left -= w + } + if (!vim.insertMode && vim.status) { + h = h / 2; + top += h; + } + style.left = left + "px"; + style.top = top + "px"; + style.width = w + "px"; + style.height = h + "px"; + }, + handleKeyboard: function(data, hashId, key, keyCode, e) { + var editor = data.editor; + var cm = editor.state.cm; + var vim = getVim(cm); + if (keyCode == -1) return; + + if (key == "c" && hashId == 1) { // key == "ctrl-c" + if (!useragent.isMac && editor.getCopyText()) { + editor.once("copy", function() { + editor.selection.clearSelection(); + }); + return {command: "null", passEvent: true}; + } + return {command: coreCommands.stop}; + } else if (!vim.insertMode) { + if (useragent.isMac && this.handleMacRepeat(data, hashId, key)) { + hashId = -1; + key = data.inputChar; + } + } + + if (hashId == -1 || hashId & 1 || hashId === 0 && key.length > 1) { + var insertMode = vim.insertMode; + var name = lookupKey(hashId, key, e || {}); + if (vim.status == null) + vim.status = ""; + var isHandled = multiSelectHandleKey(cm, name, 'user'); + vim = getVim(cm); // may be changed by multiSelectHandleKey + if (isHandled && vim.status != null) + vim.status += name; + else if (vim.status == null) + vim.status = ""; + cm._signal("changeStatus"); + if (!isHandled && (hashId != -1 || insertMode)) + return; + return {command: "null", passEvent: !isHandled}; + } + }, + attach: function(editor) { + if (!editor.state) editor.state = {}; + var cm = new CodeMirror(editor); + editor.state.cm = cm; + editor.$vimModeHandler = this; + CodeMirror.keyMap.vim.attach(cm); + getVim(cm).status = null; + cm.on('vim-command-done', function() { + if (cm.virtualSelectionMode()) return; + getVim(cm).status = null; + cm.ace._signal("changeStatus"); + cm.ace.session.markUndoGroup(); + }); + cm.on("changeStatus", function() { + cm.ace.renderer.updateCursor(); + cm.ace._signal("changeStatus"); + }); + cm.on("vim-mode-change", function() { + if (cm.virtualSelectionMode()) return; + cm.ace.renderer.setStyle("normal-mode", !getVim(cm).insertMode); + cm._signal("changeStatus"); + }); + cm.ace.renderer.setStyle("normal-mode", !getVim(cm).insertMode); + editor.renderer.$cursorLayer.drawCursor = this.drawCursor.bind(cm); + // renderVirtualNumbers.attach(editor); + this.updateMacCompositionHandlers(editor, true); + }, + detach: function(editor) { + var cm = editor.state.cm; + CodeMirror.keyMap.vim.detach(cm); + cm.destroy(); + editor.state.cm = null; + editor.$vimModeHandler = null; + editor.renderer.$cursorLayer.drawCursor = null; + editor.renderer.setStyle("normal-mode", false); + // renderVirtualNumbers.detach(editor); + this.updateMacCompositionHandlers(editor, false); + }, + getStatusText: function(editor) { + var cm = editor.state.cm; + var vim = getVim(cm); + if (vim.insertMode) + return "INSERT"; + var status = ""; + if (vim.visualMode) { + status += "VISUAL"; + if (vim.visualLine) + status += " LINE"; + if (vim.visualBlock) + status += " BLOCK"; + } + if (vim.status) + status += (status ? " " : "") + vim.status; + return status; + }, // workaround for j not repeating with `defaults write -g ApplePressAndHoldEnabled -bool true` handleMacRepeat: function(data, hashId, key) { - if (hashId == -1) { - // record key - data.inputChar = key; - data.lastEvent = "input"; - } else if (data.inputChar && data.$lastHash == hashId && data.$lastKey == key) { - // check for repeated keypress - if (data.lastEvent == "input") { - data.lastEvent = "input1"; - } else if (data.lastEvent == "input1") { - // simulate textinput - return true; - } - } else { - // reset - data.$lastHash = hashId; - data.$lastKey = key; - data.lastEvent = "keypress"; + if (hashId == -1) { + // record key + data.inputChar = key; + data.lastEvent = "input"; + } else if (data.inputChar && data.$lastHash == hashId && data.$lastKey == key) { + // check for repeated keypress + if (data.lastEvent == "input") { + data.lastEvent = "input1"; + } else if (data.lastEvent == "input1") { + // simulate textinput + return true; } + } else { + // reset + data.$lastHash = hashId; + data.$lastKey = key; + data.lastEvent = "keypress"; + } }, // on mac, with some keyboard layouts (e.g swedish) ^ starts composition, we don't need it in normal mode updateMacCompositionHandlers: function(editor, enable) { - var onCompositionUpdateOverride = function(text) { - if (util.currentMode !== "insert") { - var el = this.textInput.getElement(); - el.blur(); - el.focus(); - el.value = text; - } else { - this.onCompositionUpdateOrig(text); - } - }; - var onCompositionStartOverride = function(text) { - if (util.currentMode === "insert") { - this.onCompositionStartOrig(text); - } - }; - if (enable) { - if (!editor.onCompositionUpdateOrig) { - editor.onCompositionUpdateOrig = editor.onCompositionUpdate; - editor.onCompositionUpdate = onCompositionUpdateOverride; - editor.onCompositionStartOrig = editor.onCompositionStart; - editor.onCompositionStart = onCompositionStartOverride; - } + var onCompositionUpdateOverride = function(text) { + if (util.currentMode !== "insert") { + var el = this.textInput.getElement(); + el.blur(); + el.focus(); + el.value = text; } else { - if (editor.onCompositionUpdateOrig) { - editor.onCompositionUpdate = editor.onCompositionUpdateOrig; - editor.onCompositionUpdateOrig = null; - editor.onCompositionStart = editor.onCompositionStartOrig; - editor.onCompositionStartOrig = null; - } + this.onCompositionUpdateOrig(text); } - }, - - handleKeyboard: function(data, hashId, key, keyCode, e) { - // ignore command keys (shift, ctrl etc.) - if (hashId !== 0 && (!key || keyCode == -1)) - return null; - - var editor = data.editor; - var vimState = data.vimState || "start"; - - if (hashId == 1) - key = "ctrl-" + key; - if (key == "ctrl-c") { - if (!useragent.isMac && editor.getCopyText()) { - editor.once("copy", function() { - if (vimState == "start") - coreCommands.stop.exec(editor); - else - editor.selection.clearSelection(); - }); - return {command: "null", passEvent: true}; - } - return {command: coreCommands.stop}; - } else if ((key == "esc" && hashId === 0) || key == "ctrl-[") { - return {command: coreCommands.stop}; - } else if (vimState == "start") { - if (useragent.isMac && this.handleMacRepeat(data, hashId, key)) { - hashId = -1; - key = data.inputChar; - } - - if (hashId == -1 || hashId == 1 || hashId === 0 && key.length > 1) { - if (cmds.inputBuffer.idle && startCommands[key]) - return startCommands[key]; - var isHandled = cmds.inputBuffer.push(editor, key); - if (!isHandled && hashId !== -1) - return; - return {command: "null", passEvent: !isHandled}; - } else if (key == "esc" && hashId === 0) { - return {command: coreCommands.stop}; - } - // if no modifier || shift: wait for input. - else if (hashId === 0 || hashId == 4) { - return {command: "null", passEvent: true}; - } - } else { - if (key == "ctrl-w") { - return {command: "removewordleft"}; - } + }; + var onCompositionStartOverride = function(text) { + if (util.currentMode === "insert") { + this.onCompositionStartOrig(text); } - }, - - attach: function(editor) { - editor.on("click", exports.onCursorMove); - if (util.currentMode !== "insert") - cmds.coreCommands.stop.exec(editor); - editor.$vimModeHandler = this; - - this.updateMacCompositionHandlers(editor, true); - }, - - detach: function(editor) { - editor.removeListener("click", exports.onCursorMove); - util.noMode(editor); - util.currentMode = "normal"; - this.updateMacCompositionHandlers(editor, false); - }, - - actions: cmds.actions, - getStatusText: function() { - if (util.currentMode == "insert") - return "INSERT"; - if (util.onVisualMode) - return (util.onVisualLineMode ? "VISUAL LINE " : "VISUAL ") + cmds.inputBuffer.status; - return cmds.inputBuffer.status; + }; + if (enable) { + if (!editor.onCompositionUpdateOrig) { + editor.onCompositionUpdateOrig = editor.onCompositionUpdate; + editor.onCompositionUpdate = onCompositionUpdateOverride; + editor.onCompositionStartOrig = editor.onCompositionStart; + editor.onCompositionStart = onCompositionStartOverride; + } + } else { + if (editor.onCompositionUpdateOrig) { + editor.onCompositionUpdate = editor.onCompositionUpdateOrig; + editor.onCompositionUpdateOrig = null; + editor.onCompositionStart = editor.onCompositionStartOrig; + editor.onCompositionStartOrig = null; + } + } } -}; - - -exports.onCursorMove = function(e) { - cmds.onCursorMove(e.editor, e); - exports.onCursorMove.scheduled = false; -}; + } + var renderVirtualNumbers = { + getText: function(session, row) { + return (Math.abs(session.selection.lead.row - row) || (row + 1 + (row < 9? "\xb7" : "" ))) + "" + }, + getWidth: function(session, lastLineNumber, config) { + return session.getLength().toString().length * config.characterWidth; + }, + update: function(e, editor) { + editor.renderer.$loop.schedule(editor.renderer.CHANGE_GUTTER) + }, + attach: function(editor) { + editor.renderer.$gutterLayer.$renderer = this; + editor.on("changeSelection", this.update); + }, + detach: function(editor) { + editor.renderer.$gutterLayer.$renderer = null; + editor.off("changeSelection", this.update); + } + }; + Vim.defineOption({ + name: "wrap", + set: function(value, cm) { + if (cm) {cm.ace.setOption("wrap", value)} + }, + type: "boolean" + }, false); + defaultKeymap.push( + { keys: 'zc', type: 'action', action: 'fold', actionArgs: { open: false } }, + { keys: 'zC', type: 'action', action: 'fold', actionArgs: { open: false, all: true } }, + { keys: 'zo', type: 'action', action: 'fold', actionArgs: { open: true, } }, + { keys: 'zO', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, + { keys: 'za', type: 'action', action: 'fold', actionArgs: { toggle: true } }, + { keys: 'zA', type: 'action', action: 'fold', actionArgs: { toggle: true, all: true } }, + { keys: 'zf', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, + { keys: 'zd', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, + + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAbove" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelow" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAboveSkipCurrent" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelowSkipCurrent" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreBefore" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreAfter" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectNextBefore" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectNextAfter" } } + ); + actions.aceCommand = function(cm, actionArgs, vim) { + cm.vimCmd = actionArgs; + if (cm.ace.inVirtualSelectionMode) + cm.ace.on("beforeEndOperation", delayedExecAceCommand); + else + delayedExecAceCommand(null, cm.ace) + }; + function delayedExecAceCommand(op, ace) { + ace.off("beforeEndOperation", delayedExecAceCommand); + var cmd = ace.state.cm.vimCmd; + if (cmd) { + ace.execCommand(cmd.name, cmd.args); + } + ace.curOp = ace.prevOp; + } + actions.fold = function(cm, actionArgs, vim) { + cm.ace.execCommand(['toggleFoldWidget', 'toggleFoldWidget', 'foldOther', 'unfoldall' + ][(actionArgs.all ? 2 : 0) + (actionArgs.open ? 1 : 0)]); + }, + Vim.map("Y", "yy"); }); diff --git a/lib/ace/keyboard/vim/commands.js b/lib/ace/keyboard/vim/commands.js deleted file mode 100644 index abf04ef9..00000000 --- a/lib/ace/keyboard/vim/commands.js +++ /dev/null @@ -1,618 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2010, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ - -define(function(require, exports, module) { - -"never use strict"; - -var lang = require("../../lib/lang"); -var util = require("./maps/util"); -var motions = require("./maps/motions"); -var operators = require("./maps/operators"); -var alias = require("./maps/aliases"); -var registers = require("./registers"); - -var NUMBER = 1; -var OPERATOR = 2; -var MOTION = 3; -var ACTION = 4; -var HMARGIN = 8; // Minimum amount of line separation between margins; - -var repeat = function repeat(fn, count, args) { - while (0 < count--) - fn.apply(this, args); -}; - -var ensureScrollMargin = function(editor) { - var renderer = editor.renderer; - var pos = renderer.$cursorLayer.getPixelPosition(); - - var top = pos.top; - - var margin = HMARGIN * renderer.layerConfig.lineHeight; - if (2 * margin > renderer.$size.scrollerHeight) - margin = renderer.$size.scrollerHeight / 2; - - if (renderer.scrollTop > top - margin) { - renderer.session.setScrollTop(top - margin); - } - - if (renderer.scrollTop + renderer.$size.scrollerHeight < top + margin + renderer.lineHeight) { - renderer.session.setScrollTop(top + margin + renderer.lineHeight - renderer.$size.scrollerHeight); - } -}; - -var actions = exports.actions = { - "z": { - param: true, - fn: function(editor, range, count, param) { - switch (param) { - case "z": - editor.renderer.alignCursor(null, 0.5); - break; - case "t": - editor.renderer.alignCursor(null, 0); - break; - case "b": - editor.renderer.alignCursor(null, 1); - break; - case "c": - editor.session.onFoldWidgetClick(range.start.row, {domEvent:{target :{}}}); - break; - case "o": - editor.session.onFoldWidgetClick(range.start.row, {domEvent:{target :{}}}); - break; - case "C": - editor.session.foldAll(); - break; - case "O": - editor.session.unfold(); - break; - } - } - }, - "r": { - param: true, - fn: function(editor, range, count, param) { - if (param && param.length) { - if (param.length > 1) - param = param == "return" ? "\n" : param == "tab" ? "\t" : param; - repeat(function() { editor.insert(param); }, count || 1); - editor.navigateLeft(); - } - } - }, - "R": { - fn: function(editor, range, count, param) { - util.insertMode(editor); - editor.setOverwrite(true); - } - }, - "~": { - fn: function(editor, range, count) { - repeat(function() { - var range = editor.selection.getRange(); - if (range.isEmpty()) - range.end.column++; - var text = editor.session.getTextRange(range); - var toggled = text.toUpperCase(); - if (toggled != text) - editor.session.replace(range, toggled); - else if (text.toLowerCase() != text) - editor.session.replace(range, text.toLowerCase()) - else - editor.navigateRight(); - }, count || 1); - } - }, - "*": { - fn: function(editor, range, count, param) { - editor.selection.selectWord(); - editor.findNext(); - ensureScrollMargin(editor); - var r = editor.selection.getRange(); - editor.selection.setSelectionRange(r, true); - } - }, - "#": { - fn: function(editor, range, count, param) { - editor.selection.selectWord(); - editor.findPrevious(); - ensureScrollMargin(editor); - var r = editor.selection.getRange(); - editor.selection.setSelectionRange(r, true); - } - }, - "m": { - param: true, - fn: function(editor, range, count, param) { - var s = editor.session; - var markers = s.vimMarkers || (s.vimMarkers = {}); - var c = editor.getCursorPosition(); - if (!markers[param]) { - markers[param] = editor.session.doc.createAnchor(c); - } - markers[param].setPosition(c.row, c.column, true); - } - }, - "n": { - fn: function(editor, range, count, param) { - var options = editor.getLastSearchOptions(); - options.backwards = false; - options.start = null; - - editor.selection.moveCursorRight(); - editor.selection.clearSelection(); - editor.findNext(options); - - ensureScrollMargin(editor); - var r = editor.selection.getRange(); - r.end.row = r.start.row; - r.end.column = r.start.column; - editor.selection.setSelectionRange(r, true); - } - }, - "N": { - fn: function(editor, range, count, param) { - var options = editor.getLastSearchOptions(); - options.backwards = true; - options.start = null; - - editor.findPrevious(options); - ensureScrollMargin(editor); - var r = editor.selection.getRange(); - r.end.row = r.start.row; - r.end.column = r.start.column; - editor.selection.setSelectionRange(r, true); - } - }, - "v": { - fn: function(editor, range, count, param) { - editor.selection.selectRight(); - util.visualMode(editor, false); - }, - acceptsMotion: true - }, - "V": { - fn: function(editor, range, count, param) { - //editor.selection.selectLine(); - //editor.selection.selectLeft(); - var row = editor.getCursorPosition().row; - editor.selection.moveTo(row, 0); - editor.selection.selectLineEnd(); - editor.selection.visualLineStart = row; - - util.visualMode(editor, true); - }, - acceptsMotion: true - }, - "Y": { - fn: function(editor, range, count, param) { - util.copyLine(editor); - } - }, - "p": { - fn: function(editor, range, count, param) { - var defaultReg = registers._default; - - editor.setOverwrite(false); - if (defaultReg.isLine) { - var pos = editor.getCursorPosition(); - pos.column = editor.session.getLine(pos.row).length; - var text = lang.stringRepeat("\n" + defaultReg.text, count || 1); - editor.session.insert(pos, text); - editor.moveCursorTo(pos.row + 1, 0); - } - else { - editor.navigateRight(); - editor.insert(lang.stringRepeat(defaultReg.text, count || 1)); - editor.navigateLeft(); - } - editor.setOverwrite(true); - editor.selection.clearSelection(); - } - }, - "P": { - fn: function(editor, range, count, param) { - var defaultReg = registers._default; - editor.setOverwrite(false); - - if (defaultReg.isLine) { - var pos = editor.getCursorPosition(); - pos.column = 0; - var text = lang.stringRepeat(defaultReg.text + "\n", count || 1); - editor.session.insert(pos, text); - editor.moveCursorToPosition(pos); - } - else { - editor.insert(lang.stringRepeat(defaultReg.text, count || 1)); - } - editor.setOverwrite(true); - editor.selection.clearSelection(); - } - }, - "J": { - fn: function(editor, range, count, param) { - var session = editor.session; - range = editor.getSelectionRange(); - var pos = {row: range.start.row, column: range.start.column}; - count = count || range.end.row - range.start.row; - var maxRow = Math.min(pos.row + (count || 1), session.getLength() - 1); - - range.start.column = session.getLine(pos.row).length; - range.end.column = session.getLine(maxRow).length; - range.end.row = maxRow; - - var text = ""; - for (var i = pos.row; i < maxRow; i++) { - var nextLine = session.getLine(i + 1); - text += " " + /^\s*(.*)$/.exec(nextLine)[1] || ""; - } - - session.replace(range, text); - editor.moveCursorTo(pos.row, pos.column); - } - }, - "u": { - fn: function(editor, range, count, param) { - count = parseInt(count || 1, 10); - for (var i = 0; i < count; i++) { - editor.undo(); - } - editor.selection.clearSelection(); - } - }, - "ctrl-r": { - fn: function(editor, range, count, param) { - count = parseInt(count || 1, 10); - for (var i = 0; i < count; i++) { - editor.redo(); - } - editor.selection.clearSelection(); - } - }, - ":": { - fn: function(editor, range, count, param) { - var val = ":"; - if (count > 1) - val = ".,.+" + count + val; - if (editor.showCommandLine) - editor.showCommandLine(val); - } - }, - "/": { - fn: function(editor, range, count, param) { - if (editor.showCommandLine) - editor.showCommandLine("/"); - } - }, - "?": { - fn: function(editor, range, count, param) { - if (editor.showCommandLine) - editor.showCommandLine("?"); - } - }, - ".": { - fn: function(editor, range, count, param) { - util.onInsertReplaySequence = inputBuffer.lastInsertCommands; - var previous = inputBuffer.previous; - if (previous) // If there is a previous action - inputBuffer.exec(editor, previous.action, previous.param); - } - }, - "ctrl-x": { - fn: function(editor, range, count, param) { - editor.modifyNumber(-(count || 1)); - } - }, - "ctrl-a": { - fn: function(editor, range, count, param) { - editor.modifyNumber(count || 1); - } - } -}; - -var inputBuffer = exports.inputBuffer = { - accepting: [NUMBER, OPERATOR, MOTION, ACTION], - currentCmd: null, - //currentMode: 0, - currentCount: "", - pendingCount: "", - status: "", - - // Types - operator: null, - motion: null, - - lastInsertCommands: [], - - push: function(editor, ch, keyId) { - var status = this.status; - var isKeyHandled = true; - this.idle = false; - var wObj = this.waitingForParam; - if (/^numpad\d+$/i.test(ch)) - ch = ch.substr(6); - - if (wObj) { - this.exec(editor, wObj, ch); - } - // If input is a number (that doesn't start with 0) - else if (!(ch === "0" && !this.currentCount.length) && - (/^\d+$/.test(ch) && this.isAccepting(NUMBER))) { - // Assuming that ch is always of type String, and not Number - this.currentCount += ch; - this.currentCmd = NUMBER; - this.accepting = [NUMBER, OPERATOR, MOTION, ACTION]; - } - else if (!this.operator && this.isAccepting(OPERATOR) && operators[ch]) { - this.operator = { - ch: ch, - count: this.getCount() - }; - this.currentCmd = OPERATOR; - this.accepting = [NUMBER, MOTION, ACTION]; - this.exec(editor, { operator: this.operator }); - } - else if (motions[ch] && this.isAccepting(MOTION)) { - this.currentCmd = MOTION; - - var ctx = { - operator: this.operator, - motion: { - ch: ch, - count: this.getCount() - } - }; - - if (motions[ch].param) - this.waitForParam(ctx); - else - this.exec(editor, ctx); - } - else if (alias[ch] && this.isAccepting(MOTION)) { - alias[ch].operator.count = this.getCount(); - this.exec(editor, alias[ch]); - } - else if (actions[ch] && this.isAccepting(ACTION)) { - var actionObj = { - action: { - fn: actions[ch].fn, - count: this.getCount() - } - }; - - if (actions[ch].param) { - this.waitForParam(actionObj); - } - else { - this.exec(editor, actionObj); - } - - if (actions[ch].acceptsMotion) - this.idle = false; - } - else if (this.operator) { - this.operator.count = this.getCount(); - this.exec(editor, { operator: this.operator }, ch); - } - else { - isKeyHandled = ch.length == 1; - this.reset(); - } - - if (this.waitingForParam || this.motion || this.operator) { - this.status += ch; - } else if (this.currentCount) { - this.status = this.currentCount; - } else if (this.status) { - this.status = ""; - } - if (this.status != status) - editor._emit("changeStatus"); - return isKeyHandled; - }, - - waitForParam: function(cmd) { - this.waitingForParam = cmd; - }, - - getCount: function() { - var count = this.currentCount || this.pendingCount; - this.currentCount = ""; - this.pendingCount = count; - return count && parseInt(count, 10); - }, - - exec: function(editor, action, param) { - var m = action.motion; - var o = action.operator; - var a = action.action; - - if (!param) - param = action.param; - - if (o) { - this.previous = { - action: action, - param: param - }; - } - - if (o && !editor.selection.isEmpty()) { - if (operators[o.ch].selFn) { - operators[o.ch].selFn(editor, editor.getSelectionRange(), o.count, param); - this.reset(); - } - return; - } - - // There is an operator, but no motion or action. We try to pass the - // current ch to the operator to see if it responds to it (an example - // of this is the 'dd' operator). - else if (!m && !a && o && param) { - operators[o.ch].fn(editor, null, o.count, param); - this.reset(); - } - else if (m) { - var run = function(fn) { - if (fn && typeof fn === "function") { // There should always be a motion - if (m.count && !motionObj.handlesCount) - repeat(fn, m.count, [editor, null, m.count, param]); - else - fn(editor, null, m.count, param); - } - }; - - var motionObj = motions[m.ch]; - var selectable = motionObj.sel; - - if (!o) { - if ((util.onVisualMode || util.onVisualLineMode) && selectable) - run(motionObj.sel); - else - run(motionObj.nav); - } - else if (selectable) { - repeat(function() { - run(motionObj.sel); - operators[o.ch].fn(editor, editor.getSelectionRange(), - o.count, motionObj.param ? motionObj : param); - }, o.count || 1); - } - this.reset(); - } - else if (a) { - a.fn(editor, editor.getSelectionRange(), a.count, param); - this.reset(); - } - handleCursorMove(editor); - }, - - isAccepting: function(type) { - return this.accepting.indexOf(type) !== -1; - }, - - reset: function() { - this.operator = null; - this.motion = null; - this.currentCount = ""; - this.pendingCount = ""; - this.status = ""; - this.accepting = [NUMBER, OPERATOR, MOTION, ACTION]; - this.idle = true; - this.waitingForParam = null; - } -}; - -function setPreviousCommand(fn) { - inputBuffer.previous = { action: { action: { fn: fn } } }; -} - -exports.coreCommands = { - start: { - exec: function start(editor) { - util.insertMode(editor); - setPreviousCommand(start); - } - }, - startBeginning: { - exec: function startBeginning(editor) { - editor.navigateLineStart(); - util.insertMode(editor); - setPreviousCommand(startBeginning); - } - }, - // Stop Insert mode as soon as possible. Works like typing in - // insert mode. - stop: { - exec: function stop(editor) { - inputBuffer.reset(); - util.onVisualMode = false; - util.onVisualLineMode = false; - inputBuffer.lastInsertCommands = util.normalMode(editor); - } - }, - append: { - exec: function append(editor) { - var pos = editor.getCursorPosition(); - var lineLen = editor.session.getLine(pos.row).length; - if (lineLen) - editor.navigateRight(); - util.insertMode(editor); - setPreviousCommand(append); - } - }, - appendEnd: { - exec: function appendEnd(editor) { - editor.navigateLineEnd(); - util.insertMode(editor); - setPreviousCommand(appendEnd); - } - } -}; - -var handleCursorMove = exports.onCursorMove = function(editor, e) { - if (util.currentMode === 'insert' || handleCursorMove.running) - return; - else if(!editor.selection.isEmpty()) { - handleCursorMove.running = true; - if (util.onVisualLineMode) { - var originRow = editor.selection.visualLineStart; - var cursorRow = editor.getCursorPosition().row; - if(originRow <= cursorRow) { - var endLine = editor.session.getLine(cursorRow); - editor.selection.moveTo(originRow, 0); - editor.selection.selectTo(cursorRow, endLine.length); - } else { - var endLine = editor.session.getLine(originRow); - editor.selection.moveTo(originRow, endLine.length); - editor.selection.selectTo(cursorRow, 0); - } - } - handleCursorMove.running = false; - return; - } - else { - if (e && (util.onVisualLineMode || util.onVisualMode)) { - editor.selection.clearSelection(); - util.normalMode(editor); - } - - handleCursorMove.running = true; - var pos = editor.getCursorPosition(); - var lineLen = editor.session.getLine(pos.row).length; - - if (lineLen && pos.column === lineLen) - editor.navigateLeft(); - handleCursorMove.running = false; - } -}; -}); diff --git a/lib/ace/keyboard/vim/maps/aliases.js b/lib/ace/keyboard/vim/maps/aliases.js deleted file mode 100644 index 1a5f32f7..00000000 --- a/lib/ace/keyboard/vim/maps/aliases.js +++ /dev/null @@ -1,94 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2010, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ - -"use strict" - -define(function(require, exports, module) { -module.exports = { - "x": { - operator: { - ch: "d", - count: 1 - }, - motion: { - ch: "l", - count: 1 - } - }, - "X": { - operator: { - ch: "d", - count: 1 - }, - motion: { - ch: "h", - count: 1 - } - }, - "D": { - operator: { - ch: "d", - count: 1 - }, - motion: { - ch: "$", - count: 1 - } - }, - "C": { - operator: { - ch: "c", - count: 1 - }, - motion: { - ch: "$", - count: 1 - } - }, - "s": { - operator: { - ch: "c", - count: 1 - }, - motion: { - ch: "l", - count: 1 - } - }, - "S": { - operator: { - ch: "c", - count: 1 - }, - param: "c" - } -}; -}); - diff --git a/lib/ace/keyboard/vim/maps/motions.js b/lib/ace/keyboard/vim/maps/motions.js deleted file mode 100644 index 92df11d6..00000000 --- a/lib/ace/keyboard/vim/maps/motions.js +++ /dev/null @@ -1,681 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2010, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ - - -define(function(require, exports, module) { -"use strict"; - -var util = require("./util"); - -var keepScrollPosition = function(editor, fn) { - var scrollTopRow = editor.renderer.getScrollTopRow(); - var initialRow = editor.getCursorPosition().row; - var diff = initialRow - scrollTopRow; - fn && fn.call(editor); - editor.renderer.scrollToRow(editor.getCursorPosition().row - diff); -}; - -function Motion(m) { - if (typeof m == "function") { - var getPos = m; - m = this; - } else { - var getPos = m.getPos; - } - m.nav = function(editor, range, count, param) { - var a = getPos(editor, range, count, param, false); - if (!a) - return; - editor.selection.moveTo(a.row, a.column); - }; - m.sel = function(editor, range, count, param) { - var a = getPos(editor, range, count, param, true); - if (!a) - return; - editor.selection.selectTo(a.row, a.column); - }; - return m; -} - -var nonWordRe = /[\s.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/; -var wordSeparatorRe = /[.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/; -var whiteRe = /\s/; -var StringStream = function(editor, cursor) { - var sel = editor.selection; - this.range = sel.getRange(); - cursor = cursor || sel.selectionLead; - this.row = cursor.row; - this.col = cursor.column; - var line = editor.session.getLine(this.row); - var maxRow = editor.session.getLength(); - this.ch = line[this.col] || '\n'; - this.skippedLines = 0; - - this.next = function() { - this.ch = line[++this.col] || this.handleNewLine(1); - //this.debug() - return this.ch; - }; - this.prev = function() { - this.ch = line[--this.col] || this.handleNewLine(-1); - //this.debug() - return this.ch; - }; - this.peek = function(dir) { - var ch = line[this.col + dir]; - if (ch) - return ch; - if (dir == -1) - return '\n'; - if (this.col == line.length - 1) - return '\n'; - return editor.session.getLine(this.row + 1)[0] || '\n'; - }; - - this.handleNewLine = function(dir) { - if (dir == 1){ - if (this.col == line.length) - return '\n'; - if (this.row == maxRow - 1) - return ''; - this.col = 0; - this.row ++; - line = editor.session.getLine(this.row); - this.skippedLines++; - return line[0] || '\n'; - } - if (dir == -1) { - if (this.row === 0) - return ''; - this.row --; - line = editor.session.getLine(this.row); - this.col = line.length; - this.skippedLines--; - return '\n'; - } - }; - this.debug = function() { - console.log(line.substring(0, this.col)+'|'+this.ch+'\''+this.col+'\''+line.substr(this.col+1)); - }; -}; - -var Search = require("../../../search").Search; -var search = new Search(); - -function find(editor, needle, dir) { - search.$options.needle = needle; - search.$options.backwards = dir == -1; - return search.find(editor.session); -} - -var Range = require("../../../range").Range; - -var LAST_SEARCH_MOTION = {}; - -module.exports = { - "w": new Motion(function(editor) { - var str = new StringStream(editor); - - if (str.ch && wordSeparatorRe.test(str.ch)) { - while (str.ch && wordSeparatorRe.test(str.ch)) - str.next(); - } else { - while (str.ch && !nonWordRe.test(str.ch)) - str.next(); - } - while (str.ch && whiteRe.test(str.ch) && str.skippedLines < 2) - str.next(); - - str.skippedLines == 2 && str.prev(); - return {column: str.col, row: str.row}; - }), - "W": new Motion(function(editor) { - var str = new StringStream(editor); - while(str.ch && !(whiteRe.test(str.ch) && !whiteRe.test(str.peek(1))) && str.skippedLines < 2) - str.next(); - if (str.skippedLines == 2) - str.prev(); - else - str.next(); - - return {column: str.col, row: str.row}; - }), - "b": new Motion(function(editor) { - var str = new StringStream(editor); - - str.prev(); - while (str.ch && whiteRe.test(str.ch) && str.skippedLines > -2) - str.prev(); - - if (str.ch && wordSeparatorRe.test(str.ch)) { - while (str.ch && wordSeparatorRe.test(str.ch)) - str.prev(); - } else { - while (str.ch && !nonWordRe.test(str.ch)) - str.prev(); - } - str.ch && str.next(); - return {column: str.col, row: str.row}; - }), - "B": new Motion(function(editor) { - var str = new StringStream(editor); - str.prev(); - while(str.ch && !(!whiteRe.test(str.ch) && whiteRe.test(str.peek(-1))) && str.skippedLines > -2) - str.prev(); - - if (str.skippedLines == -2) - str.next(); - - return {column: str.col, row: str.row}; - }), - "e": new Motion(function(editor) { - var str = new StringStream(editor); - - str.next(); - while (str.ch && whiteRe.test(str.ch)) - str.next(); - - if (str.ch && wordSeparatorRe.test(str.ch)) { - while (str.ch && wordSeparatorRe.test(str.ch)) - str.next(); - } else { - while (str.ch && !nonWordRe.test(str.ch)) - str.next(); - } - str.ch && str.prev(); - return {column: str.col, row: str.row}; - }), - "E": new Motion(function(editor) { - var str = new StringStream(editor); - str.next(); - while(str.ch && !(!whiteRe.test(str.ch) && whiteRe.test(str.peek(1)))) - str.next(); - - return {column: str.col, row: str.row}; - }), - - "l": { - nav: function(editor) { - var pos = editor.getCursorPosition(); - var col = pos.column; - var lineLen = editor.session.getLine(pos.row).length; - if (lineLen && col !== lineLen) - editor.navigateRight(); - }, - sel: function(editor) { - var pos = editor.getCursorPosition(); - var col = pos.column; - var lineLen = editor.session.getLine(pos.row).length; - - // Solving the behavior at the end of the line due to the - // different 0 index-based colum positions in ACE. - if (lineLen && col !== lineLen) //In selection mode you can select the newline - editor.selection.selectRight(); - } - }, - "h": { - nav: function(editor) { - var pos = editor.getCursorPosition(); - if (pos.column > 0) - editor.navigateLeft(); - }, - sel: function(editor) { - var pos = editor.getCursorPosition(); - if (pos.column > 0) - editor.selection.selectLeft(); - } - }, - "H": { - nav: function(editor) { - var row = editor.renderer.getScrollTopRow(); - editor.moveCursorTo(row); - }, - sel: function(editor) { - var row = editor.renderer.getScrollTopRow(); - editor.selection.selectTo(row); - } - }, - "M": { - nav: function(editor) { - var topRow = editor.renderer.getScrollTopRow(); - var bottomRow = editor.renderer.getScrollBottomRow(); - var row = topRow + ((bottomRow - topRow) / 2); - editor.moveCursorTo(row); - }, - sel: function(editor) { - var topRow = editor.renderer.getScrollTopRow(); - var bottomRow = editor.renderer.getScrollBottomRow(); - var row = topRow + ((bottomRow - topRow) / 2); - editor.selection.selectTo(row); - } - }, - "L": { - nav: function(editor) { - var row = editor.renderer.getScrollBottomRow(); - editor.moveCursorTo(row); - }, - sel: function(editor) { - var row = editor.renderer.getScrollBottomRow(); - editor.selection.selectTo(row); - } - }, - "k": { - nav: function(editor) { - editor.navigateUp(); - }, - sel: function(editor) { - editor.selection.selectUp(); - } - }, - "j": { - nav: function(editor) { - editor.navigateDown(); - }, - sel: function(editor) { - editor.selection.selectDown(); - } - }, - - "i": { - param: true, - sel: function(editor, range, count, param) { - switch (param) { - case "w": - editor.selection.selectWord(); - break; - case "W": - editor.selection.selectAWord(); - break; - case "(": - case "{": - case "[": - var cursor = editor.getCursorPosition(); - var end = editor.session.$findClosingBracket(param, cursor, /paren/); - if (!end) - return; - var start = editor.session.$findOpeningBracket(editor.session.$brackets[param], cursor, /paren/); - if (!start) - return; - start.column ++; - editor.selection.setSelectionRange(Range.fromPoints(start, end)); - break; - case "'": - case '"': - case "/": - var end = find(editor, param, 1); - if (!end) - return; - var start = find(editor, param, -1); - if (!start) - return; - editor.selection.setSelectionRange(Range.fromPoints(start.end, end.start)); - break; - } - } - }, - "a": { - param: true, - sel: function(editor, range, count, param) { - switch (param) { - case "w": - editor.selection.selectAWord(); - break; - case "W": - editor.selection.selectAWord(); - break; - case ")": - case "}": - case "]": - param = editor.session.$brackets[param]; - case "(": - case "{": - case "[": - var cursor = editor.getCursorPosition(); - var end = editor.session.$findClosingBracket(param, cursor, /paren/); - if (!end) - return; - var start = editor.session.$findOpeningBracket(editor.session.$brackets[param], cursor, /paren/); - if (!start) - return; - end.column ++; - editor.selection.setSelectionRange(Range.fromPoints(start, end)); - break; - case "'": - case "\"": - case "/": - var end = find(editor, param, 1); - if (!end) - return; - var start = find(editor, param, -1); - if (!start) - return; - end.column ++; - editor.selection.setSelectionRange(Range.fromPoints(start.start, end.end)); - break; - } - } - }, - - "f": new Motion({ - param: true, - handlesCount: true, - getPos: function(editor, range, count, param, isSel, isRepeat) { - if (param == "space") param = " "; - if (!isRepeat) - LAST_SEARCH_MOTION = {ch: "f", param: param}; - var cursor = editor.getCursorPosition(); - var column = util.getRightNthChar(editor, cursor, param, count || 1); - - if (typeof column === "number") { - cursor.column += column + (isSel ? 2 : 1); - return cursor; - } - } - }), - "F": new Motion({ - param: true, - handlesCount: true, - getPos: function(editor, range, count, param, isSel, isRepeat) { - if (param == "space") param = " "; - if (!isRepeat) - LAST_SEARCH_MOTION = {ch: "F", param: param}; - var cursor = editor.getCursorPosition(); - var column = util.getLeftNthChar(editor, cursor, param, count || 1); - - if (typeof column === "number") { - cursor.column -= column + 1; - return cursor; - } - } - }), - "t": new Motion({ - param: true, - handlesCount: true, - getPos: function(editor, range, count, param, isSel, isRepeat) { - if (param == "space") param = " "; - if (!isRepeat) - LAST_SEARCH_MOTION = {ch: "t", param: param}; - var cursor = editor.getCursorPosition(); - var column = util.getRightNthChar(editor, cursor, param, count || 1); - - if (isRepeat && column == 0 && !(count > 1)) - column = util.getRightNthChar(editor, cursor, param, 2); - - if (typeof column === "number") { - cursor.column += column + (isSel ? 1 : 0); - return cursor; - } - } - }), - "T": new Motion({ - param: true, - handlesCount: true, - getPos: function(editor, range, count, param, isSel, isRepeat) { - if (param == "space") param = " "; - if (!isRepeat) - LAST_SEARCH_MOTION = {ch: "T", param: param}; - var cursor = editor.getCursorPosition(); - var column = util.getLeftNthChar(editor, cursor, param, count || 1); - - if (isRepeat && column === 0 && !(count > 1)) - column = util.getLeftNthChar(editor, cursor, param, 2); - - if (typeof column === "number") { - cursor.column -= column; - return cursor; - } - } - }), - ";": new Motion({ - handlesCount: true, - getPos: function(editor, range, count, param, isSel) { - var ch = LAST_SEARCH_MOTION.ch; - if (!ch) - return; - return module.exports[ch].getPos( - editor, range, count, LAST_SEARCH_MOTION.param, isSel, true - ); - } - }), - ",": new Motion({ - handlesCount: true, - getPos: function(editor, range, count, param, isSel) { - var ch = LAST_SEARCH_MOTION.ch; - if (!ch) - return; - var up = ch.toUpperCase(); - ch = ch === up ? ch.toLowerCase() : up; - - return module.exports[ch].getPos( - editor, range, count, LAST_SEARCH_MOTION.param, isSel, true - ); - } - }), - - "^": { - nav: function(editor) { - editor.navigateLineStart(); - }, - sel: function(editor) { - editor.selection.selectLineStart(); - } - }, - "$": { - handlesCount: true, - nav: function(editor, range, count, param) { - if (count > 1) { - editor.navigateDown(count-1); - } - editor.navigateLineEnd(); - }, - sel: function(editor, range, count, param) { - if (count > 1) { - editor.selection.moveCursorBy(count-1, 0); - } - editor.selection.selectLineEnd(); - } - }, - "0": new Motion(function(ed) { - return {row: ed.selection.lead.row, column: 0}; - }), - "G": { - nav: function(editor, range, count, param) { - if (!count && count !== 0) { // Stupid JS - count = editor.session.getLength(); - } - editor.gotoLine(count); - }, - sel: function(editor, range, count, param) { - if (!count && count !== 0) { // Stupid JS - count = editor.session.getLength(); - } - editor.selection.selectTo(count, 0); - } - }, - "g": { - param: true, - nav: function(editor, range, count, param) { - switch(param) { - case "m": - console.log("Middle line"); - break; - case "e": - console.log("End of prev word"); - break; - case "g": - editor.gotoLine(count || 0); - case "u": - editor.gotoLine(count || 0); - case "U": - editor.gotoLine(count || 0); - } - }, - sel: function(editor, range, count, param) { - switch(param) { - case "m": - console.log("Middle line"); - break; - case "e": - console.log("End of prev word"); - break; - case "g": - editor.selection.selectTo(count || 0, 0); - } - } - }, - "o": { - nav: function(editor, range, count, param) { - count = count || 1; - var content = ""; - while (0 < count--) - content += "\n"; - - if (content.length) { - editor.navigateLineEnd(); - editor.insert(content); - util.insertMode(editor); - } - } - }, - "O": { - nav: function(editor, range, count, param) { - var row = editor.getCursorPosition().row; - count = count || 1; - var content = ""; - while (0 < count--) - content += "\n"; - - if (content.length) { - if(row > 0) { - editor.navigateUp(); - editor.navigateLineEnd(); - editor.insert(content); - } else { - editor.session.insert({row: 0, column: 0}, content); - editor.navigateUp(); - } - util.insertMode(editor); - } - } - }, - "%": new Motion(function(editor){ - var brRe = /[\[\]{}()]/g; - var cursor = editor.getCursorPosition(); - var ch = editor.session.getLine(cursor.row)[cursor.column]; - if (!brRe.test(ch)) { - var range = find(editor, brRe); - if (!range) - return; - cursor = range.start; - } - var match = editor.session.findMatchingBracket({ - row: cursor.row, - column: cursor.column + 1 - }); - - return match; - }), - "{": new Motion(function(ed) { - var session = ed.session; - var row = session.selection.lead.row; - while(row > 0 && !/\S/.test(session.getLine(row))) - row--; - while(/\S/.test(session.getLine(row))) - row--; - return {column: 0, row: row}; - }), - "}": new Motion(function(ed) { - var session = ed.session; - var l = session.getLength(); - var row = session.selection.lead.row; - while(row < l && !/\S/.test(session.getLine(row))) - row++; - while(/\S/.test(session.getLine(row))) - row++; - return {column: 0, row: row}; - }), - "ctrl-d": { - nav: function(editor, range, count, param) { - editor.selection.clearSelection(); - keepScrollPosition(editor, editor.gotoPageDown); - }, - sel: function(editor, range, count, param) { - keepScrollPosition(editor, editor.selectPageDown); - } - }, - "ctrl-u": { - nav: function(editor, range, count, param) { - editor.selection.clearSelection(); - keepScrollPosition(editor, editor.gotoPageUp); - }, - sel: function(editor, range, count, param) { - keepScrollPosition(editor, editor.selectPageUp); - } - }, - "`": new Motion({ - param: true, - handlesCount: true, - getPos: function(editor, range, count, param, isSel) { - var s = editor.session; - var marker = s.vimMarkers && s.vimMarkers[param]; - if (marker) { - return marker.getPosition(); - } - } - }), - "'": new Motion({ - param: true, - handlesCount: true, - getPos: function(editor, range, count, param, isSel) { - var s = editor.session; - var marker = s.vimMarkers && s.vimMarkers[param]; - if (marker) { - var pos = marker.getPosition(); - var line = editor.session.getLine(pos.row); - pos.column = line.search(/\S/); - if (pos.column == -1) - pos.column = line.length; - return pos; - } - }, - isLine: true - }) -}; - -module.exports.backspace = module.exports.left = module.exports.h; -module.exports.space = module.exports['return'] = module.exports.right = module.exports.l; -module.exports.up = module.exports.k; -module.exports.down = module.exports.j; -module.exports.pagedown = module.exports["ctrl-d"]; -module.exports.pageup = module.exports["ctrl-u"]; -module.exports.home = module.exports["0"]; -module.exports.end = module.exports["$"]; - -}); diff --git a/lib/ace/keyboard/vim/maps/operators.js b/lib/ace/keyboard/vim/maps/operators.js deleted file mode 100644 index 6df55b0f..00000000 --- a/lib/ace/keyboard/vim/maps/operators.js +++ /dev/null @@ -1,201 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2010, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ - -define(function(require, exports, module) { - -"use strict"; - -var util = require("./util"); -var registers = require("../registers"); -var Range = require("../../../range").Range; - -module.exports = { - "d": { - selFn: function(editor, range, count, param) { - registers._default.text = editor.getCopyText(); - registers._default.isLine = util.onVisualLineMode; - if(util.onVisualLineMode) - editor.removeLines(); - else - editor.session.remove(range); - util.normalMode(editor); - }, - fn: function(editor, range, count, param) { - count = count || 1; - switch (param) { - case "d": - registers._default.text = ""; - registers._default.isLine = true; - for (var i = 0; i < count; i++) { - editor.selection.selectLine(); - registers._default.text += editor.getCopyText(); - var selRange = editor.getSelectionRange(); - // check if end of the document was reached - if (!selRange.isMultiLine()) { - var row = selRange.start.row - 1; - var col = editor.session.getLine(row).length - selRange.setStart(row, col); - editor.session.remove(selRange); - editor.selection.clearSelection(); - break; - } - editor.session.remove(selRange); - editor.selection.clearSelection(); - } - registers._default.text = registers._default.text.replace(/\n$/, ""); - break; - default: - if (range) { - editor.selection.setSelectionRange(range); - registers._default.text = editor.getCopyText(); - registers._default.isLine = false; - editor.session.remove(range); - editor.selection.clearSelection(); - } - } - } - }, - "c": { - selFn: function(editor, range, count, param) { - editor.session.remove(range); - util.insertMode(editor); - }, - fn: function(editor, range, count, param) { - count = count || 1; - switch (param) { - case "c": - editor.$blockScrolling++; - editor.selection.$moveSelection(function() { - editor.selection.moveCursorBy(count - 1, 0); - }); - var rows = editor.$getSelectedRows(); - range = new Range(rows.first, 0, rows.last, Infinity); - editor.session.remove(range); - editor.$blockScrolling--; - util.insertMode(editor); - break; - default: - if (range) { - // range.end.column ++; - editor.session.remove(range); - util.insertMode(editor); - } - } - } - }, - "y": { - selFn: function(editor, range, count, param) { - registers._default.text = editor.getCopyText(); - registers._default.isLine = util.onVisualLineMode; - editor.selection.clearSelection(); - util.normalMode(editor); - }, - fn: function(editor, range, count, param) { - count = count || 1; - if (param && param.isLine) - param = "y"; - switch (param) { - case "y": - var pos = editor.getCursorPosition(); - editor.selection.selectLine(); - for (var i = 0; i < count - 1; i++) { - editor.selection.moveCursorDown(); - } - registers._default.text = editor.getCopyText().replace(/\n$/, ""); - editor.selection.clearSelection(); - registers._default.isLine = true; - editor.moveCursorToPosition(pos); - break; - default: - if (range) { - var pos = editor.getCursorPosition(); - editor.selection.setSelectionRange(range); - registers._default.text = editor.getCopyText(); - registers._default.isLine = false; - editor.selection.clearSelection(); - editor.moveCursorTo(pos.row, pos.column); - } - } - } - }, - ">": { - selFn: function(editor, range, count, param) { - count = count || 1; - for (var i = 0; i < count; i++) { - editor.indent(); - } - util.normalMode(editor); - }, - fn: function(editor, range, count, param) { - count = parseInt(count || 1, 10); - switch (param) { - case ">": - var pos = editor.getCursorPosition(); - editor.selection.selectLine(); - for (var i = 0; i < count - 1; i++) { - editor.selection.moveCursorDown(); - } - editor.indent(); - editor.selection.clearSelection(); - editor.moveCursorToPosition(pos); - editor.navigateLineEnd(); - editor.navigateLineStart(); - break; - } - } - }, - "<": { - selFn: function(editor, range, count, param) { - count = count || 1; - for (var i = 0; i < count; i++) { - editor.blockOutdent(); - } - util.normalMode(editor); - }, - fn: function(editor, range, count, param) { - count = count || 1; - switch (param) { - case "<": - var pos = editor.getCursorPosition(); - editor.selection.selectLine(); - for (var i = 0; i < count - 1; i++) { - editor.selection.moveCursorDown(); - } - editor.blockOutdent(); - editor.selection.clearSelection(); - editor.moveCursorToPosition(pos); - editor.navigateLineEnd(); - editor.navigateLineStart(); - break; - } - } - } -}; -}); diff --git a/lib/ace/keyboard/vim/maps/util.js b/lib/ace/keyboard/vim/maps/util.js deleted file mode 100644 index 1eadde84..00000000 --- a/lib/ace/keyboard/vim/maps/util.js +++ /dev/null @@ -1,132 +0,0 @@ -define(function(require, exports, module) { -var registers = require("../registers"); - -var dom = require("../../../lib/dom"); -dom.importCssString('.insert-mode .ace_cursor{\ - border-left: 2px solid #333333;\ -}\ -.ace_dark.insert-mode .ace_cursor{\ - border-left: 2px solid #eeeeee;\ -}\ -.normal-mode .ace_cursor{\ - border: 0!important;\ - background-color: red;\ - opacity: 0.5;\ -}', 'vimMode'); - -module.exports = { - onVisualMode: false, - onVisualLineMode: false, - currentMode: 'normal', - noMode: function(editor) { - editor.unsetStyle('insert-mode'); - editor.unsetStyle('normal-mode'); - if (editor.commands.recording) - editor.commands.toggleRecording(editor); - editor.setOverwrite(false); - }, - insertMode: function(editor) { - this.currentMode = 'insert'; - // Switch editor to insert mode - editor.setStyle('insert-mode'); - editor.unsetStyle('normal-mode'); - - editor.setOverwrite(false); - editor.keyBinding.$data.buffer = ""; - editor.keyBinding.$data.vimState = "insertMode"; - this.onVisualMode = false; - this.onVisualLineMode = false; - if(this.onInsertReplaySequence) { - // Ok, we're apparently replaying ("."), so let's do it - editor.commands.macro = this.onInsertReplaySequence; - editor.commands.replay(editor); - this.onInsertReplaySequence = null; - this.normalMode(editor); - } else { - editor._emit("changeStatus"); - // Record any movements, insertions in insert mode - if(!editor.commands.recording) - editor.commands.toggleRecording(editor); - } - }, - normalMode: function(editor) { - // Switch editor to normal mode - this.currentMode = 'normal'; - - editor.unsetStyle('insert-mode'); - editor.setStyle('normal-mode'); - editor.clearSelection(); - - var pos; - if (!editor.getOverwrite()) { - pos = editor.getCursorPosition(); - if (pos.column > 0) - editor.navigateLeft(); - } - - editor.setOverwrite(true); - editor.keyBinding.$data.buffer = ""; - editor.keyBinding.$data.vimState = "start"; - this.onVisualMode = false; - this.onVisualLineMode = false; - editor._emit("changeStatus"); - // Save recorded keystrokes - if (editor.commands.recording) { - editor.commands.toggleRecording(editor); - return editor.commands.macro; - } - else { - return []; - } - }, - visualMode: function(editor, lineMode) { - if ( - (this.onVisualLineMode && lineMode) - || (this.onVisualMode && !lineMode) - ) { - this.normalMode(editor); - return; - } - - editor.setStyle('insert-mode'); - editor.unsetStyle('normal-mode'); - - editor._emit("changeStatus"); - if (lineMode) { - this.onVisualLineMode = true; - } else { - this.onVisualMode = true; - this.onVisualLineMode = false; - } - }, - getRightNthChar: function(editor, cursor, ch, n) { - var line = editor.getSession().getLine(cursor.row); - var matches = line.substr(cursor.column + 1).split(ch); - - return n < matches.length ? matches.slice(0, n).join(ch).length : null; - }, - getLeftNthChar: function(editor, cursor, ch, n) { - var line = editor.getSession().getLine(cursor.row); - var matches = line.substr(0, cursor.column).split(ch); - - return n < matches.length ? matches.slice(-1 * n).join(ch).length : null; - }, - toRealChar: function(ch) { - if (ch.length === 1) - return ch; - - if (/^shift-./.test(ch)) - return ch[ch.length - 1].toUpperCase(); - else - return ""; - }, - copyLine: function(editor) { - var pos = editor.getCursorPosition(); - editor.selection.moveTo(pos.row, pos.column); - editor.selection.selectLine(); - registers._default.isLine = true; - registers._default.text = editor.getCopyText().replace(/\n$/, ""); - editor.selection.moveTo(pos.row, pos.column); - } -}; -}); diff --git a/lib/ace/keyboard/vim/registers.js b/lib/ace/keyboard/vim/registers.js deleted file mode 100644 index ef929a35..00000000 --- a/lib/ace/keyboard/vim/registers.js +++ /dev/null @@ -1,42 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2010, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ - -define(function(require, exports, module) { - -"never use strict"; - -module.exports = { - _default: { - text: "", - isLine: false - } -}; - -}); diff --git a/lib/ace/keyboard/vim2.js b/lib/ace/keyboard/vim2.js deleted file mode 100644 index 0e860db1..00000000 --- a/lib/ace/keyboard/vim2.js +++ /dev/null @@ -1,5960 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Supported keybindings: - * - * Motion: - * h, j, k, l - * gj, gk - * e, E, w, W, b, B, ge, gE - * f, F, t, T - * $, ^, 0, -, +, _ - * gg, G - * % - * ', ` - * - * Operator: - * d, y, c - * dd, yy, cc - * g~, g~g~ - * >, <, >>, << - * - * Operator-Motion: - * x, X, D, Y, C, ~ - * - * Action: - * a, i, s, A, I, S, o, O - * zz, z., z, zt, zb, z- - * J - * u, Ctrl-r - * m - * r - * - * Modes: - * ESC - leave insert mode, visual mode, and clear input state. - * Ctrl-[, Ctrl-c - same as ESC. - * - * Registers: unnamed, -, a-z, A-Z, 0-9 - * (Does not respect the special case for number registers when delete - * operator is made with these commands: %, (, ), , /, ?, n, N, {, } ) - * TODO: Implement the remaining registers. - * Marks: a-z, A-Z, and 0-9 - * TODO: Implement the remaining special marks. They have more complex - * behavior. - * - * Events: - * 'vim-mode-change' - raised on the editor anytime the current mode changes, - * Event object: {mode: "visual", subMode: "linewise"} - * - * Code structure: - * 1. Default keymap - * 2. Variable declarations and short basic helpers - * 3. Instance (External API) implementation - * 4. Internal state tracking objects (input state, counter) implementation - * and instanstiation - * 5. Key handler (the main command dispatcher) implementation - * 6. Motion, operator, and action implementations - * 7. Helper functions for the key handler, motions, operators, and actions - * 8. Set up Vim to work as a keymap for CodeMirror. - */ - -define(function(require, exports, module) { - 'use strict'; - - /* function log() { - var d = ""; - function format(p) { - if (typeof p != "object") - return p + "" - if ("line" in p) { - return p.line + ":" + p.ch - } - if ("anchor" in p) { - return format(p.anchor) + "->" + format(p.head) - } - if (Array.isArray(p)) - return "[" + p.map(function(x) {return format(x)})+"]" - return JSON.stringify(p) - } - for (var i = 0; i < arguments.length; i++) { - var p = arguments[i] - var f = format(p) - d+= f+" " - } - console.log(d) - } */ - var Range = require("../range").Range; - var EventEmitter = require("../lib/event_emitter").EventEmitter; - var dom = require("../lib/dom"); - var oop = require("../lib/oop"); - var KEYS = require("../lib/keys"); - var event = require("../lib/event"); - var Search = require("../search").Search; - var useragent = require("../lib/useragent"); - var SearchHighlight = require("../search_highlight").SearchHighlight; - var multiSelectCommands = require("../commands/multi_select_commands"); - require("../multi_select"); - - var CodeMirror = function(ace) { - this.ace = ace; - this.state = {}; - this.marks = {}; - this.$uid = 0; - this.onChange = this.onChange.bind(this); - this.onSelectionChange = this.onSelectionChange.bind(this); - this.onBeforeEndOperation = this.onBeforeEndOperation.bind(this); - this.ace.on('change', this.onChange); - this.ace.on('changeSelection', this.onSelectionChange); - this.ace.on('beforeEndOperation', this.onBeforeEndOperation); - }; - CodeMirror.Pos = function(line, ch) { - if (!(this instanceof Pos)) return new Pos(line, ch); - this.line = line; this.ch = ch; - }; - CodeMirror.defineOption = function(name, val, setter) {}; - CodeMirror.commands = { - redo: function(cm) { cm.ace.redo(); }, - undo: function(cm) { cm.ace.undo(); }, - newlineAndIndent: function(cm) { cm.ace.insert("\n"); }, - }; - CodeMirror.keyMap = {}; - CodeMirror.addClass = CodeMirror.rmClass = - CodeMirror.e_stop = function() {}; - CodeMirror.keyName = function(e) { - if (e.key) return e.key; - var key = (KEYS[e.keyCode] || ""); - if (key.length == 1) key = key.toUpperCase(); - key = event.getModifierString(e).replace(/(^|-)\w/g, function(m) { - return m.toUpperCase(); - }) + key; - return key; - }; - CodeMirror.keyMap['default'] = function(key) { - return function(cm) { - var cmd = cm.ace.commands.commandKeyBinding[key.toLowerCase()]; - return cmd && cm.ace.execCommand(cmd) !== false; - }; - }; - CodeMirror.lookupKey = function lookupKey(key, map, handle) { - if (typeof map == "string") - map = CodeMirror.keyMap[map]; - var found = typeof map == "function" ? map(key) : map[key]; - if (found === false) return "nothing"; - if (found === "...") return "multi"; - if (found != null && handle(found)) return "handled"; - - if (map.fallthrough) { - if (!Array.isArray(map.fallthrough)) - return lookupKey(key, map.fallthrough, handle); - for (var i = 0; i < map.fallthrough.length; i++) { - var result = lookupKey(key, map.fallthrough[i], handle); - if (result) return result; - } - } - }; - - CodeMirror.signal = function(o, name, e) { return o._signal(name, e) }; - CodeMirror.on = event.addListener; - CodeMirror.off = event.removeListener; -(function() { - oop.implement(CodeMirror.prototype, EventEmitter); - - this.destroy = function() { - this.ace.off('change', this.onChange); - this.ace.off('changeSelection', this.onSelectionChange); - this.ace.off('beforeEndOperation', this.onBeforeEndOperation); - this.removeOverlay(); - }; - this.virtualSelectionMode = function() { - return this.ace.inVirtualSelectionMode && this.ace.selection.index - }; - this.onChange = function(delta) { - var oldDelta = delta.data; - delta = { - start: oldDelta.range.start, - end: oldDelta.range.end, - action: oldDelta.action, - lines: oldDelta.lines || [oldDelta.text] - };// v1.2 api compatibility - if (delta.action[0] == 'i') { - var change = { text: delta.lines }; - var curOp = this.curOp = this.curOp || {}; - if (!curOp.changeHandlers) - curOp.changeHandlers = this._eventRegistry["change"] && this._eventRegistry["change"].slice(); - if (this.virtualSelectionMode()) return; - if (!curOp.lastChange) { - curOp.lastChange = curOp.change = change; - } else { - curOp.lastChange.next = curOp.lastChange = change; - } - } - this.$updateMarkers(delta); - }; - this.onSelectionChange = function() { - var curOp = this.curOp = this.curOp || {}; - if (!curOp.cursorActivityHandlers) - curOp.cursorActivityHandlers = this._eventRegistry["cursorActivity"] && this._eventRegistry["cursorActivity"].slice(); - this.curOp.cursorActivity = true; - if (this.ace.inMultiSelectMode) { - this.ace.keyBinding.removeKeyboardHandler(multiSelectCommands.keyboardHandler); - } - }; - this.operation = function(fn, force) { - if (!force && this.curOp || force && this.curOp && this.curOp.force) { - return fn(); - } - if (force || !this.ace.curOp) { - if (this.curOp) - this.onBeforeEndOperation(); - } - if (!this.ace.curOp) { - var prevOp = this.ace.prevOp; - this.ace.startOperation({ - command: { name: "vim", scrollIntoView: "cursor" } - }); - } - var curOp = this.curOp = this.curOp || {}; - this.curOp.force = force; - var result = fn(); - if (this.ace.curOp && this.ace.curOp.command.name == "vim") { - this.ace.endOperation(); - if (!curOp.cursorActivity && !curOp.lastChange && prevOp) - this.ace.prevOp = prevOp; - } - if (force || !this.ace.curOp) { - if (this.curOp) - this.onBeforeEndOperation(); - } - return result; - }; - this.onBeforeEndOperation = function() { - var op = this.curOp; - if (op) { - if (op.change) { this.signal("change", op.change, op); } - if (op && op.cursorActivity) { this.signal("cursorActivity", null, op); } - this.curOp = null; - } - }; - - this.signal = function(eventName, e, handlers) { - var listeners = handlers ? handlers[eventName + "Handlers"] - : (this._eventRegistry || {})[eventName]; - if (!listeners) - return; - listeners = listeners.slice(); - for (var i=0; i 0) { - point.row += rowShift; - point.column += point.row == end.row ? colShift : 0; - continue; - } - if (!isInsert && cmp2 <= 0) { - point.row = start.row; - point.column = start.column; - if (cmp2 === 0) - point.bias = 1 - } - } - }; - var Marker = function(cm, id, row, column) { - this.cm = cm; - this.id = id; - this.row = row; - this.column = column; - cm.marks[this.id] = this; - }; - Marker.prototype.clear = function() { delete this.cm.marks[this.id] }; - Marker.prototype.find = function() { return toCmPos(this) }; - this.setBookmark = function(cursor, options) { - var bm = new Marker(this, this.$uid++, cursor.line, cursor.ch); - if (!options || !options.insertLeft) - bm.$insertRight = true; - this.marks[bm.id] = bm; - return bm; - }; - this.moveH = function(increment, unit) { - if (unit == 'char') { - var sel = this.ace.selection; - sel.clearSelection(); - sel.moveCursorBy(0, increment); - } - }; - this.findPosV = function(start, amaount, unit, goalColumn) { - if (unit == 'line') { - var screenPos = this.ace.session.documentToScreenPosition(start.line, start.ch); - if (goalColumn != null) - screenPos.column = goalColumn; - screenPos.row += amaount; - // not what codemirror does but vim mode needs only it - screenPos.row = Math.min(Math.max(0, screenPos.row), this.ace.session.getScreenLength() - 1); - var pos = this.ace.session.screenToDocumentPosition(screenPos.row, screenPos.column); - return toCmPos(pos); - } else { - debugger; - } - }; - this.charCoords = function(pos, mode) { - if (mode == 'div' || !mode) { - var sc = this.ace.session.documentToScreenPosition(pos.line, pos.ch); - return {left: sc.column, top: sc.row}; - }if (mode == 'local') { - var renderer = this.ace.renderer; - var sc = this.ace.session.documentToScreenPosition(pos.line, pos.ch); - var lh = renderer.layerConfig.lineHeight; - var cw = renderer.layerConfig.characterWidth; - var top = lh * sc.row; - return {left: sc.column * cw, top: top, bottom: top + lh}; - } - }; - this.coordsChar = function(pos, mode) { - var renderer = this.ace.renderer; - if (mode == 'local') { - var row = Math.max(0, Math.floor(pos.top / renderer.lineHeight)); - var col = Math.max(0, Math.floor(pos.left / renderer.characterWidth)); - var ch = renderer.session.screenToDocumentPosition(row, col); - return toCmPos(ch); - } else if (mode == 'div') { - throw "not implemented"; - } - }; - this.openDialog = function() { - debugger - }; - this.getSearchCursor = function(query, pos, caseFold) { - var caseSensitive = false; - var isRegexp = false; - if (query instanceof RegExp && !query.global) { - caseSensitive = !query.ignoreCase; - query = query.source; - isRegexp = true; - } - var search = new Search(); - if (pos.ch == undefined) pos.ch = Number.MAX_VALUE; - var acePos = {row: pos.line, column: pos.ch}; - var cm = this; - var last = null; - return { - findNext: function() { return this.find(false) }, - findPrevious: function() {return this.find(true) }, - find: function(back) { - search.setOptions({ - needle: query, - caseSensitive: caseSensitive, - wrap: false, - backwards: back, - regExp: isRegexp, - start: last || acePos - }); - var range = search.find(cm.ace.session); - if (range && range.isEmpty()) { - if (cm.getLine(range.start.row).length == range.start.column) { - search.$options.start = range; - range = search.find(cm.ace.session); - } - } - last = range; - return last; - }, - from: function() { return last && toCmPos(last.start) }, - to: function() { return last && toCmPos(last.end) }, - replace: function(text) { - if (last) { - last.end = cm.ace.session.doc.replace(last, text); - } - } - }; - }; - this.scrollTo = function(x, y) { - var renderer = this.ace.renderer; - var config = renderer.layerConfig; - var maxHeight = config.maxHeight; - maxHeight -= (renderer.$size.scrollerHeight - renderer.lineHeight) * renderer.$scrollPastEnd; - if (y != null) this.ace.session.setScrollTop(Math.max(0, Math.min(y, maxHeight))); - if (x != null) this.ace.session.setScrollLeft(Math.max(0, Math.min(x, config.width))); - }; - this.scrollInfo = function() { return 0; }; - this.scrollIntoView = function(pos, margin) { - if (pos) - this.ace.renderer.scrollCursorIntoView(toAcePos(pos), null, margin); - }; - this.getLine = function(row) { return this.ace.session.getLine(row) }; - this.getRange = function(s, e) { - return this.ace.session.getTextRange(new Range(s.line, s.ch, e.line, e.ch)); - }; - this.replaceRange = function(text, s, e) { - if (!e) e = s; - return this.ace.session.replace(new Range(s.line, s.ch, e.line, e.ch), text); - }; - this.replaceSelections = function(p) { - var sel = this.ace.selection; - if (this.ace.inVirtualSelectionMode) { - this.ace.session.replace(sel.getRange(), p[0] || ""); - return; - } - sel.inVirtualSelectionMode = true; - var ranges = sel.rangeList.ranges; - if (!ranges.length) ranges = [this.ace.multiSelect.getRange()]; - for (var i = ranges.length; i--;) - this.ace.session.replace(ranges[i], p[i] || ""); - sel.inVirtualSelectionMode = false; - }; - this.getSelection = function() { - return this.ace.getSelectedText(); - }; - this.getSelections = function() { - return this.listSelections().map(function(x) { - return this.getRange(x.anchor, x.head); - }, this); - }; - this.getInputField = function() { - return this.ace.textInput.getElement(); - }; - this.getWrapperElement = function() { - return this.ace.containter; - }; - var optMap = { - indentWithTabs: "useSoftTabs", - indentUnit: "tabSize", - firstLineNumber: "firstLineNumber" - }; - this.setOption = function(name, val) { - this.state[name] = val; - switch (name) { - case 'indentWithTabs': - name = optMap[name]; - val = !val; - break; - default: - name = optMap[name]; - } - if (name) - this.ace.setOption(name, val); - }; - this.getOption = function(name, val) { - var aceOpt = optMap[name]; - if (aceOpt) - val = this.ace.getOption(aceOpt); - switch (name) { - case 'indentWithTabs': - name = optMap[name]; - return !val; - } - return aceOpt ? val : this.state[name]; - }; - this.toggleOverwrite = function(on) { - this.state.overwrite = on; - return this.ace.setOverwrite(on); - }; - this.addOverlay = function(o) { - if (!this.$searchHighlight || !this.$searchHighlight.session) { - var highlight = new SearchHighlight(null, "ace_highlight-marker", "text"); - var marker = this.ace.session.addDynamicMarker(highlight); - highlight.id = marker.id; - highlight.session = this.ace.session; - highlight.destroy = function(o) { - highlight.session.off("change", highlight.updateOnChange); - highlight.session.off("changeEditor", highlight.destroy); - highlight.session.removeMarker(highlight.id); - highlight.session = null; - }; - highlight.updateOnChange = function(delta) { - delta = delta.data.range;// v1.2 api compatibility - var row = delta.start.row; - if (row == delta.end.row) highlight.cache[row] = undefined; - else highlight.cache.splice(row, highlight.cache.length); - } - highlight.session.on("changeEditor", highlight.destroy); - highlight.session.on("change", highlight.updateOnChange); - } - var re = new RegExp(o.query.source, "gmi"); - console.log(re) - this.$searchHighlight = o.highlight = highlight; - this.$searchHighlight.setRegexp(re); - this.ace.renderer.updateBackMarkers(); - }; - this.removeOverlay = function(o) { - if (this.$searchHighlight && this.$searchHighlight.session) { - this.$searchHighlight.destroy(); - } - }; - this.getScrollInfo = function() { - var renderer = this.ace.renderer; - var config = renderer.layerConfig; - return { - left: renderer.scrollLeft, - top: renderer.scrollTop, - height: config.maxHeight, - width: config.width, - clientHeight: config.height, - clientWidth: config.width - }; - }; - this.getValue = function() { - return this.ace.getValue(); - }; - this.setValue = function(v) { - return this.ace.setValue(v); - }; - this.getTokenTypeAt = function(pos) { - var token = this.ace.session.getTokenAt(pos.line, pos.ch); - return token && /comment|string/.test(token.type) ? "string" : ""; - }; - this.findMatchingBracket = function(pos) { - var m = this.ace.session.findMatchingBracket(toAcePos(pos)); - return {to: m && toCmPos(m)}; - }; - this.indentLine = function(line, method) { - if (method === true) - this.ace.session.indentRows(line, line, "\t"); - else if (method === false) - this.ace.session.outdentRows(new Range(line, 0, line, 0)); - }; - this.indexFromPos = function(pos) { - return this.ace.session.doc.positionToIndex(toAcePos(pos)); - }; - this.posFromIndex = function(index) { - return toCmPos(this.ace.session.doc.indexToPosition(index)); - }; - this.focus = function(index) { - return this.ace.focus(); - }; - this.blur = function(index) { - return this.ace.blur(); - }; - this.defaultTextHeight = function(index) { - return this.ace.renderer.layerConfig.lineHeight; - }; - this.scanForBracket = function(pos, dir, _, options) { - var re = options.bracketRegex.source; - if (dir == 1) { - var m = this.ace.session.$findClosingBracket(re.slice(1, 2), toAcePos(pos), /paren|text/); - } else { - var m = this.ace.session.$findOpeningBracket(re.slice(-2, -1), {row: pos.line, column: pos.ch + 1}, /paren|text/); - } - return m && {pos: toCmPos(m)}; - }; - this.refresh = function() { - return this.ace.resize(true); - }; -}).call(CodeMirror.prototype); - function toAcePos(cmPos) { - return {row: cmPos.line, column: cmPos.ch}; - } - function toCmPos(acePos) { - return new Pos(acePos.row, acePos.column); - } - - var StringStream = CodeMirror.StringStream = function(string, tabSize) { - this.pos = this.start = 0; - this.string = string; - this.tabSize = tabSize || 8; - this.lastColumnPos = this.lastColumnValue = 0; - this.lineStart = 0; - }; - - StringStream.prototype = { - eol: function() {return this.pos >= this.string.length;}, - sol: function() {return this.pos == this.lineStart;}, - peek: function() {return this.string.charAt(this.pos) || undefined;}, - next: function() { - if (this.pos < this.string.length) - return this.string.charAt(this.pos++); - }, - eat: function(match) { - var ch = this.string.charAt(this.pos); - if (typeof match == "string") var ok = ch == match; - else var ok = ch && (match.test ? match.test(ch) : match(ch)); - if (ok) {++this.pos; return ch;} - }, - eatWhile: function(match) { - var start = this.pos; - while (this.eat(match)){} - return this.pos > start; - }, - eatSpace: function() { - var start = this.pos; - while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; - return this.pos > start; - }, - skipToEnd: function() {this.pos = this.string.length;}, - skipTo: function(ch) { - var found = this.string.indexOf(ch, this.pos); - if (found > -1) {this.pos = found; return true;} - }, - backUp: function(n) {this.pos -= n;}, - column: function() { - throw "not implemented"; - }, - indentation: function() { - throw "not implemented"; - }, - match: function(pattern, consume, caseInsensitive) { - if (typeof pattern == "string") { - var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; - var substr = this.string.substr(this.pos, pattern.length); - if (cased(substr) == cased(pattern)) { - if (consume !== false) this.pos += pattern.length; - return true; - } - } else { - var match = this.string.slice(this.pos).match(pattern); - if (match && match.index > 0) return null; - if (match && consume !== false) this.pos += match[0].length; - return match; - } - }, - current: function(){return this.string.slice(this.start, this.pos);}, - hideFirstChars: function(n, inner) { - this.lineStart += n; - try { return inner(); } - finally { this.lineStart -= n; } - } - }; - -// todo replace with showCommandLine -CodeMirror.defineExtension = function(name, fn) { - CodeMirror.prototype[name] = fn; -}; -dom.importCssString(".normal-mode .ace_cursor{\ - border: 0!important;\ - background-color: red;\ - opacity: 0.5;\ -}.ace_dialog {\ - position: absolute;\ - left: 0; right: 0;\ - background: white;\ - z-index: 15;\ - padding: .1em .8em;\ - overflow: hidden;\ - color: #333;\ -}\ -.ace_dialog-top {\ - border-bottom: 1px solid #eee;\ - top: 0;\ -}\ -.ace_dialog-bottom {\ - border-top: 1px solid #eee;\ - bottom: 0;\ -}\ -.ace_dialog input {\ - border: none;\ - outline: none;\ - background: transparent;\ - width: 20em;\ - color: inherit;\ - font-family: monospace;\ -}", "vimMode"); -(function() { - function dialogDiv(cm, template, bottom) { - var wrap = cm.ace.container; - var dialog; - dialog = wrap.appendChild(document.createElement("div")); - if (bottom) - dialog.className = "ace_dialog ace_dialog-bottom"; - else - dialog.className = "ace_dialog ace_dialog-top"; - - if (typeof template == "string") { - dialog.innerHTML = template; - } else { // Assuming it's a detached DOM element. - dialog.appendChild(template); - } - return dialog; - } - - function closeNotification(cm, newVal) { - if (cm.state.currentNotificationClose) - cm.state.currentNotificationClose(); - cm.state.currentNotificationClose = newVal; - } - - CodeMirror.defineExtension("openDialog", function(template, callback, options) { - if (this.virtualSelectionMode()) return; - if (!options) options = {}; - - closeNotification(this, null); - - var dialog = dialogDiv(this, template, options.bottom); - var closed = false, me = this; - function close(newVal) { - if (typeof newVal == 'string') { - inp.value = newVal; - } else { - if (closed) return; - closed = true; - dialog.parentNode.removeChild(dialog); - me.focus(); - - if (options.onClose) options.onClose(dialog); - } - } - - var inp = dialog.getElementsByTagName("input")[0], button; - if (inp) { - if (options.value) { - inp.value = options.value; - inp.select(); - } - - if (options.onInput) - CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); - if (options.onKeyUp) - CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); - - CodeMirror.on(inp, "keydown", function(e) { - if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } - if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { - inp.blur(); - CodeMirror.e_stop(e); - close(); - } - if (e.keyCode == 13) callback(inp.value); - }); - - if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close); - - inp.focus(); - } else if (button = dialog.getElementsByTagName("button")[0]) { - CodeMirror.on(button, "click", function() { - close(); - me.focus(); - }); - - if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); - - button.focus(); - } - return close; - }); - - CodeMirror.defineExtension("openNotification", function(template, options) { - if (this.virtualSelectionMode()) return; - closeNotification(this, close); - var dialog = dialogDiv(this, template, options && options.bottom); - var closed = false, doneTimer; - var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; - - function close() { - if (closed) return; - closed = true; - clearTimeout(doneTimer); - dialog.parentNode.removeChild(dialog); - } - - CodeMirror.on(dialog, 'click', function(e) { - CodeMirror.e_preventDefault(e); - close(); - }); - - if (duration) - doneTimer = setTimeout(close, duration); - - return close; - }); -})(); - - - var defaultKeymap = [ - // Key to key mapping. This goes first to make it possible to override - // existing mappings. - { keys: '', type: 'keyToKey', toKeys: 'h' }, - { keys: '', type: 'keyToKey', toKeys: 'l' }, - { keys: '', type: 'keyToKey', toKeys: 'k' }, - { keys: '', type: 'keyToKey', toKeys: 'j' }, - { keys: '', type: 'keyToKey', toKeys: 'l' }, - { keys: '', type: 'keyToKey', toKeys: 'h' }, - { keys: '', type: 'keyToKey', toKeys: 'W' }, - { keys: '', type: 'keyToKey', toKeys: 'B' }, - { keys: '', type: 'keyToKey', toKeys: 'w' }, - { keys: '', type: 'keyToKey', toKeys: 'b' }, - { keys: '', type: 'keyToKey', toKeys: 'j' }, - { keys: '', type: 'keyToKey', toKeys: 'k' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, - { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, - { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' }, - { keys: 's', type: 'keyToKey', toKeys: 'xi', context: 'visual'}, - { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' }, - { keys: 'S', type: 'keyToKey', toKeys: 'dcc', context: 'visual' }, - { keys: '', type: 'keyToKey', toKeys: '0' }, - { keys: '', type: 'keyToKey', toKeys: '$' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' }, - // Motions - { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }}, - { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }}, - { keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true }}, - { keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }}, - { keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true }}, - { keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true }}, - { keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true }}, - { keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true }}, - { keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false }}, - { keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false }}, - { keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true }}, - { keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true }}, - { keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }}, - { keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }}, - { keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true }}, - { keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true }}, - { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }}, - { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }}, - { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }}, - { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }}, - { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }}, - { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }}, - { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }}, - { keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }}, - { keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }}, - { keys: '0', type: 'motion', motion: 'moveToStartOfLine' }, - { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true }}, - { keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar:true }}, - { keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }}, - { keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true }}, - { keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true }}, - { keys: 'f', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true , inclusive: true }}, - { keys: 'F', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false }}, - { keys: 't', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true }}, - { keys: 'T', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false }}, - { keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true }}, - { keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false }}, - { keys: '\'', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true, linewise: true}}, - { keys: '`', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true}}, - { keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } }, - { keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } }, - { keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } }, - { keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } }, - // the next two aren't motions but must come before more general motion declarations - { keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}}, - { keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}}, - { keys: ']', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true}}, - { keys: '[', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true}}, - { keys: '|', type: 'motion', motion: 'moveToColumn'}, - { keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context:'visual'}, - { keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'}, - // Operators - { keys: 'd', type: 'operator', operator: 'delete' }, - { keys: 'y', type: 'operator', operator: 'yank' }, - { keys: 'c', type: 'operator', operator: 'change' }, - { keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true }}, - { keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false }}, - { keys: 'g~', type: 'operator', operator: 'changeCase' }, - { keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, isEdit: true }, - { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true }, - { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }}, - { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }}, - // Operator-Motion dual commands - { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }}, - { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }}, - { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, operatorMotionArgs: { visualLine: true }}, - { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, operatorMotionArgs: { visualLine: true }}, - { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, operatorMotionArgs: { visualLine: true }}, - { keys: '~', type: 'operatorMotion', operator: 'changeCase', operatorArgs: { shouldMoveCursor: true }, motion: 'moveByCharacters', motionArgs: { forward: true }}, - { keys: '', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' }, - // Actions - { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }}, - { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }}, - { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }}, - { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }}, - { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' }, - { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, - { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, - { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' }, - { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank' }}, - { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' }, - { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, - { keys: 'v', type: 'action', action: 'toggleVisualMode' }, - { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }}, - { keys: '', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, - { keys: 'gv', type: 'action', action: 'reselectLastSelection' }, - { keys: 'J', type: 'action', action: 'joinLines', isEdit: true }, - { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }}, - { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }}, - { keys: 'r', type: 'action', action: 'replace', isEdit: true }, - { keys: '@', type: 'action', action: 'replayMacro' }, - { keys: 'q', type: 'action', action: 'enterMacroRecordMode' }, - // Handle Replace-mode as a special case of insert mode. - { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }}, - { keys: 'u', type: 'action', action: 'undo', context: 'normal' }, - { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true }, - { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true }, - { keys: '', type: 'action', action: 'redo' }, - { keys: 'm', type: 'action', action: 'setMark' }, - { keys: '"', type: 'action', action: 'setRegister' }, - { keys: 'zz', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }}, - { keys: 'z.', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: 'zt', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }}, - { keys: 'z', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: 'z-', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }}, - { keys: 'zb', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: '.', type: 'action', action: 'repeatLastEdit' }, - { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}}, - { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}}, - // Text object motions - { keys: 'a', type: 'motion', motion: 'textObjectManipulation' }, - { keys: 'i', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }}, - // Search - { keys: '/', type: 'search', searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }}, - { keys: '?', type: 'search', searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }}, - { keys: '*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, - { keys: '#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, - { keys: 'g*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }}, - { keys: 'g#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }}, - // Ex command - { keys: ':', type: 'ex' } - ]; - - var Pos = CodeMirror.Pos; - - var modifierCodes = [16, 17, 18, 91]; - var specialKey = {Enter:'CR',Backspace:'BS',Delete:'Del'}; - var mac = /Mac/.test(navigator.platform); - var Vim = function() { return vimApi; } //{ - function lookupKey(e) { - var keyCode = e.keyCode; - if (modifierCodes.indexOf(keyCode) != -1) { return; } - var hasModifier = e.ctrlKey || e.metaKey; - var key = CodeMirror.keyNames[keyCode]; - key = specialKey[key] || key; - var name = ''; - if (e.ctrlKey) { name += 'C-'; } - if (e.altKey) { name += 'A-'; } - if (mac && e.metaKey || (!hasModifier && e.shiftKey) && key.length < 2) { - // Shift key bindings can only specified for special characters. - return; - } else if (e.shiftKey && !/^[A-Za-z]$/.test(key)) { - name += 'S-'; - } - if (key.length == 1) { key = key.toLowerCase(); } - name += key; - if (name.length > 1) { name = '<' + name + '>'; } - return name; - } - // Keys with modifiers are handled using keydown due to limitations of - // keypress event. - function handleKeyDown(cm, e) { - var name = lookupKey(e); - if (!name) { return; } - - CodeMirror.signal(cm, 'vim-keypress', name); - if (CodeMirror.Vim.handleKey(cm, name, 'user')) { - CodeMirror.e_stop(e); - } - } - // Keys without modifiers are handled using keypress to work best with - // non-standard keyboard layouts. - function handleKeyPress(cm, e) { - var code = e.charCode || e.keyCode; - if (e.ctrlKey || e.metaKey || e.altKey || - e.shiftKey && code < 32) { return; } - var name = String.fromCharCode(code); - - CodeMirror.signal(cm, 'vim-keypress', name); - if (CodeMirror.Vim.handleKey(cm, name, 'user')) { - CodeMirror.e_stop(e); - } - } - - function enterVimMode(cm) { - cm.setOption('disableInput', true); - cm.setOption('showCursorWhenSelecting', false); - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - cm.on('cursorActivity', onCursorActivity); - maybeInitVimState(cm); - CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); - cm.on('keypress', handleKeyPress); - cm.on('keydown', handleKeyDown); - CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); - } - - function leaveVimMode(cm) { - cm.setOption('disableInput', false); - cm.off('cursorActivity', onCursorActivity); - CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); - cm.state.vim = null; - cm.off('keypress', handleKeyPress); - cm.off('keydown', handleKeyDown); - } - - function detachVimMap(cm, next) { - if (this == CodeMirror.keyMap.vim) - CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor"); - - if (!next || next.attach != attachVimMap) - leaveVimMode(cm, false); - } - function attachVimMap(cm, prev) { - if (this == CodeMirror.keyMap.vim) - CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); - - if (!prev || prev.attach != attachVimMap) - enterVimMode(cm); - } - - // Deprecated, simply setting the keymap works again. - CodeMirror.defineOption('vimMode', false, function(cm, val, prev) { - if (val && cm.getOption("keyMap") != "vim") - cm.setOption("keyMap", "vim"); - else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap"))) - cm.setOption("keyMap", "default"); - }); - function getOnPasteFn(cm) { - var vim = cm.state.vim; - if (!vim.onPasteFn) { - vim.onPasteFn = function() { - if (!vim.insertMode) { - cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); - actions.enterInsertMode(cm, {}, vim); - } - }; - } - return vim.onPasteFn; - } - - var numberRegex = /[\d]/; - var wordRegexp = [(/\w/), (/[^\w\s]/)], bigWordRegexp = [(/\S/)]; - function makeKeyRange(start, size) { - var keys = []; - for (var i = start; i < start + size; i++) { - keys.push(String.fromCharCode(i)); - } - return keys; - } - var upperCaseAlphabet = makeKeyRange(65, 26); - var lowerCaseAlphabet = makeKeyRange(97, 26); - var numbers = makeKeyRange(48, 10); - var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']); - var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']); - - function isLine(cm, line) { - return line >= cm.firstLine() && line <= cm.lastLine(); - } - function isLowerCase(k) { - return (/^[a-z]$/).test(k); - } - function isMatchableSymbol(k) { - return '()[]{}'.indexOf(k) != -1; - } - function isNumber(k) { - return numberRegex.test(k); - } - function isUpperCase(k) { - return (/^[A-Z]$/).test(k); - } - function isWhiteSpaceString(k) { - return (/^\s*$/).test(k); - } - function inArray(val, arr) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] == val) { - return true; - } - } - return false; - } - - var options = {}; - function defineOption(name, defaultValue, type) { - if (defaultValue === undefined) { throw Error('defaultValue is required'); } - if (!type) { type = 'string'; } - var opt = name; - if (typeof name == "string") - opt = { - type: type, - defaultValue: defaultValue - }; - else - name = opt.name; - options[name] = opt; - setOption(name, defaultValue); - } - - function setOption(name, value, cm) { - var option = options[name]; - if (!option) { - throw Error('Unknown option: ' + name); - } - if (option.type == 'boolean') { - if (value && value !== true) { - throw Error('Invalid argument: ' + name + '=' + value); - } else if (value !== false) { - // Boolean options are set to true if value is not defined. - value = true; - } - } - option.value = value; - if (option.set) option.set(value, cm); - } - - function getOption(name) { - var option = options[name]; - if (!option) { - throw Error('Unknown option: ' + name); - } - return option.value; - } - - var createCircularJumpList = function() { - var size = 100; - var pointer = -1; - var head = 0; - var tail = 0; - var buffer = new Array(size); - function add(cm, oldCur, newCur) { - var current = pointer % size; - var curMark = buffer[current]; - function useNextSlot(cursor) { - var next = ++pointer % size; - var trashMark = buffer[next]; - if (trashMark) { - trashMark.clear(); - } - buffer[next] = cm.setBookmark(cursor); - } - if (curMark) { - var markPos = curMark.find(); - // avoid recording redundant cursor position - if (markPos && !cursorEqual(markPos, oldCur)) { - useNextSlot(oldCur); - } - } else { - useNextSlot(oldCur); - } - useNextSlot(newCur); - head = pointer; - tail = pointer - size + 1; - if (tail < 0) { - tail = 0; - } - } - function move(cm, offset) { - pointer += offset; - if (pointer > head) { - pointer = head; - } else if (pointer < tail) { - pointer = tail; - } - var mark = buffer[(size + pointer) % size]; - // skip marks that are temporarily removed from text buffer - if (mark && !mark.find()) { - var inc = offset > 0 ? 1 : -1; - var newCur; - var oldCur = cm.getCursor(); - do { - pointer += inc; - mark = buffer[(size + pointer) % size]; - // skip marks that are the same as current position - if (mark && - (newCur = mark.find()) && - !cursorEqual(oldCur, newCur)) { - break; - } - } while (pointer < head && pointer > tail); - } - return mark; - } - return { - cachedCursor: undefined, //used for # and * jumps - add: add, - move: move - }; - }; - - // Returns an object to track the changes associated insert mode. It - // clones the object that is passed in, or creates an empty object one if - // none is provided. - var createInsertModeChanges = function(c) { - if (c) { - // Copy construction - return { - changes: c.changes, - expectCursorActivityForChange: c.expectCursorActivityForChange - }; - } - return { - // Change list - changes: [], - // Set to true on change, false on cursorActivity. - expectCursorActivityForChange: false - }; - }; - - function MacroModeState() { - this.latestRegister = undefined; - this.isPlaying = false; - this.isRecording = false; - this.replaySearchQueries = []; - this.onRecordingDone = undefined; - this.lastInsertModeChanges = createInsertModeChanges(); - } - MacroModeState.prototype = { - exitMacroRecordMode: function() { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.onRecordingDone) { - macroModeState.onRecordingDone(); // close dialog - } - macroModeState.onRecordingDone = undefined; - macroModeState.isRecording = false; - }, - enterMacroRecordMode: function(cm, registerName) { - var register = - vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.clear(); - this.latestRegister = registerName; - if (cm.openDialog) { - this.onRecordingDone = cm.openDialog( - '(recording)['+registerName+']', null, {bottom:true}); - } - this.isRecording = true; - } - } - }; - - function maybeInitVimState(cm) { - if (!cm.state.vim) { - // Store instance state in the CodeMirror object. - cm.state.vim = { - inputState: new InputState(), - // Vim's input state that triggered the last edit, used to repeat - // motions and operators with '.'. - lastEditInputState: undefined, - // Vim's action command before the last edit, used to repeat actions - // with '.' and insert mode repeat. - lastEditActionCommand: undefined, - // When using jk for navigation, if you move from a longer line to a - // shorter line, the cursor may clip to the end of the shorter line. - // If j is pressed again and cursor goes to the next line, the - // cursor should go back to its horizontal position on the longer - // line if it can. This is to keep track of the horizontal position. - lastHPos: -1, - // Doing the same with screen-position for gj/gk - lastHSPos: -1, - // The last motion command run. Cleared if a non-motion command gets - // executed in between. - lastMotion: null, - marks: {}, - // Mark for rendering fake cursor for visual mode. - fakeCursor: null, - insertMode: false, - // Repeat count for changes made in insert mode, triggered by key - // sequences like 3,i. Only exists when insertMode is true. - insertModeRepeat: undefined, - visualMode: false, - // If we are in visual line mode. No effect if visualMode is false. - visualLine: false, - visualBlock: false, - lastSelection: null, - lastPastedText: null - }; - } - return cm.state.vim; - } - var vimGlobalState; - function resetVimGlobalState() { - vimGlobalState = { - // The current search query. - searchQuery: null, - // Whether we are searching backwards. - searchIsReversed: false, - // Replace part of the last substituted pattern - lastSubstituteReplacePart: undefined, - jumpList: createCircularJumpList(), - macroModeState: new MacroModeState, - // Recording latest f, t, F or T motion command. - lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''}, - registerController: new RegisterController({}), - // search history buffer - searchHistoryController: new HistoryController({}), - // ex Command history buffer - exCommandHistoryController : new HistoryController({}) - }; - for (var optionName in options) { - var option = options[optionName]; - option.value = option.defaultValue; - } - } - - var lastInsertModeKeyTimer; - var vimApi= { - buildKeyMap: function() { - // TODO: Convert keymap into dictionary format for fast lookup. - }, - // Testing hook, though it might be useful to expose the register - // controller anyways. - getRegisterController: function() { - return vimGlobalState.registerController; - }, - // Testing hook. - resetVimGlobalState_: resetVimGlobalState, - - // Testing hook. - getVimGlobalState_: function() { - return vimGlobalState; - }, - - // Testing hook. - maybeInitVimState_: maybeInitVimState, - - InsertModeKey: InsertModeKey, - map: function(lhs, rhs, ctx) { - // Add user defined key bindings. - exCommandDispatcher.map(lhs, rhs, ctx); - }, - setOption: setOption, - getOption: getOption, - defineOption: defineOption, - defineEx: function(name, prefix, func){ - if (name.indexOf(prefix) !== 0) { - throw new Error('(Vim.defineEx) "'+prefix+'" is not a prefix of "'+name+'", command not registered'); - } - exCommands[name]=func; - exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'}; - }, - // This is the outermost function called by CodeMirror, after keys have - // been mapped to their Vim equivalents. - handleKey: function(cm, key, origin) { - var vim = maybeInitVimState(cm); - function handleMacroRecording() { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isRecording) { - if (key == 'q') { - macroModeState.exitMacroRecordMode(); - clearInputState(cm); - return true; - } - if (origin != 'mapping') { - logKey(macroModeState, key); - } - } - } - function handleEsc() { - if (key == '') { - // Clear input state and get back to normal mode. - clearInputState(cm); - if (vim.visualMode) { - exitVisualMode(cm); - } else if (vim.insertMode) { - exitInsertMode(cm); - } - return true; - } - } - function doKeyToKey(keys) { - // TODO: prevent infinite recursion. - var match; - while (keys) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - match = (/<\w+-.+?>|<\w+>|./).exec(keys); - key = match[0]; - keys = keys.substring(match.index + key.length); - CodeMirror.Vim.handleKey(cm, key, 'mapping'); - } - } - - function handleKeyInsertMode() { - if (handleEsc()) { return true; } - var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; - var keysAreChars = key.length == 1; - var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); - // Need to check all key substrings in insert mode. - while (keys.length > 1 && match.type != 'full') { - var keys = vim.inputState.keyBuffer = keys.slice(1); - var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); - if (thisMatch.type != 'none') { match = thisMatch; } - } - if (match.type == 'none') { clearInputState(cm); return false; } - else if (match.type == 'partial') { - if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } - lastInsertModeKeyTimer = window.setTimeout( - function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } }, - getOption('insertModeEscKeysTimeout')); - return !keysAreChars; - } - - if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } - if (keysAreChars) { - var here = cm.getCursor(); - cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input'); - } - clearInputState(cm); - var command = match.command; - if (command.type == 'keyToKey') { - doKeyToKey(command.toKeys); - } else { - commandDispatcher.processCommand(cm, vim, command); - } - return true; - } - - function handleKeyNonInsertMode() { - if (handleMacroRecording() || handleEsc()) { return true; }; - - var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; - if (/^[1-9]\d*$/.test(keys)) { return true; } - - var keysMatcher = /^(\d*)(.*)$/.exec(keys); - if (!keysMatcher) { clearInputState(cm); return false; } - var context = vim.visualMode ? 'visual' : - 'normal'; - var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context); - if (match.type == 'none') { clearInputState(cm); return false; } - else if (match.type == 'partial') { return true; } - - vim.inputState.keyBuffer = ''; - var command = match.command; - var keysMatcher = /^(\d*)(.*)$/.exec(keys); - if (keysMatcher[1] && keysMatcher[1] != '0') { - vim.inputState.pushRepeatDigit(keysMatcher[1]); - } - if (command.type == 'keyToKey') { - doKeyToKey(command.toKeys); - } else { - commandDispatcher.processCommand(cm, vim, command); - } - return true; - } - - return cm.operation(function() { - cm.curOp.isVimOp = true; - try { - if (vim.insertMode) { return handleKeyInsertMode(); } - else { return handleKeyNonInsertMode(); } - } catch (e) { - // clear VIM state in case it's in a bad state. - cm.state.vim = undefined; - throw e; - } - }); - }, - handleEx: function(cm, input) { - exCommandDispatcher.processCommand(cm, input); - } - }; - - // Represents the current input state. - function InputState() { - this.prefixRepeat = []; - this.motionRepeat = []; - - this.operator = null; - this.operatorArgs = null; - this.motion = null; - this.motionArgs = null; - this.keyBuffer = []; // For matching multi-key commands. - this.registerName = null; // Defaults to the unnamed register. - } - InputState.prototype.pushRepeatDigit = function(n) { - if (!this.operator) { - this.prefixRepeat = this.prefixRepeat.concat(n); - } else { - this.motionRepeat = this.motionRepeat.concat(n); - } - }; - InputState.prototype.getRepeat = function() { - var repeat = 0; - if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) { - repeat = 1; - if (this.prefixRepeat.length > 0) { - repeat *= parseInt(this.prefixRepeat.join(''), 10); - } - if (this.motionRepeat.length > 0) { - repeat *= parseInt(this.motionRepeat.join(''), 10); - } - } - return repeat; - }; - - function clearInputState(cm, reason) { - cm.state.vim.inputState = new InputState(); - CodeMirror.signal(cm, 'vim-command-done', reason); - } - - /* - * Register stores information about copy and paste registers. Besides - * text, a register must store whether it is linewise (i.e., when it is - * pasted, should it insert itself into a new line, or should the text be - * inserted at the cursor position.) - */ - function Register(text, linewise, blockwise) { - this.clear(); - this.keyBuffer = [text || '']; - this.insertModeChanges = []; - this.searchQueries = []; - this.linewise = !!linewise; - this.blockwise = !!blockwise; - } - Register.prototype = { - setText: function(text, linewise, blockwise) { - this.keyBuffer = [text || '']; - this.linewise = !!linewise; - this.blockwise = !!blockwise; - }, - pushText: function(text, linewise) { - // if this register has ever been set to linewise, use linewise. - if (linewise) { - if (!this.linewise) { - this.keyBuffer.push('\n'); - } - this.linewise = true; - } - this.keyBuffer.push(text); - }, - pushInsertModeChanges: function(changes) { - this.insertModeChanges.push(createInsertModeChanges(changes)); - }, - pushSearchQuery: function(query) { - this.searchQueries.push(query); - }, - clear: function() { - this.keyBuffer = []; - this.insertModeChanges = []; - this.searchQueries = []; - this.linewise = false; - }, - toString: function() { - return this.keyBuffer.join(''); - } - }; - - /* - * vim registers allow you to keep many independent copy and paste buffers. - * See http://usevim.com/2012/04/13/registers/ for an introduction. - * - * RegisterController keeps the state of all the registers. An initial - * state may be passed in. The unnamed register '"' will always be - * overridden. - */ - function RegisterController(registers) { - this.registers = registers; - this.unnamedRegister = registers['"'] = new Register(); - registers['.'] = new Register(); - registers[':'] = new Register(); - registers['/'] = new Register(); - } - RegisterController.prototype = { - pushText: function(registerName, operator, text, linewise, blockwise) { - if (linewise && text.charAt(0) == '\n') { - text = text.slice(1) + '\n'; - } - if (linewise && text.charAt(text.length - 1) !== '\n'){ - text += '\n'; - } - // Lowercase and uppercase registers refer to the same register. - // Uppercase just means append. - var register = this.isValidRegister(registerName) ? - this.getRegister(registerName) : null; - // if no register/an invalid register was specified, things go to the - // default registers - if (!register) { - switch (operator) { - case 'yank': - // The 0 register contains the text from the most recent yank. - this.registers['0'] = new Register(text, linewise, blockwise); - break; - case 'delete': - case 'change': - if (text.indexOf('\n') == -1) { - // Delete less than 1 line. Update the small delete register. - this.registers['-'] = new Register(text, linewise); - } else { - // Shift down the contents of the numbered registers and put the - // deleted text into register 1. - this.shiftNumericRegisters_(); - this.registers['1'] = new Register(text, linewise); - } - break; - } - // Make sure the unnamed register is set to what just happened - this.unnamedRegister.setText(text, linewise, blockwise); - return; - } - - // If we've gotten to this point, we've actually specified a register - var append = isUpperCase(registerName); - if (append) { - register.pushText(text, linewise); - } else { - register.setText(text, linewise, blockwise); - } - // The unnamed register always has the same value as the last used - // register. - this.unnamedRegister.setText(register.toString(), linewise); - }, - // Gets the register named @name. If one of @name doesn't already exist, - // create it. If @name is invalid, return the unnamedRegister. - getRegister: function(name) { - if (!this.isValidRegister(name)) { - return this.unnamedRegister; - } - name = name.toLowerCase(); - if (!this.registers[name]) { - this.registers[name] = new Register(); - } - return this.registers[name]; - }, - isValidRegister: function(name) { - return name && inArray(name, validRegisters); - }, - shiftNumericRegisters_: function() { - for (var i = 9; i >= 2; i--) { - this.registers[i] = this.getRegister('' + (i - 1)); - } - } - }; - function HistoryController() { - this.historyBuffer = []; - this.iterator; - this.initialPrefix = null; - } - HistoryController.prototype = { - // the input argument here acts a user entered prefix for a small time - // until we start autocompletion in which case it is the autocompleted. - nextMatch: function (input, up) { - var historyBuffer = this.historyBuffer; - var dir = up ? -1 : 1; - if (this.initialPrefix === null) this.initialPrefix = input; - for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i+= dir) { - var element = historyBuffer[i]; - for (var j = 0; j <= element.length; j++) { - if (this.initialPrefix == element.substring(0, j)) { - this.iterator = i; - return element; - } - } - } - // should return the user input in case we reach the end of buffer. - if (i >= historyBuffer.length) { - this.iterator = historyBuffer.length; - return this.initialPrefix; - } - // return the last autocompleted query or exCommand as it is. - if (i < 0 ) return input; - }, - pushInput: function(input) { - var index = this.historyBuffer.indexOf(input); - if (index > -1) this.historyBuffer.splice(index, 1); - if (input.length) this.historyBuffer.push(input); - }, - reset: function() { - this.initialPrefix = null; - this.iterator = this.historyBuffer.length; - } - }; - var commandDispatcher = { - matchCommand: function(keys, keyMap, inputState, context) { - var matches = commandMatches(keys, keyMap, context, inputState); - if (!matches.full && !matches.partial) { - return {type: 'none'}; - } else if (!matches.full && matches.partial) { - return {type: 'partial'}; - } - - var bestMatch; - for (var i = 0; i < matches.full.length; i++) { - var match = matches.full[i]; - if (!bestMatch) { - bestMatch = match; - } - } - if (bestMatch.keys.slice(-11) == '') { - inputState.selectedCharacter = lastChar(keys); - } - return {type: 'full', command: bestMatch}; - }, - processCommand: function(cm, vim, command) { - vim.inputState.repeatOverride = command.repeatOverride; - switch (command.type) { - case 'motion': - this.processMotion(cm, vim, command); - break; - case 'operator': - this.processOperator(cm, vim, command); - break; - case 'operatorMotion': - this.processOperatorMotion(cm, vim, command); - break; - case 'action': - this.processAction(cm, vim, command); - break; - case 'search': - this.processSearch(cm, vim, command); - clearInputState(cm); - break; - case 'ex': - case 'keyToEx': - this.processEx(cm, vim, command); - clearInputState(cm); - break; - default: - break; - } - }, - processMotion: function(cm, vim, command) { - vim.inputState.motion = command.motion; - vim.inputState.motionArgs = copyArgs(command.motionArgs); - this.evalInput(cm, vim); - }, - processOperator: function(cm, vim, command) { - var inputState = vim.inputState; - if (inputState.operator) { - if (inputState.operator == command.operator) { - // Typing an operator twice like 'dd' makes the operator operate - // linewise - inputState.motion = 'expandToLine'; - inputState.motionArgs = { linewise: true }; - this.evalInput(cm, vim); - return; - } else { - // 2 different operators in a row doesn't make sense. - clearInputState(cm); - } - } - inputState.operator = command.operator; - inputState.operatorArgs = copyArgs(command.operatorArgs); - if (vim.visualMode) { - // Operating on a selection in visual mode. We don't need a motion. - this.evalInput(cm, vim); - } - }, - processOperatorMotion: function(cm, vim, command) { - var visualMode = vim.visualMode; - var operatorMotionArgs = copyArgs(command.operatorMotionArgs); - if (operatorMotionArgs) { - // Operator motions may have special behavior in visual mode. - if (visualMode && operatorMotionArgs.visualLine) { - vim.visualLine = true; - } - } - this.processOperator(cm, vim, command); - if (!visualMode) { - this.processMotion(cm, vim, command); - } - }, - processAction: function(cm, vim, command) { - var inputState = vim.inputState; - var repeat = inputState.getRepeat(); - var repeatIsExplicit = !!repeat; - var actionArgs = copyArgs(command.actionArgs) || {}; - if (inputState.selectedCharacter) { - actionArgs.selectedCharacter = inputState.selectedCharacter; - } - // Actions may or may not have motions and operators. Do these first. - if (command.operator) { - this.processOperator(cm, vim, command); - } - if (command.motion) { - this.processMotion(cm, vim, command); - } - if (command.motion || command.operator) { - this.evalInput(cm, vim); - } - actionArgs.repeat = repeat || 1; - actionArgs.repeatIsExplicit = repeatIsExplicit; - actionArgs.registerName = inputState.registerName; - clearInputState(cm); - vim.lastMotion = null; - if (command.isEdit) { - this.recordLastEdit(vim, inputState, command); - } - actions[command.action](cm, actionArgs, vim); - }, - processSearch: function(cm, vim, command) { - if (!cm.getSearchCursor) { - // Search depends on SearchCursor. - return; - } - var forward = command.searchArgs.forward; - var wholeWordOnly = command.searchArgs.wholeWordOnly; - getSearchState(cm).setReversed(!forward); - var promptPrefix = (forward) ? '/' : '?'; - var originalQuery = getSearchState(cm).getQuery(); - var originalScrollPos = cm.getScrollInfo(); - function handleQuery(query, ignoreCase, smartCase) { - vimGlobalState.searchHistoryController.pushInput(query); - vimGlobalState.searchHistoryController.reset(); - try { - updateSearchQuery(cm, query, ignoreCase, smartCase); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + query); - return; - } - commandDispatcher.processMotion(cm, vim, { - type: 'motion', - motion: 'findNext', - motionArgs: { forward: true, toJumplist: command.searchArgs.toJumplist } - }); - } - function onPromptClose(query) { - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - handleQuery(query, true /** ignoreCase */, true /** smartCase */); - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isRecording) { - logSearchQuery(macroModeState, query); - } - } - function onPromptKeyUp(e, query, close) { - var keyName = CodeMirror.keyName(e), up; - if (keyName == 'Up' || keyName == 'Down') { - up = keyName == 'Up' ? true : false; - query = vimGlobalState.searchHistoryController.nextMatch(query, up) || ''; - close(query); - } else { - if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') - vimGlobalState.searchHistoryController.reset(); - } - var parsedQuery; - try { - parsedQuery = updateSearchQuery(cm, query, - true /** ignoreCase */, true /** smartCase */); - } catch (e) { - // Swallow bad regexes for incremental search. - } - if (parsedQuery) { - cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30); - } else { - clearSearchHighlight(cm); - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - } - } - function onPromptKeyDown(e, query, close) { - var keyName = CodeMirror.keyName(e); - if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') { - vimGlobalState.searchHistoryController.pushInput(query); - vimGlobalState.searchHistoryController.reset(); - updateSearchQuery(cm, originalQuery); - clearSearchHighlight(cm); - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - CodeMirror.e_stop(e); - close(); - cm.focus(); - } - } - switch (command.searchArgs.querySrc) { - case 'prompt': - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { - var query = macroModeState.replaySearchQueries.shift(); - handleQuery(query, true /** ignoreCase */, false /** smartCase */); - } else { - showPrompt(cm, { - onClose: onPromptClose, - prefix: promptPrefix, - desc: searchPromptDesc, - onKeyUp: onPromptKeyUp, - onKeyDown: onPromptKeyDown - }); - } - break; - case 'wordUnderCursor': - var word = expandWordUnderCursor(cm, false /** inclusive */, - true /** forward */, false /** bigWord */, - true /** noSymbol */); - var isKeyword = true; - if (!word) { - word = expandWordUnderCursor(cm, false /** inclusive */, - true /** forward */, false /** bigWord */, - false /** noSymbol */); - isKeyword = false; - } - if (!word) { - return; - } - var query = cm.getLine(word.start.line).substring(word.start.ch, - word.end.ch); - if (isKeyword && wholeWordOnly) { - query = '\\b' + query + '\\b'; - } else { - query = escapeRegex(query); - } - - // cachedCursor is used to save the old position of the cursor - // when * or # causes vim to seek for the nearest word and shift - // the cursor before entering the motion. - vimGlobalState.jumpList.cachedCursor = cm.getCursor(); - cm.setCursor(word.start); - - handleQuery(query, true /** ignoreCase */, false /** smartCase */); - break; - } - }, - processEx: function(cm, vim, command) { - function onPromptClose(input) { - // Give the prompt some time to close so that if processCommand shows - // an error, the elements don't overlap. - vimGlobalState.exCommandHistoryController.pushInput(input); - vimGlobalState.exCommandHistoryController.reset(); - exCommandDispatcher.processCommand(cm, input); - } - function onPromptKeyDown(e, input, close) { - var keyName = CodeMirror.keyName(e), up; - if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') { - vimGlobalState.exCommandHistoryController.pushInput(input); - vimGlobalState.exCommandHistoryController.reset(); - CodeMirror.e_stop(e); - close(); - cm.focus(); - } - if (keyName == 'Up' || keyName == 'Down') { - up = keyName == 'Up' ? true : false; - input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || ''; - close(input); - } else { - if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') - vimGlobalState.exCommandHistoryController.reset(); - } - } - if (command.type == 'keyToEx') { - // Handle user defined Ex to Ex mappings - exCommandDispatcher.processCommand(cm, command.exArgs.input); - } else { - if (vim.visualMode) { - showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>', - onKeyDown: onPromptKeyDown}); - } else { - showPrompt(cm, { onClose: onPromptClose, prefix: ':', - onKeyDown: onPromptKeyDown}); - } - } - }, - evalInput: function(cm, vim) { - // If the motion comand is set, execute both the operator and motion. - // Otherwise return. - var inputState = vim.inputState; - var motion = inputState.motion; - var motionArgs = inputState.motionArgs || {}; - var operator = inputState.operator; - var operatorArgs = inputState.operatorArgs || {}; - var registerName = inputState.registerName; - var selectionEnd = copyCursor(cm.getCursor('head')); - var selectionStart = copyCursor(cm.getCursor('anchor')); - // The difference between cur and selection cursors are that cur is - // being operated on and ignores that there is a selection. - var curStart = copyCursor(selectionEnd); - var curOriginal = copyCursor(curStart); - var curEnd; - var repeat; - if (operator) { - this.recordLastEdit(vim, inputState); - } - if (inputState.repeatOverride !== undefined) { - // If repeatOverride is specified, that takes precedence over the - // input state's repeat. Used by Ex mode and can be user defined. - repeat = inputState.repeatOverride; - } else { - repeat = inputState.getRepeat(); - } - if (repeat > 0 && motionArgs.explicitRepeat) { - motionArgs.repeatIsExplicit = true; - } else if (motionArgs.noRepeat || - (!motionArgs.explicitRepeat && repeat === 0)) { - repeat = 1; - motionArgs.repeatIsExplicit = false; - } - if (inputState.selectedCharacter) { - // If there is a character input, stick it in all of the arg arrays. - motionArgs.selectedCharacter = operatorArgs.selectedCharacter = - inputState.selectedCharacter; - } - motionArgs.repeat = repeat; - clearInputState(cm); - if (motion) { - var motionResult = motions[motion](cm, motionArgs, vim); - vim.lastMotion = motions[motion]; - if (!motionResult) { - return; - } - if (motionArgs.toJumplist) { - var jumpList = vimGlobalState.jumpList; - // if the current motion is # or *, use cachedCursor - var cachedCursor = jumpList.cachedCursor; - if (cachedCursor) { - recordJumpPosition(cm, cachedCursor, motionResult); - delete jumpList.cachedCursor; - } else { - recordJumpPosition(cm, curOriginal, motionResult); - } - } - if (motionResult instanceof Array) { - curStart = motionResult[0]; - curEnd = motionResult[1]; - } else { - curEnd = motionResult; - } - // TODO: Handle null returns from motion commands better. - if (!curEnd) { - curEnd = Pos(curStart.line, curStart.ch); - } - if (vim.visualMode) { - // Check if the selection crossed over itself. Will need to shift - // the start point if that happened. - // offset is set to -1 or 1 to shift the curEnd - // left or right - var offset = 0; - if (cursorIsBefore(selectionStart, selectionEnd) && - (cursorEqual(selectionStart, curEnd) || - cursorIsBefore(curEnd, selectionStart))) { - // The end of the selection has moved from after the start to - // before the start. We will shift the start right by 1. - selectionStart.ch += 1; - offset = -1; - } else if (cursorIsBefore(selectionEnd, selectionStart) && - (cursorEqual(selectionStart, curEnd) || - cursorIsBefore(selectionStart, curEnd))) { - // The opposite happened. We will shift the start left by 1. - selectionStart.ch -= 1; - offset = 1; - } - // in case of visual Block selectionStart and curEnd - // may not be on the same line, - // Also, In case of v_o this should not happen. - if (!vim.visualBlock && !(motionResult instanceof Array)) { - curEnd.ch += offset; - } - if (vim.lastHPos != Infinity) { - vim.lastHPos = curEnd.ch; - } - selectionEnd = curEnd; - selectionStart = (motionResult instanceof Array) ? curStart : selectionStart; - if (vim.visualLine) { - if (cursorIsBefore(selectionStart, selectionEnd)) { - selectionStart.ch = 0; - - var lastLine = cm.lastLine(); - if (selectionEnd.line > lastLine) { - selectionEnd.line = lastLine; - } - selectionEnd.ch = lineLength(cm, selectionEnd.line); - } else { - selectionEnd.ch = 0; - selectionStart.ch = lineLength(cm, selectionStart.line); - } - } else if (vim.visualBlock) { - // Select a block and - // return the diagonally opposite end. - selectionStart = selectBlock(cm, selectionEnd); - } - if (!vim.visualBlock) { - cm.setSelection(selectionStart, selectionEnd); - } - updateMark(cm, vim, '<', - cursorIsBefore(selectionStart, selectionEnd) ? selectionStart - : selectionEnd); - updateMark(cm, vim, '>', - cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd - : selectionStart); - } else if (!operator) { - curEnd = clipCursorToContent(cm, curEnd); - cm.setCursor(curEnd.line, curEnd.ch); - } - } - - if (operator) { - var inverted = false; - vim.lastMotion = null; - var lastSelection = vim.lastSelection; - operatorArgs.repeat = repeat; // Indent in visual mode needs this. - if (vim.visualMode) { - curStart = selectionStart; - curEnd = selectionEnd; - motionArgs.inclusive = true; - operatorArgs.shouldMoveCursor = false; - } - // Swap start and end if motion was backward. - if (curEnd && cursorIsBefore(curEnd, curStart)) { - var tmp = curStart; - curStart = curEnd; - curEnd = tmp; - inverted = true; - } else if (!curEnd) { - curEnd = copyCursor(curStart); - } - if (motionArgs.inclusive && !vim.visualMode) { - // Move the selection end one to the right to include the last - // character. - curEnd.ch++; - } - if (operatorArgs.selOffset) { - // Replaying a visual mode operation - curEnd.line = curStart.line + operatorArgs.selOffset.line; - if (operatorArgs.selOffset.line) {curEnd.ch = operatorArgs.selOffset.ch; } - else { curEnd.ch = curStart.ch + operatorArgs.selOffset.ch; } - // In case of blockwise visual - if (lastSelection && lastSelection.visualBlock) { - var block = lastSelection.visualBlock; - var width = block.width; - var height = block.height; - curEnd = Pos(curStart.line + height, curStart.ch + width); - // selectBlock creates a 'proper' rectangular block. - // We do not want that in all cases, so we manually set selections. - var selections = []; - for (var i = curStart.line; i < curEnd.line; i++) { - var anchor = Pos(i, curStart.ch); - var head = Pos(i, curEnd.ch); - var range = {anchor: anchor, head: head}; - selections.push(range); - } - cm.setSelections(selections); - var blockSelected = true; - } - } else if (vim.visualMode) { - var selOffset = Pos(); - selOffset.line = curEnd.line - curStart.line; - if (selOffset.line) { selOffset.ch = curEnd.ch; } - else { selOffset.ch = curEnd.ch - curStart.ch; } - operatorArgs.selOffset = selOffset; - } - var linewise = motionArgs.linewise || - (vim.visualMode && vim.visualLine) || - operatorArgs.linewise; - if (linewise) { - // Expand selection to entire line. - expandSelectionToLine(cm, curStart, curEnd); - } else if (motionArgs.forward) { - // Clip to trailing newlines only if the motion goes forward. - clipToLine(cm, curStart, curEnd); - } - operatorArgs.registerName = registerName; - // Keep track of linewise as it affects how paste and change behave. - operatorArgs.linewise = linewise; - if (!vim.visualBlock && !blockSelected) { - cm.setSelection(curStart, curEnd); - } - operators[operator](cm, operatorArgs, vim, curStart, - curEnd, curOriginal); - if (vim.visualMode) { - exitVisualMode(cm); - } - } - }, - recordLastEdit: function(vim, inputState, actionCommand) { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { return; } - vim.lastEditInputState = inputState; - vim.lastEditActionCommand = actionCommand; - macroModeState.lastInsertModeChanges.changes = []; - macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false; - } - }; - - /** - * typedef {Object{line:number,ch:number}} Cursor An object containing the - * position of the cursor. - */ - // All of the functions below return Cursor objects. - var motions = { - moveToTopLine: function(cm, motionArgs) { - var line = getUserVisibleLines(cm).top + motionArgs.repeat -1; - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - moveToMiddleLine: function(cm) { - var range = getUserVisibleLines(cm); - var line = Math.floor((range.top + range.bottom) * 0.5); - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - moveToBottomLine: function(cm, motionArgs) { - var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1; - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - expandToLine: function(cm, motionArgs) { - // Expands forward to end of line, and then to next line if repeat is - // >1. Does not handle backward motion! - var cur = cm.getCursor(); - return Pos(cur.line + motionArgs.repeat - 1, Infinity); - }, - findNext: function(cm, motionArgs) { - var state = getSearchState(cm); - var query = state.getQuery(); - if (!query) { - return; - } - var prev = !motionArgs.forward; - // If search is initiated with ? instead of /, negate direction. - prev = (state.isReversed()) ? !prev : prev; - highlightSearchMatches(cm, query); - return findNext(cm, prev/** prev */, query, motionArgs.repeat); - }, - goToMark: function(cm, motionArgs, vim) { - var mark = vim.marks[motionArgs.selectedCharacter]; - if (mark) { - var pos = mark.find(); - return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos; - } - return null; - }, - moveToOtherHighlightedEnd: function(cm, motionArgs, vim) { - var ranges = cm.listSelections(); - var curEnd = cm.getCursor('head'); - var curStart = ranges[0].anchor; - var curIndex = cursorEqual(ranges[0].head, curEnd) ? ranges.length-1 : 0; - if (motionArgs.sameLine && vim.visualBlock) { - curStart = Pos(curEnd.line, ranges[curIndex].anchor.ch); - curEnd = Pos(ranges[curIndex].head.line, curEnd.ch); - } else { - curStart = ranges[curIndex].anchor; - } - cm.setCursor(curEnd); - return ([curEnd, curStart]); - }, - jumpToMark: function(cm, motionArgs, vim) { - var best = cm.getCursor(); - for (var i = 0; i < motionArgs.repeat; i++) { - var cursor = best; - for (var key in vim.marks) { - if (!isLowerCase(key)) { - continue; - } - var mark = vim.marks[key].find(); - var isWrongDirection = (motionArgs.forward) ? - cursorIsBefore(mark, cursor) : cursorIsBefore(cursor, mark); - - if (isWrongDirection) { - continue; - } - if (motionArgs.linewise && (mark.line == cursor.line)) { - continue; - } - - var equal = cursorEqual(cursor, best); - var between = (motionArgs.forward) ? - cursorIsBetween(cursor, mark, best) : - cursorIsBetween(best, mark, cursor); - - if (equal || between) { - best = mark; - } - } - } - - if (motionArgs.linewise) { - // Vim places the cursor on the first non-whitespace character of - // the line if there is one, else it places the cursor at the end - // of the line, regardless of whether a mark was found. - best = Pos(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line))); - } - return best; - }, - moveByCharacters: function(cm, motionArgs) { - var cur = cm.getCursor(); - var repeat = motionArgs.repeat; - var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat; - return Pos(cur.line, ch); - }, - moveByLines: function(cm, motionArgs, vim) { - var cur = cm.getCursor(); - var endCh = cur.ch; - // Depending what our last motion was, we may want to do different - // things. If our last motion was moving vertically, we want to - // preserve the HPos from our last horizontal move. If our last motion - // was going to the end of a line, moving vertically we should go to - // the end of the line, etc. - switch (vim.lastMotion) { - case this.moveByLines: - case this.moveByDisplayLines: - case this.moveByScroll: - case this.moveToColumn: - case this.moveToEol: - endCh = vim.lastHPos; - break; - default: - vim.lastHPos = endCh; - } - var repeat = motionArgs.repeat+(motionArgs.repeatOffset||0); - var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat; - var first = cm.firstLine(); - var last = cm.lastLine(); - // Vim cancels linewise motions that start on an edge and move beyond - // that edge. It does not cancel motions that do not start on an edge. - if ((line < first && cur.line == first) || - (line > last && cur.line == last)) { - return; - } - if (motionArgs.toFirstChar){ - endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line)); - vim.lastHPos = endCh; - } - vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left; - return Pos(line, endCh); - }, - moveByDisplayLines: function(cm, motionArgs, vim) { - var cur = cm.getCursor(); - switch (vim.lastMotion) { - case this.moveByDisplayLines: - case this.moveByScroll: - case this.moveByLines: - case this.moveToColumn: - case this.moveToEol: - break; - default: - vim.lastHSPos = cm.charCoords(cur,'div').left; - } - var repeat = motionArgs.repeat; - var res=cm.findPosV(cur,(motionArgs.forward ? repeat : -repeat),'line',vim.lastHSPos); - if (res.hitSide) { - if (motionArgs.forward) { - var lastCharCoords = cm.charCoords(res, 'div'); - var goalCoords = { top: lastCharCoords.top + 8, left: vim.lastHSPos }; - var res = cm.coordsChar(goalCoords, 'div'); - } else { - var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div'); - resCoords.left = vim.lastHSPos; - res = cm.coordsChar(resCoords, 'div'); - } - } - vim.lastHPos = res.ch; - return res; - }, - moveByPage: function(cm, motionArgs) { - // CodeMirror only exposes functions that move the cursor page down, so - // doing this bad hack to move the cursor and move it back. evalInput - // will move the cursor to where it should be in the end. - var curStart = cm.getCursor(); - var repeat = motionArgs.repeat; - return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page'); - }, - moveByParagraph: function(cm, motionArgs) { - var line = cm.getCursor().line; - var repeat = motionArgs.repeat; - var inc = motionArgs.forward ? 1 : -1; - for (var i = 0; i < repeat; i++) { - if ((!motionArgs.forward && line === cm.firstLine() ) || - (motionArgs.forward && line == cm.lastLine())) { - break; - } - line += inc; - while (line !== cm.firstLine() && line != cm.lastLine() && cm.getLine(line)) { - line += inc; - } - } - return Pos(line, 0); - }, - moveByScroll: function(cm, motionArgs, vim) { - var scrollbox = cm.getScrollInfo(); - var curEnd = null; - var repeat = motionArgs.repeat; - if (!repeat) { - repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight()); - } - var orig = cm.charCoords(cm.getCursor(), 'local'); - motionArgs.repeat = repeat; - var curEnd = motions.moveByDisplayLines(cm, motionArgs, vim); - if (!curEnd) { - return null; - } - var dest = cm.charCoords(curEnd, 'local'); - cm.scrollTo(null, scrollbox.top + dest.top - orig.top); - return curEnd; - }, - moveByWords: function(cm, motionArgs) { - return moveToWord(cm, motionArgs.repeat, !!motionArgs.forward, - !!motionArgs.wordEnd, !!motionArgs.bigWord); - }, - moveTillCharacter: function(cm, motionArgs) { - var repeat = motionArgs.repeat; - var curEnd = moveToCharacter(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter); - var increment = motionArgs.forward ? -1 : 1; - recordLastCharacterSearch(increment, motionArgs); - if (!curEnd) return null; - curEnd.ch += increment; - return curEnd; - }, - moveToCharacter: function(cm, motionArgs) { - var repeat = motionArgs.repeat; - recordLastCharacterSearch(0, motionArgs); - return moveToCharacter(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || cm.getCursor(); - }, - moveToSymbol: function(cm, motionArgs) { - var repeat = motionArgs.repeat; - return findSymbol(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || cm.getCursor(); - }, - moveToColumn: function(cm, motionArgs, vim) { - var repeat = motionArgs.repeat; - // repeat is equivalent to which column we want to move to! - vim.lastHPos = repeat - 1; - vim.lastHSPos = cm.charCoords(cm.getCursor(),'div').left; - return moveToColumn(cm, repeat); - }, - moveToEol: function(cm, motionArgs, vim) { - var cur = cm.getCursor(); - vim.lastHPos = Infinity; - var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity); - var end=cm.clipPos(retval); - end.ch--; - vim.lastHSPos = cm.charCoords(end,'div').left; - return retval; - }, - moveToFirstNonWhiteSpaceCharacter: function(cm) { - // Go to the start of the line where the text begins, or the end for - // whitespace-only lines - var cursor = cm.getCursor(); - return Pos(cursor.line, - findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))); - }, - moveToMatchedSymbol: function(cm) { - var cursor = cm.getCursor(); - var line = cursor.line; - var ch = cursor.ch; - var lineText = cm.getLine(line); - var symbol; - do { - symbol = lineText.charAt(ch++); - if (symbol && isMatchableSymbol(symbol)) { - var style = cm.getTokenTypeAt(Pos(line, ch)); - if (style !== "string" && style !== "comment") { - break; - } - } - } while (symbol); - if (symbol) { - var matched = cm.findMatchingBracket(Pos(line, ch)); - return matched.to; - } else { - return cursor; - } - }, - moveToStartOfLine: function(cm) { - var cursor = cm.getCursor(); - return Pos(cursor.line, 0); - }, - moveToLineOrEdgeOfDocument: function(cm, motionArgs) { - var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine(); - if (motionArgs.repeatIsExplicit) { - lineNum = motionArgs.repeat - cm.getOption('firstLineNumber'); - } - return Pos(lineNum, - findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))); - }, - textObjectManipulation: function(cm, motionArgs) { - // TODO: lots of possible exceptions that can be thrown here. Try da( - // outside of a () block. - - // TODO: adding <> >< to this map doesn't work, presumably because - // they're operators - var mirroredPairs = {'(': ')', ')': '(', - '{': '}', '}': '{', - '[': ']', ']': '['}; - var selfPaired = {'\'': true, '"': true}; - - var character = motionArgs.selectedCharacter; - // 'b' refers to '()' block. - // 'B' refers to '{}' block. - if (character == 'b') { - character = '('; - } else if (character == 'B') { - character = '{'; - } - - // Inclusive is the difference between a and i - // TODO: Instead of using the additional text object map to perform text - // object operations, merge the map into the defaultKeyMap and use - // motionArgs to define behavior. Define separate entries for 'aw', - // 'iw', 'a[', 'i[', etc. - var inclusive = !motionArgs.textObjectInner; - - var tmp; - if (mirroredPairs[character]) { - tmp = selectCompanionObject(cm, character, inclusive); - } else if (selfPaired[character]) { - tmp = findBeginningAndEnd(cm, character, inclusive); - } else if (character === 'W') { - tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, - true /** bigWord */); - } else if (character === 'w') { - tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, - false /** bigWord */); - } else if (character === 'p') { - tmp = expandParagraphUnderCursor(cm, inclusive, true /** forward */, - false /** bigWord */); - } else { - // No text object defined for this, don't move. - return null; - } - - if (!cm.state.vim.visualMode) { - return [tmp.start, tmp.end]; - } else { - return expandSelection(cm, tmp.start, tmp.end); - } - }, - - repeatLastCharacterSearch: function(cm, motionArgs) { - var lastSearch = vimGlobalState.lastChararacterSearch; - var repeat = motionArgs.repeat; - var forward = motionArgs.forward === lastSearch.forward; - var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1); - cm.moveH(-increment, 'char'); - motionArgs.inclusive = forward ? true : false; - var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter); - if (!curEnd) { - cm.moveH(increment, 'char'); - return cm.getCursor(); - } - curEnd.ch += increment; - return curEnd; - } - }; - - var operators = { - change: function(cm, operatorArgs, vim) { - var selections = cm.listSelections(); - var start = selections[0], end = selections[selections.length-1]; - var curStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; - var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; - var text = cm.getSelection(); - var visualBlock = vim.visualBlock; - if (vim.lastSelection && !vim.visualMode) { - visualBlock = vim.lastSelection.visualBlock ? true : visualBlock; - } - var lastInsertModeChanges = vimGlobalState.macroModeState.lastInsertModeChanges; - lastInsertModeChanges.inVisualBlock = visualBlock; - var replacement = new Array(selections.length).join('1').split('1'); - // save the selectionEnd mark - var selectionEnd = vim.marks[">"] && vim.marks[">"].find(); - if (!selectionEnd) { - selectionEnd = cm.getCursor("head"); - } - vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'change', text, - operatorArgs.linewise); - if (operatorArgs.linewise) { - // 'C' in visual block extends the block till eol for all lines - if (visualBlock){ - var startLine = curStart.line; - while (startLine <= curEnd.line) { - var endCh = lineLength(cm, startLine); - var head = Pos(startLine, endCh); - var anchor = Pos(startLine, curStart.ch); - startLine++; - cm.replaceRange('', anchor, head); - } - } else { - // Push the next line back down, if there is a next line. - replacement = '\n'; - if (curEnd.line == curStart.line && curEnd.line == cm.lastLine()) { - replacement = ''; - } - cm.replaceRange(replacement, curStart, curEnd); - cm.indentLine(curStart.line, 'smart'); - // null ch so setCursor moves to end of line. - curStart.ch = null; - cm.setCursor(curStart); - } - } else { - // Exclude trailing whitespace if the range is not all whitespace. - var text = cm.getRange(curStart, curEnd); - if (!isWhiteSpaceString(text)) { - var match = (/\s+$/).exec(text); - if (match) { - curEnd = offsetCursor(curEnd, 0, - match[0].length); - } - } - if (visualBlock) { - cm.replaceSelections(replacement); - } else { - cm.setCursor(curStart); - cm.replaceRange('', curStart, curEnd); - } - } - vim.marks['>'] = cm.setBookmark(selectionEnd); - actions.enterInsertMode(cm, {}, cm.state.vim); - }, - // delete is a javascript keyword. - 'delete': function(cm, operatorArgs, vim) { - var selections = cm.listSelections(); - var start = selections[0], end = selections[selections.length-1]; - var curStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; - var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; - // Save the '>' mark before cm.replaceRange clears it. - var selectionEnd, selectionStart; - var blockwise = vim.visualBlock; - if (vim.visualMode) { - selectionEnd = vim.marks['>'].find(); - selectionStart = vim.marks['<'].find(); - } else if (vim.lastSelection) { - selectionEnd = vim.lastSelection.curStartMark.find(); - selectionStart = vim.lastSelection.curEndMark.find(); - blockwise = vim.lastSelection.visualBlock; - } - var text = cm.getSelection(); - vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'delete', text, - operatorArgs.linewise, blockwise); - var replacement = new Array(selections.length).join('1').split('1'); - // If the ending line is past the last line, inclusive, instead of - // including the trailing \n, include the \n before the starting line - if (operatorArgs.linewise && - curEnd.line == cm.lastLine() && curStart.line == curEnd.line) { - if (curEnd.line == 0) { - curStart.ch = 0; - } - else { - var tmp = copyCursor(curEnd); - curStart.line--; - curStart.ch = lineLength(cm, curStart.line); - curEnd = tmp; - } - cm.replaceRange('', curStart, curEnd); - } else { - cm.replaceSelections(replacement); - } - // restore the saved bookmark - if (selectionEnd) { - var curStartMark = cm.setBookmark(selectionStart); - var curEndMark = cm.setBookmark(selectionEnd); - if (vim.visualMode) { - vim.marks['<'] = curStartMark; - vim.marks['>'] = curEndMark; - } else { - vim.lastSelection.curStartMark = curStartMark; - vim.lastSelection.curEndMark = curEndMark; - } - } - if (operatorArgs.linewise) { - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); - } else { - cm.setCursor(curStart); - } - }, - indent: function(cm, operatorArgs, vim, curStart, curEnd) { - var startLine = curStart.line; - var endLine = curEnd.line; - // In visual mode, n> shifts the selection right n times, instead of - // shifting n lines right once. - var repeat = (vim.visualMode) ? operatorArgs.repeat : 1; - if (operatorArgs.linewise) { - // The only way to delete a newline is to delete until the start of - // the next line, so in linewise mode evalInput will include the next - // line. We don't want this in indent, so we go back a line. - endLine--; - } - for (var i = startLine; i <= endLine; i++) { - for (var j = 0; j < repeat; j++) { - cm.indentLine(i, operatorArgs.indentRight); - } - } - cm.setCursor(curStart); - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); - }, - changeCase: function(cm, operatorArgs, _vim, _curStart, _curEnd, _curOriginal) { - var selections = cm.getSelections(); - var ranges = cm.listSelections(); - var swapped = []; - var toLower = operatorArgs.toLower; - for (var j = 0; j < selections.length; j++) { - var toSwap = selections[j]; - var text = ''; - if (toLower === true) { - text = toSwap.toLowerCase(); - } else if (toLower === false) { - text = toSwap.toUpperCase(); - } else { - for (var i = 0; i < toSwap.length; i++) { - var character = toSwap.charAt(i); - text += isUpperCase(character) ? character.toLowerCase() : - character.toUpperCase(); - } - } - swapped.push(text); - } - cm.replaceSelections(swapped); - var curStart = ranges[0].anchor; - var curEnd = ranges[0].head; - if (!operatorArgs.shouldMoveCursor) { - cm.setCursor(cursorIsBefore(curStart, curEnd) ? curStart : curEnd); - } - }, - yank: function(cm, operatorArgs, vim, _curStart, _curEnd, curOriginal) { - var text = cm.getSelection(); - vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'yank', - text, operatorArgs.linewise, vim.visualBlock); - cm.setCursor(curOriginal); - } - }; - - var actions = { - jumpListWalk: function(cm, actionArgs, vim) { - if (vim.visualMode) { - return; - } - var repeat = actionArgs.repeat; - var forward = actionArgs.forward; - var jumpList = vimGlobalState.jumpList; - - var mark = jumpList.move(cm, forward ? repeat : -repeat); - var markPos = mark ? mark.find() : undefined; - markPos = markPos ? markPos : cm.getCursor(); - cm.setCursor(markPos); - }, - scroll: function(cm, actionArgs, vim) { - if (vim.visualMode) { - return; - } - var repeat = actionArgs.repeat || 1; - var lineHeight = cm.defaultTextHeight(); - var top = cm.getScrollInfo().top; - var delta = lineHeight * repeat; - var newPos = actionArgs.forward ? top + delta : top - delta; - var cursor = copyCursor(cm.getCursor()); - var cursorCoords = cm.charCoords(cursor, 'local'); - if (actionArgs.forward) { - if (newPos > cursorCoords.top) { - cursor.line += (newPos - cursorCoords.top) / lineHeight; - cursor.line = Math.ceil(cursor.line); - cm.setCursor(cursor); - cursorCoords = cm.charCoords(cursor, 'local'); - cm.scrollTo(null, cursorCoords.top); - } else { - // Cursor stays within bounds. Just reposition the scroll window. - cm.scrollTo(null, newPos); - } - } else { - var newBottom = newPos + cm.getScrollInfo().clientHeight; - if (newBottom < cursorCoords.bottom) { - cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight; - cursor.line = Math.floor(cursor.line); - cm.setCursor(cursor); - cursorCoords = cm.charCoords(cursor, 'local'); - cm.scrollTo( - null, cursorCoords.bottom - cm.getScrollInfo().clientHeight); - } else { - // Cursor stays within bounds. Just reposition the scroll window. - cm.scrollTo(null, newPos); - } - } - }, - scrollToCursor: function(cm, actionArgs) { - var lineNum = cm.getCursor().line; - var charCoords = cm.charCoords(Pos(lineNum, 0), 'local'); - var height = cm.getScrollInfo().clientHeight; - var y = charCoords.top; - var lineHeight = charCoords.bottom - y; - switch (actionArgs.position) { - case 'center': y = y - (height / 2) + lineHeight; - break; - case 'bottom': y = y - height + lineHeight*1.4; - break; - case 'top': y = y + lineHeight*0.4; - break; - } - cm.scrollTo(null, y); - }, - replayMacro: function(cm, actionArgs, vim) { - var registerName = actionArgs.selectedCharacter; - var repeat = actionArgs.repeat; - var macroModeState = vimGlobalState.macroModeState; - if (registerName == '@') { - registerName = macroModeState.latestRegister; - } - while(repeat--){ - executeMacroRegister(cm, vim, macroModeState, registerName); - } - }, - enterMacroRecordMode: function(cm, actionArgs) { - var macroModeState = vimGlobalState.macroModeState; - var registerName = actionArgs.selectedCharacter; - macroModeState.enterMacroRecordMode(cm, registerName); - }, - enterInsertMode: function(cm, actionArgs, vim) { - if (cm.getOption('readOnly')) { return; } - vim.insertMode = true; - vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1; - var insertAt = (actionArgs) ? actionArgs.insertAt : null; - if (vim.visualMode) { - var selections = getSelectedAreaRange(cm, vim); - var selectionStart = selections[0]; - var selectionEnd = selections[1]; - } - if (insertAt == 'eol') { - var cursor = cm.getCursor(); - cursor = Pos(cursor.line, lineLength(cm, cursor.line)); - cm.setCursor(cursor); - } else if (insertAt == 'charAfter') { - cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); - } else if (insertAt == 'firstNonBlank') { - if (vim.visualMode && !vim.visualBlock) { - if (selectionEnd.line < selectionStart.line) { - cm.setCursor(selectionEnd); - } else { - selectionStart = Pos(selectionStart.line, 0); - cm.setCursor(selectionStart); - } - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); - } else if (vim.visualBlock) { - selectionEnd = Pos(selectionEnd.line, selectionStart.ch); - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); - } else { - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); - } - } else if (insertAt == 'endOfSelectedArea') { - if (vim.visualBlock) { - selectionStart = Pos(selectionStart.line, selectionEnd.ch); - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); - } else if (selectionEnd && selectionEnd.line < selectionStart.line) { - selectionEnd = Pos(selectionStart.line, 0); - cm.setCursor(selectionEnd); - } - } else if (insertAt == 'inplace') { - if (vim.visualMode){ - return; - } - } - cm.setOption('keyMap', 'vim-insert'); - cm.setOption('disableInput', false); - if (actionArgs && actionArgs.replace) { - // Handle Replace-mode as a special case of insert mode. - cm.toggleOverwrite(true); - cm.setOption('keyMap', 'vim-replace'); - CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); - } else { - cm.setOption('keyMap', 'vim-insert'); - CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); - } - if (!vimGlobalState.macroModeState.isPlaying) { - // Only record if not replaying. - cm.on('change', onChange); - CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); - } - if (vim.visualMode) { - exitVisualMode(cm); - } - }, - toggleVisualMode: function(cm, actionArgs, vim) { - var repeat = actionArgs.repeat; - var curStart = cm.getCursor(); - var curEnd; - var selections = cm.listSelections(); - // TODO: The repeat should actually select number of characters/lines - // equal to the repeat times the size of the previous visual - // operation. - if (!vim.visualMode) { - vim.visualMode = true; - vim.visualLine = !!actionArgs.linewise; - vim.visualBlock = !!actionArgs.blockwise; - if (vim.visualLine) { - curStart.ch = 0; - curEnd = clipCursorToContent( - cm, Pos(curStart.line + repeat - 1, lineLength(cm, curStart.line)), - true /** includeLineBreak */); - } else { - curEnd = clipCursorToContent( - cm, Pos(curStart.line, curStart.ch + repeat), - true /** includeLineBreak */); - } - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""}); - } else { - curStart = cm.getCursor('anchor'); - curEnd = cm.getCursor('head'); - if (vim.visualLine) { - if (actionArgs.blockwise) { - // This means Ctrl-V pressed in linewise visual - vim.visualBlock = true; - selectBlock(cm, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'blockwise'}); - } else if (!actionArgs.linewise) { - // v pressed in linewise, switch to characterwise visual mode - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual'}); - } else { - exitVisualMode(cm); - } - vim.visualLine = false; - } else if (vim.visualBlock) { - if (actionArgs.linewise) { - // Shift-V pressed in blockwise visual mode - vim.visualLine = true; - curStart = Pos(selections[0].anchor.line, 0); - curEnd = Pos(selections[selections.length-1].anchor.line, lineLength(cm, selections[selections.length-1].anchor.line)); - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'linewise'}); - } else if (!actionArgs.blockwise) { - // v pressed in blockwise mode, Switch to characterwise - if (curEnd != selections[0].head) { - curStart = selections[0].anchor; - } else { - curStart = selections[selections.length-1].anchor; - } - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual'}); - } else { - exitVisualMode(cm); - } - vim.visualBlock = false; - } else if (actionArgs.linewise) { - // Shift-V pressed in characterwise visual mode. Switch to linewise - // visual mode instead of exiting visual mode. - vim.visualLine = true; - curStart.ch = cursorIsBefore(curStart, curEnd) ? 0 : - lineLength(cm, curStart.line); - curEnd.ch = cursorIsBefore(curStart, curEnd) ? - lineLength(cm, curEnd.line) : 0; - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: "linewise"}); - } else if (actionArgs.blockwise) { - vim.visualBlock = true; - selectBlock(cm, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'blockwise'}); - } else { - exitVisualMode(cm); - } - } - updateMark(cm, vim, '<', cursorIsBefore(curStart, curEnd) ? curStart - : curEnd); - updateMark(cm, vim, '>', cursorIsBefore(curStart, curEnd) ? curEnd - : curStart); - }, - reselectLastSelection: function(cm, _actionArgs, vim) { - var curStart = vim.marks['<'].find(); - var curEnd = vim.marks['>'].find(); - var lastSelection = vim.lastSelection; - if (lastSelection) { - // Set the selections as per last selection - var selectionStart = lastSelection.curStartMark.find(); - var selectionEnd = lastSelection.curEndMark.find(); - var blockwise = lastSelection.visualBlock; - // update last selection - updateLastSelection(cm, vim, curStart, curEnd); - if (blockwise) { - cm.setCursor(selectionStart); - selectionStart = selectBlock(cm, selectionEnd); - } else { - cm.setSelection(selectionStart, selectionEnd); - selectionStart = cm.getCursor('anchor'); - selectionEnd = cm.getCursor('head'); - } - if (vim.visualMode) { - updateMark(cm, vim, '<', cursorIsBefore(selectionStart, selectionEnd) ? selectionStart - : selectionEnd); - updateMark(cm, vim, '>', cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd - : selectionStart); - } - // Last selection is updated now - vim.visualMode = true; - if (lastSelection.visualLine) { - vim.visualLine = true; - vim.visualBlock = false; - } else if (lastSelection.visualBlock) { - vim.visualLine = false; - vim.visualBlock = true; - } else { - vim.visualBlock = vim.visualLine = false; - } - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""}); - } - }, - joinLines: function(cm, actionArgs, vim) { - var curStart, curEnd; - if (vim.visualMode) { - curStart = cm.getCursor('anchor'); - curEnd = cm.getCursor('head'); - curEnd.ch = lineLength(cm, curEnd.line) - 1; - } else { - // Repeat is the number of lines to join. Minimum 2 lines. - var repeat = Math.max(actionArgs.repeat, 2); - curStart = cm.getCursor(); - curEnd = clipCursorToContent(cm, Pos(curStart.line + repeat - 1, - Infinity)); - } - var finalCh = 0; - cm.operation(function() { - for (var i = curStart.line; i < curEnd.line; i++) { - finalCh = lineLength(cm, curStart.line); - var tmp = Pos(curStart.line + 1, - lineLength(cm, curStart.line + 1)); - var text = cm.getRange(curStart, tmp); - text = text.replace(/\n\s*/g, ' '); - cm.replaceRange(text, curStart, tmp); - } - var curFinalPos = Pos(curStart.line, finalCh); - cm.setCursor(curFinalPos); - }); - }, - newLineAndEnterInsertMode: function(cm, actionArgs, vim) { - vim.insertMode = true; - var insertAt = copyCursor(cm.getCursor()); - if (insertAt.line === cm.firstLine() && !actionArgs.after) { - // Special case for inserting newline before start of document. - cm.replaceRange('\n', Pos(cm.firstLine(), 0)); - cm.setCursor(cm.firstLine(), 0); - } else { - insertAt.line = (actionArgs.after) ? insertAt.line : - insertAt.line - 1; - insertAt.ch = lineLength(cm, insertAt.line); - cm.setCursor(insertAt); - var newlineFn = CodeMirror.commands.newlineAndIndentContinueComment || - CodeMirror.commands.newlineAndIndent; - newlineFn(cm); - } - this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim); - }, - paste: function(cm, actionArgs, vim) { - var cur = copyCursor(cm.getCursor()); - var register = vimGlobalState.registerController.getRegister( - actionArgs.registerName); - var text = register.toString(); - if (!text) { - return; - } - if (actionArgs.matchIndent) { - var tabSize = cm.getOption("tabSize"); - // length that considers tabs and tabSize - var whitespaceLength = function(str) { - var tabs = (str.split("\t").length - 1); - var spaces = (str.split(" ").length - 1); - return tabs * tabSize + spaces * 1; - }; - var currentLine = cm.getLine(cm.getCursor().line); - var indent = whitespaceLength(currentLine.match(/^\s*/)[0]); - // chomp last newline b/c don't want it to match /^\s*/gm - var chompedText = text.replace(/\n$/, ''); - var wasChomped = text !== chompedText; - var firstIndent = whitespaceLength(text.match(/^\s*/)[0]); - var text = chompedText.replace(/^\s*/gm, function(wspace) { - var newIndent = indent + (whitespaceLength(wspace) - firstIndent); - if (newIndent < 0) { - return ""; - } - else if (cm.getOption("indentWithTabs")) { - var quotient = Math.floor(newIndent / tabSize); - return Array(quotient + 1).join('\t'); - } - else { - return Array(newIndent + 1).join(' '); - } - }); - text += wasChomped ? "\n" : ""; - } - if (actionArgs.repeat > 1) { - var text = Array(actionArgs.repeat + 1).join(text); - } - var linewise = register.linewise; - var blockwise = register.blockwise; - if (linewise) { - if(vim.visualMode) { - text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n'; - } else if (actionArgs.after) { - // Move the newline at the end to the start instead, and paste just - // before the newline character of the line we are on right now. - text = '\n' + text.slice(0, text.length - 1); - cur.ch = lineLength(cm, cur.line); - } else { - cur.ch = 0; - } - } else { - if (blockwise) { - text = text.split('\n'); - for (var i = 0; i < text.length; i++) { - text[i] = (text[i] == '') ? ' ' : text[i]; - } - } - cur.ch += actionArgs.after ? 1 : 0; - } - var curPosFinal; - var idx; - if (vim.visualMode) { - // save the pasted text for reselection if the need arises - vim.lastPastedText = text; - var lastSelectionCurEnd; - var selectedArea = getSelectedAreaRange(cm, vim); - var selectionStart = selectedArea[0]; - var selectionEnd = selectedArea[1]; - var selectedText = cm.getSelection(); - var selections = cm.listSelections(); - var emptyStrings = new Array(selections.length).join('1').split('1'); - // save the curEnd marker before it get cleared due to cm.replaceRange. - if (vim.lastSelection) { - lastSelectionCurEnd = vim.lastSelection.curEndMark.find(); - } - // push the previously selected text to unnamed register - vimGlobalState.registerController.unnamedRegister.setText(selectedText); - if (blockwise) { - // first delete the selected text - cm.replaceSelections(emptyStrings); - // Set new selections as per the block length of the yanked text - selectionEnd = Pos(selectionStart.line + text.length-1, selectionStart.ch); - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); - cm.replaceSelections(text); - curPosFinal = selectionStart; - } else if (vim.visualBlock) { - cm.replaceSelections(emptyStrings); - cm.setCursor(selectionStart); - cm.replaceRange(text, selectionStart, selectionStart); - curPosFinal = selectionStart; - } else { - cm.replaceRange(text, selectionStart, selectionEnd); - curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1); - } - // restore the the curEnd marker - if(lastSelectionCurEnd) { - vim.lastSelection.curEndMark = cm.setBookmark(lastSelectionCurEnd); - } - if (linewise) { - curPosFinal.ch=0; - } - } else { - if (blockwise) { - cm.setCursor(cur); - for (var i = 0; i < text.length; i++) { - var line = cur.line+i; - if (line > cm.lastLine()) { - cm.replaceRange('\n', Pos(line, 0)); - } - var lastCh = lineLength(cm, line); - if (lastCh < cur.ch) { - extendLineToColumn(cm, line, cur.ch); - } - } - cm.setCursor(cur); - selectBlock(cm, Pos(cur.line + text.length-1, cur.ch)); - cm.replaceSelections(text); - curPosFinal = cur; - } else { - cm.replaceRange(text, cur); - // Now fine tune the cursor to where we want it. - if (linewise && actionArgs.after) { - curPosFinal = Pos( - cur.line + 1, - findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1))); - } else if (linewise && !actionArgs.after) { - curPosFinal = Pos( - cur.line, - findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line))); - } else if (!linewise && actionArgs.after) { - idx = cm.indexFromPos(cur); - curPosFinal = cm.posFromIndex(idx + text.length - 1); - } else { - idx = cm.indexFromPos(cur); - curPosFinal = cm.posFromIndex(idx + text.length); - } - } - } - cm.setCursor(curPosFinal); - if (vim.visualMode) { - exitVisualMode(cm); - } - }, - undo: function(cm, actionArgs) { - cm.operation(function() { - repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)(); - cm.setCursor(cm.getCursor('anchor')); - }); - }, - redo: function(cm, actionArgs) { - repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)(); - }, - setRegister: function(_cm, actionArgs, vim) { - vim.inputState.registerName = actionArgs.selectedCharacter; - }, - setMark: function(cm, actionArgs, vim) { - var markName = actionArgs.selectedCharacter; - updateMark(cm, vim, markName, cm.getCursor()); - }, - replace: function(cm, actionArgs, vim) { - var replaceWith = actionArgs.selectedCharacter; - var curStart = cm.getCursor(); - var replaceTo; - var curEnd; - var selections = cm.listSelections(); - if (vim.visualMode) { - curStart = cm.getCursor('start'); - curEnd = cm.getCursor('end'); - } else { - var line = cm.getLine(curStart.line); - replaceTo = curStart.ch + actionArgs.repeat; - if (replaceTo > line.length) { - replaceTo=line.length; - } - curEnd = Pos(curStart.line, replaceTo); - } - if (replaceWith=='\n') { - if (!vim.visualMode) cm.replaceRange('', curStart, curEnd); - // special case, where vim help says to replace by just one line-break - (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm); - } else { - var replaceWithStr = cm.getRange(curStart, curEnd); - //replace all characters in range by selected, but keep linebreaks - replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith); - if (vim.visualBlock) { - // Tabs are split in visua block before replacing - var spaces = new Array(cm.getOption("tabSize")+1).join(' '); - replaceWithStr = cm.getSelection(); - replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n'); - cm.replaceSelections(replaceWithStr); - } else { - cm.replaceRange(replaceWithStr, curStart, curEnd); - } - if (vim.visualMode) { - curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ? - selections[0].anchor : selections[0].head; - cm.setCursor(curStart); - exitVisualMode(cm); - } else { - cm.setCursor(offsetCursor(curEnd, 0, -1)); - } - } - }, - incrementNumberToken: function(cm, actionArgs) { - var cur = cm.getCursor(); - var lineStr = cm.getLine(cur.line); - var re = /-?\d+/g; - var match; - var start; - var end; - var numberStr; - var token; - while ((match = re.exec(lineStr)) !== null) { - token = match[0]; - start = match.index; - end = start + token.length; - if (cur.ch < end)break; - } - if (!actionArgs.backtrack && (end <= cur.ch))return; - if (token) { - var increment = actionArgs.increase ? 1 : -1; - var number = parseInt(token) + (increment * actionArgs.repeat); - var from = Pos(cur.line, start); - var to = Pos(cur.line, end); - numberStr = number.toString(); - cm.replaceRange(numberStr, from, to); - } else { - return; - } - cm.setCursor(Pos(cur.line, start + numberStr.length - 1)); - }, - repeatLastEdit: function(cm, actionArgs, vim) { - var lastEditInputState = vim.lastEditInputState; - if (!lastEditInputState) { return; } - var repeat = actionArgs.repeat; - if (repeat && actionArgs.repeatIsExplicit) { - vim.lastEditInputState.repeatOverride = repeat; - } else { - repeat = vim.lastEditInputState.repeatOverride || repeat; - } - repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */); - }, - exitInsertMode: exitInsertMode - }; - - /* - * Below are miscellaneous utility functions used by vim.js - */ - - /** - * Clips cursor to ensure that line is within the buffer's range - * If includeLineBreak is true, then allow cur.ch == lineLength. - */ - function clipCursorToContent(cm, cur, includeLineBreak) { - var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine() ); - var maxCh = lineLength(cm, line) - 1; - maxCh = (includeLineBreak) ? maxCh + 1 : maxCh; - var ch = Math.min(Math.max(0, cur.ch), maxCh); - return Pos(line, ch); - } - function copyArgs(args) { - var ret = {}; - for (var prop in args) { - if (args.hasOwnProperty(prop)) { - ret[prop] = args[prop]; - } - } - return ret; - } - function offsetCursor(cur, offsetLine, offsetCh) { - return Pos(cur.line + offsetLine, cur.ch + offsetCh); - } - function commandMatches(keys, keyMap, context, inputState) { - // Partial matches are not applied. They inform the key handler - // that the current key sequence is a subsequence of a valid key - // sequence, so that the key buffer is not cleared. - var match, partial = [], full = []; - for (var i = 0; i < keyMap.length; i++) { - var command = keyMap[i]; - if (context == 'insert' && command.context != 'insert' || - command.context && command.context != context || - inputState.operator && command.type == 'action' || - !(match = commandMatch(keys, command.keys))) { continue; } - if (match == 'partial') { partial.push(command); } - if (match == 'full') { full.push(command); } - } - return { - partial: partial.length && partial, - full: full.length && full - }; - } - function commandMatch(pressed, mapped) { - if (mapped.slice(-11) == '') { - // Last character matches anything. - var prefixLen = mapped.length - 11; - var pressedPrefix = pressed.slice(0, prefixLen); - var mappedPrefix = mapped.slice(0, prefixLen); - return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' : - mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false; - } else { - return pressed == mapped ? 'full' : - mapped.indexOf(pressed) == 0 ? 'partial' : false; - } - } - function lastChar(keys) { - var match = /^.*(<[\w\-]+>)$/.exec(keys); - var selectedCharacter = match ? match[1] : keys.slice(-1); - if (selectedCharacter.length > 1){ - switch(selectedCharacter){ - case '': - selectedCharacter='\n'; - break; - case '': - selectedCharacter=' '; - break; - default: - break; - } - } - return selectedCharacter; - } - function repeatFn(cm, fn, repeat) { - return function() { - for (var i = 0; i < repeat; i++) { - fn(cm); - } - }; - } - function copyCursor(cur) { - return Pos(cur.line, cur.ch); - } - function cursorEqual(cur1, cur2) { - return cur1.ch == cur2.ch && cur1.line == cur2.line; - } - function cursorIsBefore(cur1, cur2) { - if (cur1.line < cur2.line) { - return true; - } - if (cur1.line == cur2.line && cur1.ch < cur2.ch) { - return true; - } - return false; - } - function cursorMin(cur1, cur2) { - return cursorIsBefore(cur1, cur2) ? cur1 : cur2; - } - function cursorMax(cur1, cur2) { - return cursorIsBefore(cur1, cur2) ? cur2 : cur1; - } - function cursorIsBetween(cur1, cur2, cur3) { - // returns true if cur2 is between cur1 and cur3. - var cur1before2 = cursorIsBefore(cur1, cur2); - var cur2before3 = cursorIsBefore(cur2, cur3); - return cur1before2 && cur2before3; - } - function lineLength(cm, lineNum) { - return cm.getLine(lineNum).length; - } - function reverse(s){ - return s.split('').reverse().join(''); - } - function trim(s) { - if (s.trim) { - return s.trim(); - } - return s.replace(/^\s+|\s+$/g, ''); - } - function escapeRegex(s) { - return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1'); - } - function extendLineToColumn(cm, lineNum, column) { - var endCh = lineLength(cm, lineNum); - var spaces = new Array(column-endCh+1).join(' '); - cm.setCursor(Pos(lineNum, endCh)); - cm.replaceRange(spaces, cm.getCursor()); - } - // This functions selects a rectangular block - // of text with selectionEnd as any of its corner - // Height of block: - // Difference in selectionEnd.line and first/last selection.line - // Width of the block: - // Distance between selectionEnd.ch and any(first considered here) selection.ch - function selectBlock(cm, selectionEnd) { - var selections = [], ranges = cm.listSelections(); - var head = copyCursor(cm.clipPos(selectionEnd)); - var isClipped = !cursorEqual(selectionEnd, head); - var curHead = cm.getCursor('head'); - var primIndex = getIndex(ranges, curHead); - var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor); - var max = ranges.length - 1; - var index = max - primIndex > primIndex ? max : 0; - var base = ranges[index].anchor; - - var firstLine = Math.min(base.line, head.line); - var lastLine = Math.max(base.line, head.line); - var baseCh = base.ch, headCh = head.ch; - - var dir = ranges[index].head.ch - baseCh; - var newDir = headCh - baseCh; - if (dir > 0 && newDir <= 0) { - baseCh++; - if (!isClipped) { headCh--; } - } else if (dir < 0 && newDir >= 0) { - baseCh--; - if (!wasClipped) { headCh++; } - } else if (dir < 0 && newDir == -1) { - baseCh--; - headCh++; - } - for (var line = firstLine; line <= lastLine; line++) { - var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)}; - selections.push(range); - } - primIndex = head.line == lastLine ? selections.length - 1 : 0; - cm.setSelections(selections, primIndex); - selectionEnd.ch = headCh; - base.ch = baseCh; - return base; - } - // getIndex returns the index of the cursor in the selections. - function getIndex(ranges, cursor, end) { - for (var i = 0; i < ranges.length; i++) { - var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor); - var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor); - if (atAnchor || atHead) { - return i; - } - } - return -1; - } - function getSelectedAreaRange(cm, vim) { - var lastSelection = vim.lastSelection; - var getCurrentSelectedAreaRange = function() { - var selections = cm.listSelections(); - var start = selections[0]; - var end = selections[selections.length-1]; - var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; - var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; - return [selectionStart, selectionEnd]; - }; - var getLastSelectedAreaRange = function() { - var selectionStart = cm.getCursor(); - var selectionEnd = cm.getCursor(); - var block = lastSelection.visualBlock; - if (block) { - var width = block.width; - var height = block.height; - selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width); - var selections = []; - // selectBlock creates a 'proper' rectangular block. - // We do not want that in all cases, so we manually set selections. - for (var i = selectionStart.line; i < selectionEnd.line; i++) { - var anchor = Pos(i, selectionStart.ch); - var head = Pos(i, selectionEnd.ch); - var range = {anchor: anchor, head: head}; - selections.push(range); - } - cm.setSelections(selections); - } else { - var start = lastSelection.curStartMark.find(); - var end = lastSelection.curEndMark.find(); - var line = end.line - start.line; - var ch = end.ch - start.ch; - selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch}; - if (lastSelection.visualLine) { - selectionStart = Pos(selectionStart.line, 0); - selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line)); - } - cm.setSelection(selectionStart, selectionEnd); - } - return [selectionStart, selectionEnd]; - }; - if (!vim.visualMode) { - // In case of replaying the action. - return getLastSelectedAreaRange(); - } else { - return getCurrentSelectedAreaRange(); - } - } - function updateLastSelection(cm, vim, selectionStart, selectionEnd) { - if (!selectionStart || !selectionEnd) { - selectionStart = vim.marks['<'].find() || cm.getCursor('anchor'); - selectionEnd = vim.marks['>'].find() || cm.getCursor('head'); - } - // To accommodate the effect of lastPastedText in the last selection - if (vim.lastPastedText) { - selectionEnd = cm.posFromIndex(cm.indexFromPos(selectionStart) + vim.lastPastedText.length); - vim.lastPastedText = null; - } - var ranges = cm.listSelections(); - // This check ensures to set the cursor - // position where we left off in previous selection - var swap = getIndex(ranges, selectionStart, 'head') > -1; - if (vim.visualBlock) { - var height = Math.abs(selectionStart.line - selectionEnd.line)+1; - var width = Math.abs(selectionStart.ch - selectionEnd.ch); - var block = {height: height, width: width}; - } - // can't use selection state here because yank has already reset its cursor - // Also, Bookmarks make the visual selections robust to edit operations - vim.lastSelection = {'curStartMark': cm.setBookmark(swap ? selectionEnd : selectionStart), - 'curEndMark': cm.setBookmark(swap ? selectionStart : selectionEnd), - 'visualMode': vim.visualMode, - 'visualLine': vim.visualLine, - 'visualBlock': block}; - } - function expandSelection(cm, start, end) { - var head = cm.getCursor('head'); - var anchor = cm.getCursor('anchor'); - var tmp; - if (cursorIsBefore(end, start)) { - tmp = end; - end = start; - start = tmp; - } - if (cursorIsBefore(head, anchor)) { - head = cursorMin(start, head); - anchor = cursorMax(anchor, end); - } else { - anchor = cursorMin(start, anchor); - head = cursorMax(head, end); - } - return [anchor, head]; - } - function getHead(cm) { - var cur = cm.getCursor('head'); - if (cm.getSelection().length == 1) { - // Small corner case when only 1 character is selected. The "real" - // head is the left of head and anchor. - cur = cursorMin(cur, cm.getCursor('anchor')); - } - return cur; - } - - function exitVisualMode(cm) { - var vim = cm.state.vim; - var selectionStart = cm.getCursor('anchor'); - var selectionEnd = cm.getCursor('head'); - // hack to place the cursor at the right place - // in case of visual block - if (vim.visualBlock && (cursorIsBefore(selectionStart, selectionEnd))) { - selectionEnd.ch--; - } - updateLastSelection(cm, vim); - vim.visualMode = false; - vim.visualLine = false; - vim.visualBlock = false; - if (!cursorEqual(selectionStart, selectionEnd)) { - cm.setCursor(clipCursorToContent(cm, selectionEnd)); - } - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } - } - - // Remove any trailing newlines from the selection. For - // example, with the caret at the start of the last word on the line, - // 'dw' should word, but not the newline, while 'w' should advance the - // caret to the first character of the next line. - function clipToLine(cm, curStart, curEnd) { - var selection = cm.getRange(curStart, curEnd); - // Only clip if the selection ends with trailing newline + whitespace - if (/\n\s*$/.test(selection)) { - var lines = selection.split('\n'); - // We know this is all whitepsace. - lines.pop(); - - // Cases: - // 1. Last word is an empty line - do not clip the trailing '\n' - // 2. Last word is not an empty line - clip the trailing '\n' - var line; - // Find the line containing the last word, and clip all whitespace up - // to it. - for (var line = lines.pop(); lines.length > 0 && line && isWhiteSpaceString(line); line = lines.pop()) { - curEnd.line--; - curEnd.ch = 0; - } - // If the last word is not an empty line, clip an additional newline - if (line) { - curEnd.line--; - curEnd.ch = lineLength(cm, curEnd.line); - } else { - curEnd.ch = 0; - } - } - } - - // Expand the selection to line ends. - function expandSelectionToLine(_cm, curStart, curEnd) { - curStart.ch = 0; - curEnd.ch = 0; - curEnd.line++; - } - - function findFirstNonWhiteSpaceCharacter(text) { - if (!text) { - return 0; - } - var firstNonWS = text.search(/\S/); - return firstNonWS == -1 ? text.length : firstNonWS; - } - - function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) { - var cur = getHead(cm); - var line = cm.getLine(cur.line); - var idx = cur.ch; - - // Seek to first word or non-whitespace character, depending on if - // noSymbol is true. - var textAfterIdx = line.substring(idx); - var firstMatchedChar; - if (noSymbol) { - firstMatchedChar = textAfterIdx.search(/\w/); - } else { - firstMatchedChar = textAfterIdx.search(/\S/); - } - if (firstMatchedChar == -1) { - return null; - } - idx += firstMatchedChar; - textAfterIdx = line.substring(idx); - var textBeforeIdx = line.substring(0, idx); - - var matchRegex; - // Greedy matchers for the "word" we are trying to expand. - if (bigWord) { - matchRegex = /^\S+/; - } else { - if ((/\w/).test(line.charAt(idx))) { - matchRegex = /^\w+/; - } else { - matchRegex = /^[^\w\s]+/; - } - } - - var wordAfterRegex = matchRegex.exec(textAfterIdx); - var wordStart = idx; - var wordEnd = idx + wordAfterRegex[0].length; - // TODO: Find a better way to do this. It will be slow on very long lines. - var revTextBeforeIdx = reverse(textBeforeIdx); - var wordBeforeRegex = matchRegex.exec(revTextBeforeIdx); - if (wordBeforeRegex) { - wordStart -= wordBeforeRegex[0].length; - } - - if (inclusive) { - // If present, trim all whitespace after word. - // Otherwise, trim all whitespace before word. - var textAfterWordEnd = line.substring(wordEnd); - var whitespacesAfterWord = textAfterWordEnd.match(/^\s*/)[0].length; - if (whitespacesAfterWord > 0) { - wordEnd += whitespacesAfterWord; - } else { - var revTrim = revTextBeforeIdx.length - wordStart; - var textBeforeWordStart = revTextBeforeIdx.substring(revTrim); - var whitespacesBeforeWord = textBeforeWordStart.match(/^\s*/)[0].length; - wordStart -= whitespacesBeforeWord; - } - } - - return { start: Pos(cur.line, wordStart), - end: Pos(cur.line, wordEnd) }; - } - - function recordJumpPosition(cm, oldCur, newCur) { - if (!cursorEqual(oldCur, newCur)) { - vimGlobalState.jumpList.add(cm, oldCur, newCur); - } - } - - function recordLastCharacterSearch(increment, args) { - vimGlobalState.lastChararacterSearch.increment = increment; - vimGlobalState.lastChararacterSearch.forward = args.forward; - vimGlobalState.lastChararacterSearch.selectedCharacter = args.selectedCharacter; - } - - var symbolToMode = { - '(': 'bracket', ')': 'bracket', '{': 'bracket', '}': 'bracket', - '[': 'section', ']': 'section', - '*': 'comment', '/': 'comment', - 'm': 'method', 'M': 'method', - '#': 'preprocess' - }; - var findSymbolModes = { - bracket: { - isComplete: function(state) { - if (state.nextCh === state.symb) { - state.depth++; - if (state.depth >= 1)return true; - } else if (state.nextCh === state.reverseSymb) { - state.depth--; - } - return false; - } - }, - section: { - init: function(state) { - state.curMoveThrough = true; - state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}'; - }, - isComplete: function(state) { - return state.index === 0 && state.nextCh === state.symb; - } - }, - comment: { - isComplete: function(state) { - var found = state.lastCh === '*' && state.nextCh === '/'; - state.lastCh = state.nextCh; - return found; - } - }, - // TODO: The original Vim implementation only operates on level 1 and 2. - // The current implementation doesn't check for code block level and - // therefore it operates on any levels. - method: { - init: function(state) { - state.symb = (state.symb === 'm' ? '{' : '}'); - state.reverseSymb = state.symb === '{' ? '}' : '{'; - }, - isComplete: function(state) { - if (state.nextCh === state.symb)return true; - return false; - } - }, - preprocess: { - init: function(state) { - state.index = 0; - }, - isComplete: function(state) { - if (state.nextCh === '#') { - var token = state.lineText.match(/#(\w+)/)[1]; - if (token === 'endif') { - if (state.forward && state.depth === 0) { - return true; - } - state.depth++; - } else if (token === 'if') { - if (!state.forward && state.depth === 0) { - return true; - } - state.depth--; - } - if (token === 'else' && state.depth === 0)return true; - } - return false; - } - } - }; - function findSymbol(cm, repeat, forward, symb) { - var cur = copyCursor(cm.getCursor()); - var increment = forward ? 1 : -1; - var endLine = forward ? cm.lineCount() : -1; - var curCh = cur.ch; - var line = cur.line; - var lineText = cm.getLine(line); - var state = { - lineText: lineText, - nextCh: lineText.charAt(curCh), - lastCh: null, - index: curCh, - symb: symb, - reverseSymb: (forward ? { ')': '(', '}': '{' } : { '(': ')', '{': '}' })[symb], - forward: forward, - depth: 0, - curMoveThrough: false - }; - var mode = symbolToMode[symb]; - if (!mode)return cur; - var init = findSymbolModes[mode].init; - var isComplete = findSymbolModes[mode].isComplete; - if (init) { init(state); } - while (line !== endLine && repeat) { - state.index += increment; - state.nextCh = state.lineText.charAt(state.index); - if (!state.nextCh) { - line += increment; - state.lineText = cm.getLine(line) || ''; - if (increment > 0) { - state.index = 0; - } else { - var lineLen = state.lineText.length; - state.index = (lineLen > 0) ? (lineLen-1) : 0; - } - state.nextCh = state.lineText.charAt(state.index); - } - if (isComplete(state)) { - cur.line = line; - cur.ch = state.index; - repeat--; - } - } - if (state.nextCh || state.curMoveThrough) { - return Pos(line, state.index); - } - return cur; - } - - /* - * Returns the boundaries of the next word. If the cursor in the middle of - * the word, then returns the boundaries of the current word, starting at - * the cursor. If the cursor is at the start/end of a word, and we are going - * forward/backward, respectively, find the boundaries of the next word. - * - * @param {CodeMirror} cm CodeMirror object. - * @param {Cursor} cur The cursor position. - * @param {boolean} forward True to search forward. False to search - * backward. - * @param {boolean} bigWord True if punctuation count as part of the word. - * False if only [a-zA-Z0-9] characters count as part of the word. - * @param {boolean} emptyLineIsWord True if empty lines should be treated - * as words. - * @return {Object{from:number, to:number, line: number}} The boundaries of - * the word, or null if there are no more words. - */ - function findWord(cm, cur, forward, bigWord, emptyLineIsWord) { - var lineNum = cur.line; - var pos = cur.ch; - var line = cm.getLine(lineNum); - var dir = forward ? 1 : -1; - var regexps = bigWord ? bigWordRegexp : wordRegexp; - - if (emptyLineIsWord && line == '') { - lineNum += dir; - line = cm.getLine(lineNum); - if (!isLine(cm, lineNum)) { - return null; - } - pos = (forward) ? 0 : line.length; - } - - while (true) { - if (emptyLineIsWord && line == '') { - return { from: 0, to: 0, line: lineNum }; - } - var stop = (dir > 0) ? line.length : -1; - var wordStart = stop, wordEnd = stop; - // Find bounds of next word. - while (pos != stop) { - var foundWord = false; - for (var i = 0; i < regexps.length && !foundWord; ++i) { - if (regexps[i].test(line.charAt(pos))) { - wordStart = pos; - // Advance to end of word. - while (pos != stop && regexps[i].test(line.charAt(pos))) { - pos += dir; - } - wordEnd = pos; - foundWord = wordStart != wordEnd; - if (wordStart == cur.ch && lineNum == cur.line && - wordEnd == wordStart + dir) { - // We started at the end of a word. Find the next one. - continue; - } else { - return { - from: Math.min(wordStart, wordEnd + 1), - to: Math.max(wordStart, wordEnd), - line: lineNum }; - } - } - } - if (!foundWord) { - pos += dir; - } - } - // Advance to next/prev line. - lineNum += dir; - if (!isLine(cm, lineNum)) { - return null; - } - line = cm.getLine(lineNum); - pos = (dir > 0) ? 0 : line.length; - } - // Should never get here. - throw new Error('The impossible happened.'); - } - - /** - * @param {CodeMirror} cm CodeMirror object. - * @param {int} repeat Number of words to move past. - * @param {boolean} forward True to search forward. False to search - * backward. - * @param {boolean} wordEnd True to move to end of word. False to move to - * beginning of word. - * @param {boolean} bigWord True if punctuation count as part of the word. - * False if only alphabet characters count as part of the word. - * @return {Cursor} The position the cursor should move to. - */ - function moveToWord(cm, repeat, forward, wordEnd, bigWord) { - var cur = cm.getCursor(); - var curStart = copyCursor(cur); - var words = []; - if (forward && !wordEnd || !forward && wordEnd) { - repeat++; - } - // For 'e', empty lines are not considered words, go figure. - var emptyLineIsWord = !(forward && wordEnd); - for (var i = 0; i < repeat; i++) { - var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord); - if (!word) { - var eodCh = lineLength(cm, cm.lastLine()); - words.push(forward - ? {line: cm.lastLine(), from: eodCh, to: eodCh} - : {line: 0, from: 0, to: 0}); - break; - } - words.push(word); - cur = Pos(word.line, forward ? (word.to - 1) : word.from); - } - var shortCircuit = words.length != repeat; - var firstWord = words[0]; - var lastWord = words.pop(); - if (forward && !wordEnd) { - // w - if (!shortCircuit && (firstWord.from != curStart.ch || firstWord.line != curStart.line)) { - // We did not start in the middle of a word. Discard the extra word at the end. - lastWord = words.pop(); - } - return Pos(lastWord.line, lastWord.from); - } else if (forward && wordEnd) { - return Pos(lastWord.line, lastWord.to - 1); - } else if (!forward && wordEnd) { - // ge - if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) { - // We did not start in the middle of a word. Discard the extra word at the end. - lastWord = words.pop(); - } - return Pos(lastWord.line, lastWord.to); - } else { - // b - return Pos(lastWord.line, lastWord.from); - } - } - - function moveToCharacter(cm, repeat, forward, character) { - var cur = cm.getCursor(); - var start = cur.ch; - var idx; - for (var i = 0; i < repeat; i ++) { - var line = cm.getLine(cur.line); - idx = charIdxInLine(start, line, character, forward, true); - if (idx == -1) { - return null; - } - start = idx; - } - return Pos(cm.getCursor().line, idx); - } - - function moveToColumn(cm, repeat) { - // repeat is always >= 1, so repeat - 1 always corresponds - // to the column we want to go to. - var line = cm.getCursor().line; - return clipCursorToContent(cm, Pos(line, repeat - 1)); - } - - function updateMark(cm, vim, markName, pos) { - if (!inArray(markName, validMarks)) { - return; - } - if (vim.marks[markName]) { - vim.marks[markName].clear(); - } - vim.marks[markName] = cm.setBookmark(pos); - } - - function charIdxInLine(start, line, character, forward, includeChar) { - // Search for char in line. - // motion_options: {forward, includeChar} - // If includeChar = true, include it too. - // If forward = true, search forward, else search backwards. - // If char is not found on this line, do nothing - var idx; - if (forward) { - idx = line.indexOf(character, start + 1); - if (idx != -1 && !includeChar) { - idx -= 1; - } - } else { - idx = line.lastIndexOf(character, start - 1); - if (idx != -1 && !includeChar) { - idx += 1; - } - } - return idx; - } - - // TODO: perhaps this finagling of start and end positions belonds - // in codmirror/replaceRange? - function selectCompanionObject(cm, symb, inclusive) { - var cur = getHead(cm), start, end; - - var bracketRegexp = ({ - '(': /[()]/, ')': /[()]/, - '[': /[[\]]/, ']': /[[\]]/, - '{': /[{}]/, '}': /[{}]/})[symb]; - var openSym = ({ - '(': '(', ')': '(', - '[': '[', ']': '[', - '{': '{', '}': '{'})[symb]; - var curChar = cm.getLine(cur.line).charAt(cur.ch); - // Due to the behavior of scanForBracket, we need to add an offset if the - // cursor is on a matching open bracket. - var offset = curChar === openSym ? 1 : 0; - - start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, null, {'bracketRegex': bracketRegexp}); - end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, null, {'bracketRegex': bracketRegexp}); - - if (!start || !end) { - return { start: cur, end: cur }; - } - - start = start.pos; - end = end.pos; - - if ((start.line == end.line && start.ch > end.ch) - || (start.line > end.line)) { - var tmp = start; - start = end; - end = tmp; - } - - if (inclusive) { - end.ch += 1; - } else { - start.ch += 1; - } - - return { start: start, end: end }; - } - - // Takes in a symbol and a cursor and tries to simulate text objects that - // have identical opening and closing symbols - // TODO support across multiple lines - function findBeginningAndEnd(cm, symb, inclusive) { - var cur = copyCursor(getHead(cm)); - var line = cm.getLine(cur.line); - var chars = line.split(''); - var start, end, i, len; - var firstIndex = chars.indexOf(symb); - - // the decision tree is to always look backwards for the beginning first, - // but if the cursor is in front of the first instance of the symb, - // then move the cursor forward - if (cur.ch < firstIndex) { - cur.ch = firstIndex; - // Why is this line even here??? - // cm.setCursor(cur.line, firstIndex+1); - } - // otherwise if the cursor is currently on the closing symbol - else if (firstIndex < cur.ch && chars[cur.ch] == symb) { - end = cur.ch; // assign end to the current cursor - --cur.ch; // make sure to look backwards - } - - // if we're currently on the symbol, we've got a start - if (chars[cur.ch] == symb && !end) { - start = cur.ch + 1; // assign start to ahead of the cursor - } else { - // go backwards to find the start - for (i = cur.ch; i > -1 && !start; i--) { - if (chars[i] == symb) { - start = i + 1; - } - } - } - - // look forwards for the end symbol - if (start && !end) { - for (i = start, len = chars.length; i < len && !end; i++) { - if (chars[i] == symb) { - end = i; - } - } - } - - // nothing found - if (!start || !end) { - return { start: cur, end: cur }; - } - - // include the symbols - if (inclusive) { - --start; ++end; - } - - return { - start: Pos(cur.line, start), - end: Pos(cur.line, end) - }; - } - - // Search functions - defineOption('pcre', true, 'boolean'); - function SearchState() {} - SearchState.prototype = { - getQuery: function() { - return vimGlobalState.query; - }, - setQuery: function(query) { - vimGlobalState.query = query; - }, - getOverlay: function() { - return this.searchOverlay; - }, - setOverlay: function(overlay) { - this.searchOverlay = overlay; - }, - isReversed: function() { - return vimGlobalState.isReversed; - }, - setReversed: function(reversed) { - vimGlobalState.isReversed = reversed; - } - }; - function getSearchState(cm) { - var vim = cm.state.vim; - return vim.searchState_ || (vim.searchState_ = new SearchState()); - } - function dialog(cm, template, shortText, onClose, options) { - if (cm.openDialog) { - cm.openDialog(template, onClose, { bottom: true, value: options.value, - onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp }); - } - else { - onClose(prompt(shortText, '')); - } - } - function splitBySlash(argString) { - var slashes = findUnescapedSlashes(argString) || []; - if (!slashes.length) return []; - var tokens = []; - // in case of strings like foo/bar - if (slashes[0] !== 0) return; - for (var i = 0; i < slashes.length; i++) { - if (typeof slashes[i] == 'number') - tokens.push(argString.substring(slashes[i] + 1, slashes[i+1])); - } - return tokens; - } - - function findUnescapedSlashes(str) { - var escapeNextChar = false; - var slashes = []; - for (var i = 0; i < str.length; i++) { - var c = str.charAt(i); - if (!escapeNextChar && c == '/') { - slashes.push(i); - } - escapeNextChar = !escapeNextChar && (c == '\\'); - } - return slashes; - } - - // Translates a search string from ex (vim) syntax into javascript form. - function translateRegex(str) { - // When these match, add a '\' if unescaped or remove one if escaped. - var specials = '|(){'; - // Remove, but never add, a '\' for these. - var unescape = '}'; - var escapeNextChar = false; - var out = []; - for (var i = -1; i < str.length; i++) { - var c = str.charAt(i) || ''; - var n = str.charAt(i+1) || ''; - var specialComesNext = (n && specials.indexOf(n) != -1); - if (escapeNextChar) { - if (c !== '\\' || !specialComesNext) { - out.push(c); - } - escapeNextChar = false; - } else { - if (c === '\\') { - escapeNextChar = true; - // Treat the unescape list as special for removing, but not adding '\'. - if (n && unescape.indexOf(n) != -1) { - specialComesNext = true; - } - // Not passing this test means removing a '\'. - if (!specialComesNext || n === '\\') { - out.push(c); - } - } else { - out.push(c); - if (specialComesNext && n !== '\\') { - out.push('\\'); - } - } - } - } - return out.join(''); - } - - // Translates the replace part of a search and replace from ex (vim) syntax into - // javascript form. Similar to translateRegex, but additionally fixes back references - // (translates '\[0..9]' to '$[0..9]') and follows different rules for escaping '$'. - function translateRegexReplace(str) { - var escapeNextChar = false; - var out = []; - for (var i = -1; i < str.length; i++) { - var c = str.charAt(i) || ''; - var n = str.charAt(i+1) || ''; - if (escapeNextChar) { - // At any point in the loop, escapeNextChar is true if the previous - // character was a '\' and was not escaped. - out.push(c); - escapeNextChar = false; - } else { - if (c === '\\') { - escapeNextChar = true; - if ((isNumber(n) || n === '$')) { - out.push('$'); - } else if (n !== '/' && n !== '\\') { - out.push('\\'); - } - } else { - if (c === '$') { - out.push('$'); - } - out.push(c); - if (n === '/') { - out.push('\\'); - } - } - } - } - return out.join(''); - } - - // Unescape \ and / in the replace part, for PCRE mode. - function unescapeRegexReplace(str) { - var stream = new CodeMirror.StringStream(str); - var output = []; - while (!stream.eol()) { - // Search for \. - while (stream.peek() && stream.peek() != '\\') { - output.push(stream.next()); - } - if (stream.match('\\/', true)) { - // \/ => / - output.push('/'); - } else if (stream.match('\\\\', true)) { - // \\ => \ - output.push('\\'); - } else { - // Don't change anything - output.push(stream.next()); - } - } - return output.join(''); - } - - /** - * Extract the regular expression from the query and return a Regexp object. - * Returns null if the query is blank. - * If ignoreCase is passed in, the Regexp object will have the 'i' flag set. - * If smartCase is passed in, and the query contains upper case letters, - * then ignoreCase is overridden, and the 'i' flag will not be set. - * If the query contains the /i in the flag part of the regular expression, - * then both ignoreCase and smartCase are ignored, and 'i' will be passed - * through to the Regex object. - */ - function parseQuery(query, ignoreCase, smartCase) { - // First update the last search register - var lastSearchRegister = vimGlobalState.registerController.getRegister('/'); - lastSearchRegister.setText(query); - // Check if the query is already a regex. - if (query instanceof RegExp) { return query; } - // First try to extract regex + flags from the input. If no flags found, - // extract just the regex. IE does not accept flags directly defined in - // the regex string in the form /regex/flags - var slashes = findUnescapedSlashes(query); - var regexPart; - var forceIgnoreCase; - if (!slashes.length) { - // Query looks like 'regexp' - regexPart = query; - } else { - // Query looks like 'regexp/...' - regexPart = query.substring(0, slashes[0]); - var flagsPart = query.substring(slashes[0]); - forceIgnoreCase = (flagsPart.indexOf('i') != -1); - } - if (!regexPart) { - return null; - } - if (!getOption('pcre')) { - regexPart = translateRegex(regexPart); - } - if (smartCase) { - ignoreCase = (/^[^A-Z]*$/).test(regexPart); - } - var regexp = new RegExp(regexPart, - (ignoreCase || forceIgnoreCase) ? 'i' : undefined); - return regexp; - } - function showConfirm(cm, text) { - if (cm.openNotification) { - cm.openNotification('' + text + '', - {bottom: true, duration: 5000}); - } else { - alert(text); - } - } - function makePrompt(prefix, desc) { - var raw = ''; - if (prefix) { - raw += '' + prefix + ''; - } - raw += ' ' + - ''; - if (desc) { - raw += ''; - raw += desc; - raw += ''; - } - return raw; - } - var searchPromptDesc = '(Javascript regexp)'; - function showPrompt(cm, options) { - var shortText = (options.prefix || '') + ' ' + (options.desc || ''); - var prompt = makePrompt(options.prefix, options.desc); - dialog(cm, prompt, shortText, options.onClose, options); - } - function regexEqual(r1, r2) { - if (r1 instanceof RegExp && r2 instanceof RegExp) { - var props = ['global', 'multiline', 'ignoreCase', 'source']; - for (var i = 0; i < props.length; i++) { - var prop = props[i]; - if (r1[prop] !== r2[prop]) { - return false; - } - } - return true; - } - return false; - } - // Returns true if the query is valid. - function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) { - if (!rawQuery) { - return; - } - var state = getSearchState(cm); - var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase); - if (!query) { - return; - } - highlightSearchMatches(cm, query); - if (regexEqual(query, state.getQuery())) { - return query; - } - state.setQuery(query); - return query; - } - function searchOverlay(query) { - if (query.source.charAt(0) == '^') { - var matchSol = true; - } - return { - token: function(stream) { - if (matchSol && !stream.sol()) { - stream.skipToEnd(); - return; - } - var match = stream.match(query, false); - if (match) { - if (match[0].length == 0) { - // Matched empty string, skip to next. - stream.next(); - return 'searching'; - } - if (!stream.sol()) { - // Backtrack 1 to match \b - stream.backUp(1); - if (!query.exec(stream.next() + match[0])) { - stream.next(); - return null; - } - } - stream.match(query); - return 'searching'; - } - while (!stream.eol()) { - stream.next(); - if (stream.match(query, false)) break; - } - }, - query: query - }; - } - function highlightSearchMatches(cm, query) { - var overlay = getSearchState(cm).getOverlay(); - if (!overlay || query != overlay.query) { - if (overlay) { - cm.removeOverlay(overlay); - } - overlay = searchOverlay(query); - cm.addOverlay(overlay); - getSearchState(cm).setOverlay(overlay); - } - } - function findNext(cm, prev, query, repeat) { - if (repeat === undefined) { repeat = 1; } - return cm.operation(function() { - var pos = cm.getCursor(); - var cursor = cm.getSearchCursor(query, pos); - for (var i = 0; i < repeat; i++) { - var found = cursor.find(prev); - if (i == 0 && found && cursorEqual(cursor.from(), pos)) { found = cursor.find(prev); } - if (!found) { - // SearchCursor may have returned null because it hit EOF, wrap - // around and try again. - cursor = cm.getSearchCursor(query, - (prev) ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) ); - if (!cursor.find(prev)) { - return; - } - } - } - return cursor.from(); - }); - } - function clearSearchHighlight(cm) { - cm.removeOverlay(getSearchState(cm).getOverlay()); - getSearchState(cm).setOverlay(null); - } - /** - * Check if pos is in the specified range, INCLUSIVE. - * Range can be specified with 1 or 2 arguments. - * If the first range argument is an array, treat it as an array of line - * numbers. Match pos against any of the lines. - * If the first range argument is a number, - * if there is only 1 range argument, check if pos has the same line - * number - * if there are 2 range arguments, then check if pos is in between the two - * range arguments. - */ - function isInRange(pos, start, end) { - if (typeof pos != 'number') { - // Assume it is a cursor position. Get the line number. - pos = pos.line; - } - if (start instanceof Array) { - return inArray(pos, start); - } else { - if (end) { - return (pos >= start && pos <= end); - } else { - return pos == start; - } - } - } - function getUserVisibleLines(cm) { - var renderer = cm.ace.renderer; - return { - top: renderer.getFirstFullyVisibleRow(), - bottom: renderer.getLastFullyVisibleRow() - } - var scrollInfo = cm.getScrollInfo(); - var occludeToleranceTop = 6; - var occludeToleranceBottom = 10; - var from = cm.coordsChar({left:0, top: occludeToleranceTop + scrollInfo.top}, 'local'); - var bottomY = scrollInfo.clientHeight - occludeToleranceBottom + scrollInfo.top; - var to = cm.coordsChar({left:0, top: bottomY}, 'local'); - return {top: from.line, bottom: to.line}; - } - - // Ex command handling - // Care must be taken when adding to the default Ex command map. For any - // pair of commands that have a shared prefix, at least one of their - // shortNames must not match the prefix of the other command. - var defaultExCommandMap = [ - { name: 'map' }, - { name: 'imap', shortName: 'im' }, - { name: 'nmap', shortName: 'nm' }, - { name: 'vmap', shortName: 'vm' }, - { name: 'unmap' }, - { name: 'write', shortName: 'w' }, - { name: 'undo', shortName: 'u' }, - { name: 'redo', shortName: 'red' }, - { name: 'set', shortName: 'set' }, - { name: 'sort', shortName: 'sor' }, - { name: 'substitute', shortName: 's', possiblyAsync: true }, - { name: 'nohlsearch', shortName: 'noh' }, - { name: 'delmarks', shortName: 'delm' }, - { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true }, - { name: 'global', shortName: 'g' } - ]; - var ExCommandDispatcher = function() { - this.buildCommandMap_(); - }; - ExCommandDispatcher.prototype = { - processCommand: function(cm, input, opt_params) { - var vim = cm.state.vim; - var commandHistoryRegister = vimGlobalState.registerController.getRegister(':'); - var previousCommand = commandHistoryRegister.toString(); - if (vim.visualMode) { - exitVisualMode(cm); - } - var inputStream = new CodeMirror.StringStream(input); - // update ": with the latest command whether valid or invalid - commandHistoryRegister.setText(input); - var params = opt_params || {}; - params.input = input; - try { - this.parseInput_(cm, inputStream, params); - } catch(e) { - showConfirm(cm, e); - throw e; - } - var command; - var commandName; - if (!params.commandName) { - // If only a line range is defined, move to the line. - if (params.line !== undefined) { - commandName = 'move'; - } - } else { - command = this.matchCommand_(params.commandName); - if (command) { - commandName = command.name; - if (command.excludeFromCommandHistory) { - commandHistoryRegister.setText(previousCommand); - } - this.parseCommandArgs_(inputStream, params, command); - if (command.type == 'exToKey') { - // Handle Ex to Key mapping. - for (var i = 0; i < command.toKeys.length; i++) { - CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping'); - } - return; - } else if (command.type == 'exToEx') { - // Handle Ex to Ex mapping. - this.processCommand(cm, command.toInput); - return; - } - } - } - if (!commandName) { - showConfirm(cm, 'Not an editor command ":' + input + '"'); - return; - } - try { - exCommands[commandName](cm, params); - // Possibly asynchronous commands (e.g. substitute, which might have a - // user confirmation), are responsible for calling the callback when - // done. All others have it taken care of for them here. - if ((!command || !command.possiblyAsync) && params.callback) { - params.callback(); - } - } catch(e) { - showConfirm(cm, e); - throw e; - } - }, - parseInput_: function(cm, inputStream, result) { - inputStream.eatWhile(':'); - // Parse range. - if (inputStream.eat('%')) { - result.line = cm.firstLine(); - result.lineEnd = cm.lastLine(); - } else { - result.line = this.parseLineSpec_(cm, inputStream); - if (result.line !== undefined && inputStream.eat(',')) { - result.lineEnd = this.parseLineSpec_(cm, inputStream); - } - } - - // Parse command name. - var commandMatch = inputStream.match(/^(\w+)/); - if (commandMatch) { - result.commandName = commandMatch[1]; - } else { - result.commandName = inputStream.match(/.*/)[0]; - } - - return result; - }, - parseLineSpec_: function(cm, inputStream) { - var numberMatch = inputStream.match(/^(\d+)/); - if (numberMatch) { - return parseInt(numberMatch[1], 10) - 1; - } - switch (inputStream.next()) { - case '.': - return cm.getCursor().line; - case '$': - return cm.lastLine(); - case '\'': - var mark = cm.state.vim.marks[inputStream.next()]; - if (mark && mark.find()) { - return mark.find().line; - } - throw new Error('Mark not set'); - default: - inputStream.backUp(1); - return undefined; - } - }, - parseCommandArgs_: function(inputStream, params, command) { - if (inputStream.eol()) { - return; - } - params.argString = inputStream.match(/.*/)[0]; - // Parse command-line arguments - var delim = command.argDelimiter || /\s+/; - var args = trim(params.argString).split(delim); - if (args.length && args[0]) { - params.args = args; - } - }, - matchCommand_: function(commandName) { - // Return the command in the command map that matches the shortest - // prefix of the passed in command name. The match is guaranteed to be - // unambiguous if the defaultExCommandMap's shortNames are set up - // correctly. (see @code{defaultExCommandMap}). - for (var i = commandName.length; i > 0; i--) { - var prefix = commandName.substring(0, i); - if (this.commandMap_[prefix]) { - var command = this.commandMap_[prefix]; - if (command.name.indexOf(commandName) === 0) { - return command; - } - } - } - return null; - }, - buildCommandMap_: function() { - this.commandMap_ = {}; - for (var i = 0; i < defaultExCommandMap.length; i++) { - var command = defaultExCommandMap[i]; - var key = command.shortName || command.name; - this.commandMap_[key] = command; - } - }, - map: function(lhs, rhs, ctx) { - if (lhs != ':' && lhs.charAt(0) == ':') { - if (ctx) { throw Error('Mode not supported for ex mappings'); } - var commandName = lhs.substring(1); - if (rhs != ':' && rhs.charAt(0) == ':') { - // Ex to Ex mapping - this.commandMap_[commandName] = { - name: commandName, - type: 'exToEx', - toInput: rhs.substring(1), - user: true - }; - } else { - // Ex to key mapping - this.commandMap_[commandName] = { - name: commandName, - type: 'exToKey', - toKeys: rhs, - user: true - }; - } - } else { - if (rhs != ':' && rhs.charAt(0) == ':') { - // Key to Ex mapping. - var mapping = { - keys: lhs, - type: 'keyToEx', - exArgs: { input: rhs.substring(1) }, - user: true}; - if (ctx) { mapping.context = ctx; } - defaultKeymap.unshift(mapping); - } else { - // Key to key mapping - var mapping = { - keys: lhs, - type: 'keyToKey', - toKeys: rhs, - user: true - }; - if (ctx) { mapping.context = ctx; } - defaultKeymap.unshift(mapping); - } - } - }, - unmap: function(lhs, ctx) { - if (lhs != ':' && lhs.charAt(0) == ':') { - // Ex to Ex or Ex to key mapping - if (ctx) { throw Error('Mode not supported for ex mappings'); } - var commandName = lhs.substring(1); - if (this.commandMap_[commandName] && this.commandMap_[commandName].user) { - delete this.commandMap_[commandName]; - return; - } - } else { - // Key to Ex or key to key mapping - var keys = lhs; - for (var i = 0; i < defaultKeymap.length; i++) { - if (keys == defaultKeymap[i].keys - && defaultKeymap[i].context === ctx - && defaultKeymap[i].user) { - defaultKeymap.splice(i, 1); - return; - } - } - } - throw Error('No such mapping.'); - } - }; - - var exCommands = { - map: function(cm, params, ctx) { - var mapArgs = params.args; - if (!mapArgs || mapArgs.length < 2) { - if (cm) { - showConfirm(cm, 'Invalid mapping: ' + params.input); - } - return; - } - exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx); - }, - imap: function(cm, params) { this.map(cm, params, 'insert'); }, - nmap: function(cm, params) { this.map(cm, params, 'normal'); }, - vmap: function(cm, params) { this.map(cm, params, 'visual'); }, - unmap: function(cm, params, ctx) { - var mapArgs = params.args; - if (!mapArgs || mapArgs.length < 1) { - if (cm) { - showConfirm(cm, 'No such mapping: ' + params.input); - } - return; - } - exCommandDispatcher.unmap(mapArgs[0], ctx); - }, - move: function(cm, params) { - commandDispatcher.processCommand(cm, cm.state.vim, { - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { forward: false, explicitRepeat: true, - linewise: true }, - repeatOverride: params.line+1}); - }, - set: function(cm, params) { - var setArgs = params.args; - if (!setArgs || setArgs.length < 1) { - if (cm) { - showConfirm(cm, 'Invalid mapping: ' + params.input); - } - return; - } - var expr = setArgs[0].split('='); - var optionName = expr[0]; - var value = expr[1]; - var forceGet = false; - - if (optionName.charAt(optionName.length - 1) == '?') { - // If post-fixed with ?, then the set is actually a get. - if (value) { throw Error('Trailing characters: ' + params.argString); } - optionName = optionName.substring(0, optionName.length - 1); - forceGet = true; - } - if (value === undefined && optionName.substring(0, 2) == 'no') { - // To set boolean options to false, the option name is prefixed with - // 'no'. - optionName = optionName.substring(2); - value = false; - } - var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean'; - if (optionIsBoolean && value == undefined) { - // Calling set with a boolean option sets it to true. - value = true; - } - if (!optionIsBoolean && !value || forceGet) { - var oldValue = getOption(optionName); - // If no value is provided, then we assume this is a get. - if (oldValue === true || oldValue === false) { - showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName); - } else { - showConfirm(cm, ' ' + optionName + '=' + oldValue); - } - } else { - setOption(optionName, value, cm); - } - }, - registers: function(cm,params) { - var regArgs = params.args; - var registers = vimGlobalState.registerController.registers; - var regInfo = '----------Registers----------

    '; - if (!regArgs) { - for (var registerName in registers) { - var text = registers[registerName].toString(); - if (text.length) { - regInfo += '"' + registerName + ' ' + text + '
    '; - } - } - } else { - var registerName; - regArgs = regArgs.join(''); - for (var i = 0; i < regArgs.length; i++) { - registerName = regArgs.charAt(i); - if (!vimGlobalState.registerController.isValidRegister(registerName)) { - continue; - } - var register = registers[registerName] || new Register(); - regInfo += '"' + registerName + ' ' + register.toString() + '
    '; - } - } - showConfirm(cm, regInfo); - }, - sort: function(cm, params) { - var reverse, ignoreCase, unique, number; - function parseArgs() { - if (params.argString) { - var args = new CodeMirror.StringStream(params.argString); - if (args.eat('!')) { reverse = true; } - if (args.eol()) { return; } - if (!args.eatSpace()) { return 'Invalid arguments'; } - var opts = args.match(/[a-z]+/); - if (opts) { - opts = opts[0]; - ignoreCase = opts.indexOf('i') != -1; - unique = opts.indexOf('u') != -1; - var decimal = opts.indexOf('d') != -1 && 1; - var hex = opts.indexOf('x') != -1 && 1; - var octal = opts.indexOf('o') != -1 && 1; - if (decimal + hex + octal > 1) { return 'Invalid arguments'; } - number = decimal && 'decimal' || hex && 'hex' || octal && 'octal'; - } - if (args.eatSpace() && args.match(/\/.*\//)) { 'patterns not supported'; } - } - } - var err = parseArgs(); - if (err) { - showConfirm(cm, err + ': ' + params.argString); - return; - } - var lineStart = params.line || cm.firstLine(); - var lineEnd = params.lineEnd || params.line || cm.lastLine(); - if (lineStart == lineEnd) { return; } - var curStart = Pos(lineStart, 0); - var curEnd = Pos(lineEnd, lineLength(cm, lineEnd)); - var text = cm.getRange(curStart, curEnd).split('\n'); - var numberRegex = (number == 'decimal') ? /(-?)([\d]+)/ : - (number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i : - (number == 'octal') ? /([0-7]+)/ : null; - var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null; - var numPart = [], textPart = []; - if (number) { - for (var i = 0; i < text.length; i++) { - if (numberRegex.exec(text[i])) { - numPart.push(text[i]); - } else { - textPart.push(text[i]); - } - } - } else { - textPart = text; - } - function compareFn(a, b) { - if (reverse) { var tmp; tmp = a; a = b; b = tmp; } - if (ignoreCase) { a = a.toLowerCase(); b = b.toLowerCase(); } - var anum = number && numberRegex.exec(a); - var bnum = number && numberRegex.exec(b); - if (!anum) { return a < b ? -1 : 1; } - anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix); - bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix); - return anum - bnum; - } - numPart.sort(compareFn); - textPart.sort(compareFn); - text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart); - if (unique) { // Remove duplicate lines - var textOld = text; - var lastLine; - text = []; - for (var i = 0; i < textOld.length; i++) { - if (textOld[i] != lastLine) { - text.push(textOld[i]); - } - lastLine = textOld[i]; - } - } - cm.replaceRange(text.join('\n'), curStart, curEnd); - }, - global: function(cm, params) { - // a global command is of the form - // :[range]g/pattern/[cmd] - // argString holds the string /pattern/[cmd] - var argString = params.argString; - if (!argString) { - showConfirm(cm, 'Regular Expression missing from global'); - return; - } - // range is specified here - var lineStart = (params.line !== undefined) ? params.line : cm.firstLine(); - var lineEnd = params.lineEnd || params.line || cm.lastLine(); - // get the tokens from argString - var tokens = splitBySlash(argString); - var regexPart = argString, cmd; - if (tokens.length) { - regexPart = tokens[0]; - cmd = tokens.slice(1, tokens.length).join('/'); - } - if (regexPart) { - // If regex part is empty, then use the previous query. Otherwise - // use the regex part as the new query. - try { - updateSearchQuery(cm, regexPart, true /** ignoreCase */, - true /** smartCase */); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + regexPart); - return; - } - } - // now that we have the regexPart, search for regex matches in the - // specified range of lines - var query = getSearchState(cm).getQuery(); - var matchedLines = [], content = ''; - for (var i = lineStart; i <= lineEnd; i++) { - var matched = query.test(cm.getLine(i)); - if (matched) { - matchedLines.push(i+1); - content+= cm.getLine(i) + '
    '; - } - } - // if there is no [cmd], just display the list of matched lines - if (!cmd) { - showConfirm(cm, content); - return; - } - var index = 0; - var nextCommand = function() { - if (index < matchedLines.length) { - var command = matchedLines[index] + cmd; - exCommandDispatcher.processCommand(cm, command, { - callback: nextCommand - }); - } - index++; - }; - nextCommand(); - }, - substitute: function(cm, params) { - if (!cm.getSearchCursor) { - throw new Error('Search feature not available. Requires searchcursor.js or ' + - 'any other getSearchCursor implementation.'); - } - var argString = params.argString; - var tokens = argString ? splitBySlash(argString) : []; - var regexPart, replacePart = '', trailing, flagsPart, count; - var confirm = false; // Whether to confirm each replace. - var global = false; // True to replace all instances on a line, false to replace only 1. - if (tokens.length) { - regexPart = tokens[0]; - replacePart = tokens[1]; - if (replacePart !== undefined) { - if (getOption('pcre')) { - replacePart = unescapeRegexReplace(replacePart); - } else { - replacePart = translateRegexReplace(replacePart); - } - vimGlobalState.lastSubstituteReplacePart = replacePart; - } - trailing = tokens[2] ? tokens[2].split(' ') : []; - } else { - // either the argString is empty or its of the form ' hello/world' - // actually splitBySlash returns a list of tokens - // only if the string starts with a '/' - if (argString && argString.length) { - showConfirm(cm, 'Substitutions should be of the form ' + - ':s/pattern/replace/'); - return; - } - } - // After the 3rd slash, we can have flags followed by a space followed - // by count. - if (trailing) { - flagsPart = trailing[0]; - count = parseInt(trailing[1]); - if (flagsPart) { - if (flagsPart.indexOf('c') != -1) { - confirm = true; - flagsPart.replace('c', ''); - } - if (flagsPart.indexOf('g') != -1) { - global = true; - flagsPart.replace('g', ''); - } - regexPart = regexPart + '/' + flagsPart; - } - } - if (regexPart) { - // If regex part is empty, then use the previous query. Otherwise use - // the regex part as the new query. - try { - updateSearchQuery(cm, regexPart, true /** ignoreCase */, - true /** smartCase */); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + regexPart); - return; - } - } - replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart; - if (replacePart === undefined) { - showConfirm(cm, 'No previous substitute regular expression'); - return; - } - var state = getSearchState(cm); - var query = state.getQuery(); - var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line; - var lineEnd = params.lineEnd || lineStart; - if (count) { - lineStart = lineEnd; - lineEnd = lineStart + count - 1; - } - var startPos = clipCursorToContent(cm, Pos(lineStart, 0)); - var cursor = cm.getSearchCursor(query, startPos); - doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback); - }, - redo: CodeMirror.commands.redo, - undo: CodeMirror.commands.undo, - write: function(cm) { - if (CodeMirror.commands.save) { - // If a save command is defined, call it. - CodeMirror.commands.save(cm); - } else { - // Saves to text area if no save command is defined. - cm.save(); - } - }, - nohlsearch: function(cm) { - clearSearchHighlight(cm); - }, - delmarks: function(cm, params) { - if (!params.argString || !trim(params.argString)) { - showConfirm(cm, 'Argument required'); - return; - } - - var state = cm.state.vim; - var stream = new CodeMirror.StringStream(trim(params.argString)); - while (!stream.eol()) { - stream.eatSpace(); - - // Record the streams position at the beginning of the loop for use - // in error messages. - var count = stream.pos; - - if (!stream.match(/[a-zA-Z]/, false)) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - - var sym = stream.next(); - // Check if this symbol is part of a range - if (stream.match('-', true)) { - // This symbol is part of a range. - - // The range must terminate at an alphabetic character. - if (!stream.match(/[a-zA-Z]/, false)) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - - var startMark = sym; - var finishMark = stream.next(); - // The range must terminate at an alphabetic character which - // shares the same case as the start of the range. - if (isLowerCase(startMark) && isLowerCase(finishMark) || - isUpperCase(startMark) && isUpperCase(finishMark)) { - var start = startMark.charCodeAt(0); - var finish = finishMark.charCodeAt(0); - if (start >= finish) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - - // Because marks are always ASCII values, and we have - // determined that they are the same case, we can use - // their char codes to iterate through the defined range. - for (var j = 0; j <= finish - start; j++) { - var mark = String.fromCharCode(start + j); - delete state.marks[mark]; - } - } else { - showConfirm(cm, 'Invalid argument: ' + startMark + '-'); - return; - } - } else { - // This symbol is a valid mark, and is not part of a range. - delete state.marks[sym]; - } - } - } - }; - - var exCommandDispatcher = new ExCommandDispatcher(); - - /** - * @param {CodeMirror} cm CodeMirror instance we are in. - * @param {boolean} confirm Whether to confirm each replace. - * @param {Cursor} lineStart Line to start replacing from. - * @param {Cursor} lineEnd Line to stop replacing at. - * @param {RegExp} query Query for performing matches with. - * @param {string} replaceWith Text to replace matches with. May contain $1, - * $2, etc for replacing captured groups using Javascript replace. - * @param {function()} callback A callback for when the replace is done. - */ - function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query, - replaceWith, callback) { - // Set up all the functions. - cm.state.vim.exMode = true; - var done = false; - var lastPos = searchCursor.from(); - function replaceAll() { - cm.operation(function() { - while (!done) { - replace(); - next(); - } - stop(); - }); - } - function replace() { - var text = cm.getRange(searchCursor.from(), searchCursor.to()); - var newText = text.replace(query, replaceWith); - searchCursor.replace(newText); - } - function next() { - var found; - // The below only loops to skip over multiple occurrences on the same - // line when 'global' is not true. - while(found = searchCursor.findNext() && - isInRange(searchCursor.from(), lineStart, lineEnd)) { - if (!global && lastPos && searchCursor.from().line == lastPos.line) { - continue; - } - cm.scrollIntoView(searchCursor.from(), 30); - cm.setSelection(searchCursor.from(), searchCursor.to()); - lastPos = searchCursor.from(); - done = false; - return; - } - done = true; - } - function stop(close) { - if (close) { close(); } - cm.focus(); - if (lastPos) { - cm.setCursor(lastPos); - var vim = cm.state.vim; - vim.exMode = false; - vim.lastHPos = vim.lastHSPos = lastPos.ch; - } - if (callback) { callback(); } - } - function onPromptKeyDown(e, _value, close) { - // Swallow all keys. - CodeMirror.e_stop(e); - var keyName = CodeMirror.keyName(e); - switch (keyName) { - case 'Y': - replace(); next(); break; - case 'N': - next(); break; - case 'A': - // replaceAll contains a call to close of its own. We don't want it - // to fire too early or multiple times. - var savedCallback = callback; - callback = undefined; - cm.operation(replaceAll); - callback = savedCallback; - break; - case 'L': - replace(); - // fall through and exit. - case 'Q': - case 'Esc': - case 'Ctrl-C': - case 'Ctrl-[': - stop(close); - break; - } - if (done) { stop(close); } - return true; - } - - // Actually do replace. - next(); - if (done) { - showConfirm(cm, 'No matches for ' + query.source); - return; - } - if (!confirm) { - replaceAll(); - if (callback) { callback(); }; - return; - } - showPrompt(cm, { - prefix: 'replace with ' + replaceWith + ' (y/n/a/q/l)', - onKeyDown: onPromptKeyDown - }); - } - - CodeMirror.keyMap.vim = { - attach: attachVimMap, - detach: detachVimMap - }; - - function exitInsertMode(cm) { - var vim = cm.state.vim; - var macroModeState = vimGlobalState.macroModeState; - var insertModeChangeRegister = vimGlobalState.registerController.getRegister('.'); - var isPlaying = macroModeState.isPlaying; - var lastChange = macroModeState.lastInsertModeChanges; - // In case of visual block, the insertModeChanges are not saved as a - // single word, so we convert them to a single word - // so as to update the ". register as expected in real vim. - var text = []; - if (!isPlaying) { - var selLength = lastChange.inVisualBlock ? vim.lastSelection.visualBlock.height : 1; - var changes = lastChange.changes; - var text = []; - var i = 0; - // In case of multiple selections in blockwise visual, - // the inserted text, for example: 'foo', is stored as - // 'f', 'f', InsertModeKey 'o', 'o', 'o', 'o'. (if you have a block with 2 lines). - // We push the contents of the changes array as per the following: - // 1. In case of InsertModeKey, just increment by 1. - // 2. In case of a character, jump by selLength (2 in the example). - while (i < changes.length) { - // This loop will convert 'ffoooo' to 'foo'. - text.push(changes[i]); - if (changes[i] instanceof InsertModeKey) { - i++; - } else { - i+= selLength; - } - } - lastChange.changes = text; - cm.off('change', onChange); - CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); - } - if (!isPlaying && vim.insertModeRepeat > 1) { - // Perform insert mode repeat for commands like 3,a and 3,o. - repeatLastEdit(cm, vim, vim.insertModeRepeat - 1, - true /** repeatForInsert */); - vim.lastEditInputState.repeatOverride = vim.insertModeRepeat; - } - delete vim.insertModeRepeat; - vim.insertMode = false; - cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1); - cm.setOption('keyMap', 'vim'); - cm.setOption('disableInput', true); - cm.toggleOverwrite(false); // exit replace mode if we were in it. - // update the ". register before exiting insert mode - insertModeChangeRegister.setText(lastChange.changes.join('')); - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - if (macroModeState.isRecording) { - logInsertModeChange(macroModeState); - } - } - - // The timeout in milliseconds for the two-character ESC keymap should be - // adjusted according to your typing speed to prevent false positives. - defineOption('insertModeEscKeysTimeout', 200, 'number'); - - CodeMirror.keyMap['vim-insert'] = { - // TODO: override navigation keys so that Esc will cancel automatic - // indentation from o, O, i_ - 'Ctrl-N': 'autocomplete', - 'Ctrl-P': 'autocomplete', - 'Enter': function(cm) { - var fn = CodeMirror.commands.newlineAndIndentContinueComment || - CodeMirror.commands.newlineAndIndent; - fn(cm); - }, - fallthrough: ['default'], - attach: attachVimMap, - detach: detachVimMap - }; - - CodeMirror.keyMap['await-second'] = { - fallthrough: ['vim-insert'], - attach: attachVimMap, - detach: detachVimMap - }; - - CodeMirror.keyMap['vim-replace'] = { - 'Backspace': 'goCharLeft', - fallthrough: ['vim-insert'], - attach: attachVimMap, - detach: detachVimMap - }; - - function executeMacroRegister(cm, vim, macroModeState, registerName) { - var register = vimGlobalState.registerController.getRegister(registerName); - var keyBuffer = register.keyBuffer; - var imc = 0; - macroModeState.isPlaying = true; - macroModeState.replaySearchQueries = register.searchQueries.slice(0); - for (var i = 0; i < keyBuffer.length; i++) { - var text = keyBuffer[i]; - var match, key; - while (text) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - match = (/<\w+-.+?>|<\w+>|./).exec(text); - key = match[0]; - text = text.substring(match.index + key.length); - CodeMirror.Vim.handleKey(cm, key, 'macro'); - if (vim.insertMode) { - var changes = register.insertModeChanges[imc++].changes; - vimGlobalState.macroModeState.lastInsertModeChanges.changes = - changes; - repeatInsertModeChanges(cm, changes, 1); - exitInsertMode(cm); - } - } - }; - macroModeState.isPlaying = false; - } - - function logKey(macroModeState, key) { - if (macroModeState.isPlaying) { return; } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.pushText(key); - } - } - - function logInsertModeChange(macroModeState) { - if (macroModeState.isPlaying) { return; } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.pushInsertModeChanges(macroModeState.lastInsertModeChanges); - } - } - - function logSearchQuery(macroModeState, query) { - if (macroModeState.isPlaying) { return; } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.pushSearchQuery(query); - } - } - - /** - * Listens for changes made in insert mode. - * Should only be active in insert mode. - */ - function onChange(_cm, changeObj) { - var macroModeState = vimGlobalState.macroModeState; - var lastChange = macroModeState.lastInsertModeChanges; - if (!macroModeState.isPlaying) { - while(changeObj) { - lastChange.expectCursorActivityForChange = true; - if (changeObj.origin == '+input' || changeObj.origin == 'paste' - || changeObj.origin === undefined /* only in testing */) { - var text = changeObj.text.join('\n'); - lastChange.changes.push(text); - } - // Change objects may be chained with next. - changeObj = changeObj.next; - } - } - } - - /** - * Listens for any kind of cursor activity on CodeMirror. - */ - function onCursorActivity(cm) { - var vim = cm.state.vim; - if (vim.insertMode) { - // Tracking cursor activity in insert mode (for macro support). - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { return; } - var lastChange = macroModeState.lastInsertModeChanges; - if (lastChange.expectCursorActivityForChange) { - lastChange.expectCursorActivityForChange = false; - } else { - // Cursor moved outside the context of an edit. Reset the change. - lastChange.changes = []; - } - } else { - handleExternalSelection(cm, vim); - } - if (vim.visualMode) { - var from, head; - from = head = cm.getCursor('head'); - var anchor = cm.getCursor('anchor'); - var to = Pos(head.line, from.ch + (cursorIsBefore(anchor, head) ? -1 : 1)); - if (cursorIsBefore(to, from)) { - var temp = from; - from = to; - to = temp; - } - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } - vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); - } - } - - function handleExternalSelection(cm, vim) { - var anchor = cm.getCursor('anchor'); - var head = cm.getCursor('head'); - // Enter or exit visual mode to match mouse selection. - if (vim.visualMode && cursorEqual(head, anchor) && lineLength(cm, head.line) > head.ch) { - exitVisualMode(cm); - } else if (!cm.curOp.isVimOp && !vim.visualMode && !vim.insertMode && cm.somethingSelected()) { - vim.visualMode = true; - vim.visualLine = false; - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); - } - if (!cm.curOp.isVimOp) { - if (vim.visualMode) { - updateMark(cm, vim, '<', cursorMin(head, anchor)); - updateMark(cm, vim, '>', cursorMax(head, anchor)); - } else if (!vim.insertMode) { - // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse. - vim.lastHPos = cm.getCursor().ch; - } - } - } - - /** Wrapper for special keys pressed in insert mode */ - function InsertModeKey(keyName) { - this.keyName = keyName; - } - - /** - * Handles raw key down events from the text area. - * - Should only be active in insert mode. - * - For recording deletes in insert mode. - */ - function onKeyEventTargetKeyDown(e) { - var macroModeState = vimGlobalState.macroModeState; - var lastChange = macroModeState.lastInsertModeChanges; - var keyName = CodeMirror.keyName(e); - function onKeyFound() { - lastChange.changes.push(new InsertModeKey(keyName)); - return true; - } - if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) { - CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound); - } - } - - /** - * Repeats the last edit, which includes exactly 1 command and at most 1 - * insert. Operator and motion commands are read from lastEditInputState, - * while action commands are read from lastEditActionCommand. - * - * If repeatForInsert is true, then the function was called by - * exitInsertMode to repeat the insert mode changes the user just made. The - * corresponding enterInsertMode call was made with a count. - */ - function repeatLastEdit(cm, vim, repeat, repeatForInsert) { - var macroModeState = vimGlobalState.macroModeState; - macroModeState.isPlaying = true; - var isAction = !!vim.lastEditActionCommand; - var cachedInputState = vim.inputState; - function repeatCommand() { - if (isAction) { - commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand); - } else { - commandDispatcher.evalInput(cm, vim); - } - } - function repeatInsert(repeat) { - if (macroModeState.lastInsertModeChanges.changes.length > 0) { - // For some reason, repeat cw in desktop VIM does not repeat - // insert mode changes. Will conform to that behavior. - repeat = !vim.lastEditActionCommand ? 1 : repeat; - var changeObject = macroModeState.lastInsertModeChanges; - repeatInsertModeChanges(cm, changeObject.changes, repeat); - } - } - vim.inputState = vim.lastEditInputState; - if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) { - // o and O repeat have to be interlaced with insert repeats so that the - // insertions appear on separate lines instead of the last line. - for (var i = 0; i < repeat; i++) { - repeatCommand(); - repeatInsert(1); - } - } else { - if (!repeatForInsert) { - // Hack to get the cursor to end up at the right place. If I is - // repeated in insert mode repeat, cursor will be 1 insert - // change set left of where it should be. - repeatCommand(); - } - repeatInsert(repeat); - } - vim.inputState = cachedInputState; - if (vim.insertMode && !repeatForInsert) { - // Don't exit insert mode twice. If repeatForInsert is set, then we - // were called by an exitInsertMode call lower on the stack. - exitInsertMode(cm); - } - macroModeState.isPlaying = false; - }; - - function repeatInsertModeChanges(cm, changes, repeat) { - function keyHandler(binding) { - if (typeof binding == 'string') { - CodeMirror.commands[binding](cm); - } else { - binding(cm); - } - return true; - } - var curStart = cm.getCursor(); - var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; - if (inVisualBlock) { - // Set up block selection again for repeating the changes. - var vim = cm.state.vim; - var block = vim.lastSelection.visualBlock; - var curEnd = Pos(curStart.line + block.height-1, curStart.ch); - cm.setCursor(curStart); - selectBlock(cm, curEnd); - repeat = cm.listSelections().length; - cm.setCursor(curStart); - } - for (var i = 0; i < repeat; i++) { - for (var j = 0; j < changes.length; j++) { - var change = changes[j]; - if (change instanceof InsertModeKey) { - CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler); - } else { - var cur = cm.getCursor(); - cm.replaceRange(change, cur, cur); - } - } - if (inVisualBlock) { - curStart.line++; - cm.setCursor(curStart); - } - } - } - - resetVimGlobalState(); - //}; - // Initialize Vim and make it available as an API. - CodeMirror.Vim = Vim(); - - Vim = CodeMirror.Vim; - - specialKey = {'return':'CR',backspace:'BS','delete':'Del',esc:'Esc', - left:'Left',right:'Right',up:'Up',down:'Down',space: 'Space', - home:'Home',end:'End',pageup:'PageUp',pagedown:'PageDown', enter: 'CR' - }; - function lookupKey(hashId, key, e) { - if (key.length > 1 && key[0] == "n") { - key = key.replace("numpad", ""); - } - key = specialKey[key] || key; - var name = ''; - if (e.ctrlKey) { name += 'C-'; } - if (e.altKey) { name += 'A-'; } - if (e.shiftKey) { name += 'S-'; } - - name += key; - if (name.length > 1) { name = '<' + name + '>'; } - return name; - } - var handleKey = Vim.handleKey - Vim.handleKey = function(cm, key, origin) { - return cm.operation(function() { - return handleKey(cm, key, origin); - }, true); - } - function cloneVimState(state) { - var n = new state.constructor(); - Object.keys(state).forEach(function(key) { - var o = state[key]; - if (Array.isArray(o)) - o = o.slice(); - else if (o && typeof o == "object" && o.constructor != Object) - o = cloneVimState(o); - n[key] = o; - }); - return n; - } - function multiSelectHandleKey(cm, key, origin) { - var isHandled = false; - var vim = Vim.maybeInitVimState_(cm); - var visualBlock = vim.visualBlock || vim.wasInVisualBlock; - if (vim.wasInVisualBlock && !cm.ace.inMultiSelectMode) { - vim.wasInVisualBlock = false; - } else if (cm.ace.inMultiSelectMode && vim.visualBlock) { - vim.wasInVisualBlock = true; - } - - if (key == '' && !vim.insertMode && !vim.visualMode && cm.ace.inMultiSelectMode) { - cm.ace.exitMultiSelectMode(); - } else if (visualBlock || !cm.ace.inMultiSelectMode || cm.ace.inVirtualSelectionMode) { - isHandled = Vim.handleKey(cm, key, origin); - } else { - var old = cloneVimState(vim); - cm.operation(function() { - cm.ace.forEachSelection(function() { - var sel = cm.ace.selection; - cm.state.vim.lastHPos = sel.$desiredColumn == null ? sel.lead.column : sel.$desiredColumn; - isHandled = handleKey(cm, key, origin); - sel.$desiredColumn = cm.state.vim.lastHPos == -1 ? null : cm.state.vim.lastHPos; - if (cm.virtualSelectionMode()) { - cm.state.vim = cloneVimState(old); - } - }); - if (cm.curOp.cursorActivity && !isHandled) - cm.curOp.cursorActivity = false; - }, true); - } - return isHandled; - }; - exports.CodeMirror = CodeMirror; - var getVim = Vim.maybeInitVimState_; - exports.handler = { - $id: "ace/keyboard/vim", - drawCursor: function(style, pixelPos, config, sel, session) { - var vim = this.state.vim || {}; - var w = config.characterWidth; - var h = config.lineHeight; - var top = pixelPos.top; - var left = pixelPos.left; - if (!vim.insertMode) { - var isbackwards = !sel.cursor - ? session.selection.isBackwards() || session.selection.isEmpty() - : Range.comparePoints(sel.cursor, sel.start) <= 0 - if (!isbackwards && left > w) - left -= w - } - if (!vim.insertMode && vim.status) { - h = h / 2; - top += h; - } - style.left = left + "px"; - style.top = top + "px"; - style.width = w + "px"; - style.height = h + "px"; - }, - handleKeyboard: function(data, hashId, key, keyCode, e) { - var editor = data.editor; - var cm = editor.state.cm; - var vim = getVim(cm); - if (keyCode == -1) return; - - if (key == "c" && hashId == 1) { // key == "ctrl-c" - if (!useragent.isMac && editor.getCopyText()) { - editor.once("copy", function() { - editor.selection.clearSelection(); - }); - return {command: "null", passEvent: true}; - } - return {command: coreCommands.stop}; - } else if (!vim.insertMode) { - if (useragent.isMac && this.handleMacRepeat(data, hashId, key)) { - hashId = -1; - key = data.inputChar; - } - } - - if (hashId == -1 || hashId & 1 || hashId === 0 && key.length > 1) { - var insertMode = vim.insertMode; - var name = lookupKey(hashId, key, e || {}); - if (vim.status == null) - vim.status = ""; - var isHandled = multiSelectHandleKey(cm, name, 'user'); - vim = getVim(cm); // may be changed by multiSelectHandleKey - if (isHandled && vim.status != null) - vim.status += name; - else if (vim.status == null) - vim.status = ""; - cm._signal("changeStatus"); - if (!isHandled && (hashId != -1 || insertMode)) - return; - return {command: "null", passEvent: !isHandled}; - } - }, - attach: function(editor) { - if (!editor.state) editor.state = {}; - var cm = new CodeMirror(editor); - editor.state.cm = cm; - editor.$vimModeHandler = this; - CodeMirror.keyMap.vim.attach(cm); - getVim(cm).status = null; - cm.on('vim-command-done', function() { - if (cm.virtualSelectionMode()) return; - getVim(cm).status = null; - cm.ace._signal("changeStatus"); - cm.ace.session.markUndoGroup(); - }); - cm.on("changeStatus", function() { - cm.ace.renderer.updateCursor(); - cm.ace._signal("changeStatus"); - }); - cm.on("vim-mode-change", function() { - if (cm.virtualSelectionMode()) return; - cm.ace.renderer.setStyle("normal-mode", !getVim(cm).insertMode); - cm._signal("changeStatus"); - }); - cm.ace.renderer.setStyle("normal-mode", !getVim(cm).insertMode); - editor.renderer.$cursorLayer.drawCursor = this.drawCursor.bind(cm); - // renderVirtualNumbers.attach(editor); - this.updateMacCompositionHandlers(editor, true); - }, - detach: function(editor) { - var cm = editor.state.cm; - CodeMirror.keyMap.vim.detach(cm); - cm.destroy(); - editor.state.cm = null; - editor.$vimModeHandler = null; - editor.renderer.$cursorLayer.drawCursor = null; - editor.renderer.setStyle("normal-mode", false); - // renderVirtualNumbers.detach(editor); - this.updateMacCompositionHandlers(editor, false); - }, - getStatusText: function(editor) { - var cm = editor.state.cm; - var vim = getVim(cm); - if (vim.insertMode) - return "INSERT"; - var status = ""; - if (vim.visualMode) { - status += "VISUAL"; - if (vim.visualLine) - status += " LINE"; - if (vim.visualBlock) - status += " BLOCK"; - } - if (vim.status) - status += (status ? " " : "") + vim.status; - return status; - }, - // workaround for j not repeating with `defaults write -g ApplePressAndHoldEnabled -bool true` - handleMacRepeat: function(data, hashId, key) { - if (hashId == -1) { - // record key - data.inputChar = key; - data.lastEvent = "input"; - } else if (data.inputChar && data.$lastHash == hashId && data.$lastKey == key) { - // check for repeated keypress - if (data.lastEvent == "input") { - data.lastEvent = "input1"; - } else if (data.lastEvent == "input1") { - // simulate textinput - return true; - } - } else { - // reset - data.$lastHash = hashId; - data.$lastKey = key; - data.lastEvent = "keypress"; - } - }, - // on mac, with some keyboard layouts (e.g swedish) ^ starts composition, we don't need it in normal mode - updateMacCompositionHandlers: function(editor, enable) { - var onCompositionUpdateOverride = function(text) { - if (util.currentMode !== "insert") { - var el = this.textInput.getElement(); - el.blur(); - el.focus(); - el.value = text; - } else { - this.onCompositionUpdateOrig(text); - } - }; - var onCompositionStartOverride = function(text) { - if (util.currentMode === "insert") { - this.onCompositionStartOrig(text); - } - }; - if (enable) { - if (!editor.onCompositionUpdateOrig) { - editor.onCompositionUpdateOrig = editor.onCompositionUpdate; - editor.onCompositionUpdate = onCompositionUpdateOverride; - editor.onCompositionStartOrig = editor.onCompositionStart; - editor.onCompositionStart = onCompositionStartOverride; - } - } else { - if (editor.onCompositionUpdateOrig) { - editor.onCompositionUpdate = editor.onCompositionUpdateOrig; - editor.onCompositionUpdateOrig = null; - editor.onCompositionStart = editor.onCompositionStartOrig; - editor.onCompositionStartOrig = null; - } - } - } - } - var renderVirtualNumbers = { - getText: function(session, row) { - return (Math.abs(session.selection.lead.row - row) || (row + 1 + (row < 9? "\xb7" : "" ))) + "" - }, - getWidth: function(session, lastLineNumber, config) { - return session.getLength().toString().length * config.characterWidth; - }, - update: function(e, editor) { - editor.renderer.$loop.schedule(editor.renderer.CHANGE_GUTTER) - }, - attach: function(editor) { - editor.renderer.$gutterLayer.$renderer = this; - editor.on("changeSelection", this.update); - }, - detach: function(editor) { - editor.renderer.$gutterLayer.$renderer = null; - editor.off("changeSelection", this.update); - } - }; - Vim.defineOption({ - name: "wrap", - set: function(value, cm) { - if (cm) {cm.ace.setOption("wrap", value)} - }, - type: "boolean" - }, false); - defaultKeymap.push( - { keys: 'zc', type: 'action', action: 'fold', actionArgs: { open: false } }, - { keys: 'zC', type: 'action', action: 'fold', actionArgs: { open: false, all: true } }, - { keys: 'zo', type: 'action', action: 'fold', actionArgs: { open: true, } }, - { keys: 'zO', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, - { keys: 'za', type: 'action', action: 'fold', actionArgs: { toggle: true } }, - { keys: 'zA', type: 'action', action: 'fold', actionArgs: { toggle: true, all: true } }, - { keys: 'zf', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, - { keys: 'zd', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, - - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAbove" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelow" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAboveSkipCurrent" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelowSkipCurrent" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreBefore" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreAfter" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectNextBefore" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectNextAfter" } } - ); - actions.aceCommand = function(cm, actionArgs, vim) { - cm.vimCmd = actionArgs; - if (cm.ace.inVirtualSelectionMode) - cm.ace.on("beforeEndOperation", delayedExecAceCommand); - else - delayedExecAceCommand(null, cm.ace) - }; - function delayedExecAceCommand(op, ace) { - ace.off("beforeEndOperation", delayedExecAceCommand); - var cmd = ace.state.cm.vimCmd; - if (cmd) { - ace.execCommand(cmd.name, cmd.args); - } - ace.curOp = ace.prevOp; - } - actions.fold = function(cm, actionArgs, vim) { - cm.ace.execCommand(['toggleFoldWidget', 'toggleFoldWidget', 'foldOther', 'unfoldall' - ][(actionArgs.all ? 2 : 0) + (actionArgs.open ? 1 : 0)]); - }, - - Vim.map("Y", "yy"); -}); diff --git a/lib/ace/keyboard/vim2_test.js b/lib/ace/keyboard/vim2_test.js deleted file mode 100644 index b437bcd7..00000000 --- a/lib/ace/keyboard/vim2_test.js +++ /dev/null @@ -1,3710 +0,0 @@ - -if (typeof process !== "undefined") { - require("amd-loader"); -} - -define(function(require, exports, module) { - -var EditSession = require("./../edit_session").EditSession; -var Editor = require("./../editor").Editor; -var UndoManager = require("./../undomanager").UndoManager; -var MockRenderer = require("./../test/mockrenderer").MockRenderer; -var JavaScriptMode = require("./../mode/javascript").Mode; -var VirtualRenderer = require("./../virtual_renderer").VirtualRenderer; -var assert = require("./../test/assertions"); -var keys = require("./../lib/keys"); -var vim = require("./vim2"); - -var el = document.createElement("div"); -el.style.position = "fixed"; -el.style.left = "20px"; -el.style.top = "30px"; -el.style.width = "500px"; -el.style.height = "300px"; -document.body.appendChild(el); - -if (!el.getBoundingClientRect) - return console.log("Skipping test: This test only runs in the browser"); - -var renderer = new VirtualRenderer(el); -editor = new Editor(renderer);//(new MockRenderer()); -editor.session.setUndoManager(new UndoManager()); -editor.session.setUseWorker(false); -editor.session.setMode(new JavaScriptMode()); -function CodeMirror(place, opts) { - if (opts.value != null) - editor.session.setValue(opts.value); - editor.setOption("wrap", opts.lineWrapping); - editor.setOption("useSoftTabs", !opts.indentWithTabs); - editor.setKeyboardHandler(null); - editor.setKeyboardHandler(vim.handler); - var cm = editor.state.cm; - cm.setOption("tabSize", opts.tabSize || 4); - cm.setOption("indentUnit", opts.indentUnit || 2); - - cm.setSize = function(w, h) { - var changed = false; - if (w && editor.w != w) { - changed = true; - el.style.width = (editor.w = w) + "px"; - } - if (h && editor.h != h) { - changed = true; - el.style.height = (editor.h = h) + "px"; - } - if (changed) - editor.resize(true); - }; - cm.setSize(500, 300); - return cm; -} -for (var key in vim.CodeMirror) - CodeMirror[key] = vim.CodeMirror[key]; -var editor; -var i = 0; -function test(name, fn) { - // if (name != 'vim_search_history') return - // for (i = 0; i < 1000; i++) - // exports["test " + name + i] = fn; // vim_ex_global_confirm - if (i++ < 0 || /- /.test(name)) - exports["test " + name] = function() {}; - else - exports["test " + name] = fn; -} - - -// cm.setBookmark({ch: 5, line: 0}) -// cm.setBookmark({ch: 4, line: 0}) -// cm.replaceRange("x-", {ch: 4, line: 0}, {ch: 5, line: 0}); [editor.$vimModeHandler.cm.marks[0].find(),editor.$vimModeHandler.cm.marks[1].find()] - -var lineText, verbose, phantom; -var Pos = CodeMirror.Pos; -var place = document.createElement("div"); -var eqPos = assert.deepEqual; -var eq = assert.equal; -var is = assert.ok; - - -var code = '' + -' wOrd1 (#%\n' + -' word3] \n' + -'aopop pop 0 1 2 3 4\n' + -' (a) [b] {c} \n' + -'int getchar(void) {\n' + -' static char buf[BUFSIZ];\n' + -' static char *bufp = buf;\n' + -' if (n == 0) { /* buffer is empty */\n' + -' n = read(0, buf, sizeof buf);\n' + -' bufp = buf;\n' + -' }\n' + -'\n' + -' return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n' + -' \n' + -'}\n'; - -var lines = (function() { - lineText = code.split('\n'); - var ret = []; - for (var i = 0; i < lineText.length; i++) { - ret[i] = { - line: i, - length: lineText[i].length, - lineText: lineText[i], - textStart: /^\s*/.exec(lineText[i])[0].length - }; - } - return ret; -})(); -var endOfDocument = makeCursor(lines.length - 1, - lines[lines.length - 1].length); -var wordLine = lines[0]; -var bigWordLine = lines[1]; -var charLine = lines[2]; -var bracesLine = lines[3]; -var seekBraceLine = lines[4]; - -var word1 = { - start: { line: wordLine.line, ch: 1 }, - end: { line: wordLine.line, ch: 5 } -}; -var word2 = { - start: { line: wordLine.line, ch: word1.end.ch + 2 }, - end: { line: wordLine.line, ch: word1.end.ch + 4 } -}; -var word3 = { - start: { line: bigWordLine.line, ch: 1 }, - end: { line: bigWordLine.line, ch: 5 } -}; -var bigWord1 = word1; -var bigWord2 = word2; -var bigWord3 = { - start: { line: bigWordLine.line, ch: 1 }, - end: { line: bigWordLine.line, ch: 7 } -}; -var bigWord4 = { - start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 }, - end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 } -}; - -var oChars = [ { line: charLine.line, ch: 1 }, - { line: charLine.line, ch: 3 }, - { line: charLine.line, ch: 7 } ]; -var pChars = [ { line: charLine.line, ch: 2 }, - { line: charLine.line, ch: 4 }, - { line: charLine.line, ch: 6 }, - { line: charLine.line, ch: 8 } ]; -var numChars = [ { line: charLine.line, ch: 10 }, - { line: charLine.line, ch: 12 }, - { line: charLine.line, ch: 14 }, - { line: charLine.line, ch: 16 }, - { line: charLine.line, ch: 18 }]; -var parens1 = { - start: { line: bracesLine.line, ch: 1 }, - end: { line: bracesLine.line, ch: 3 } -}; -var squares1 = { - start: { line: bracesLine.line, ch: 5 }, - end: { line: bracesLine.line, ch: 7 } -}; -var curlys1 = { - start: { line: bracesLine.line, ch: 9 }, - end: { line: bracesLine.line, ch: 11 } -}; -var seekOutside = { - start: { line: seekBraceLine.line, ch: 1 }, - end: { line: seekBraceLine.line, ch: 16 } -}; -var seekInside = { - start: { line: seekBraceLine.line, ch: 14 }, - end: { line: seekBraceLine.line, ch: 11 } -}; - -function copyCursor(cur) { - return { ch: cur.ch, line: cur.line }; -} - -function forEach(arr, func) { - for (var i = 0; i < arr.length; i++) { - func(arr[i], i, arr); - } -} - -function testVim(name, run, opts, expectedFail) { - var vimOpts = { - lineNumbers: true, - vimMode: true, - showCursorWhenSelecting: true, - value: code - }; - for (var prop in opts) { - if (opts.hasOwnProperty(prop)) { - vimOpts[prop] = opts[prop]; - } - } - return test('vim_' + name, function() { - var place = document.getElementById("testground"); - var cm = CodeMirror(place, vimOpts); - var vim = CodeMirror.Vim.maybeInitVimState_(cm); - - function doKeysFn(cm) { - return function(args) { - if (args instanceof Array) { - arguments = args; - } - for (var i = 0; i < arguments.length; i++) { - CodeMirror.Vim.handleKey(cm, arguments[i]); - } - } - } - function doInsertModeKeysFn(cm) { - return function(args) { - if (args instanceof Array) { arguments = args; } - function executeHandler(handler) { - if (typeof handler == 'string') { - CodeMirror.commands[handler](cm); - } else { - handler(cm); - } - return true; - } - for (var i = 0; i < arguments.length; i++) { - var key = arguments[i]; - // Find key in keymap and handle. - var handled = CodeMirror.lookupKey(key, 'vim-insert', executeHandler); - // Record for insert mode. - if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') { - var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges; - if (lastChange) { - lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key)); - } - } - } - } - } - function doExFn(cm) { - return function(command) { - cm.openDialog = helpers.fakeOpenDialog(command); - helpers.doKeys(':'); - } - } - function assertCursorAtFn(cm) { - return function(line, ch) { - var pos; - if (ch == null && typeof line.line == 'number') { - pos = line; - } else { - pos = makeCursor(line, ch); - } - eqPos(pos, cm.getCursor()); - } - } - function fakeOpenDialog(result) { - return function(text, callback) { - return callback(result); - } - } - function fakeOpenNotification(matcher) { - return function(text) { - matcher(text); - } - } - var helpers = { - doKeys: doKeysFn(cm), - // Warning: Only emulates keymap events, not character insertions. Use - // replaceRange to simulate character insertions. - // Keys are in CodeMirror format, NOT vim format. - doInsertModeKeys: doInsertModeKeysFn(cm), - doEx: doExFn(cm), - assertCursorAt: assertCursorAtFn(cm), - fakeOpenDialog: fakeOpenDialog, - fakeOpenNotification: fakeOpenNotification, - getRegisterController: function() { - return CodeMirror.Vim.getRegisterController(); - } - } - CodeMirror.Vim.resetVimGlobalState_(); - var successful = false; - var savedOpenNotification = cm.openNotification; - try { - run(cm, vim, helpers); - successful = true; - } finally { - cm.openNotification = savedOpenNotification; - // if (!successful || verbose) { - // place.style.visibility = "visible"; - // } else { - // place.removeChild(cm.getWrapperElement()); - // } - } - }, expectedFail); -}; -testVim('qq@q', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'q', 'l', 'l', 'q'); - helpers.assertCursorAt(0,2); - helpers.doKeys('@', 'q'); - helpers.assertCursorAt(0,4); -}, { value: ' '}); -testVim('@@', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'q', 'l', 'l', 'q'); - helpers.assertCursorAt(0,2); - helpers.doKeys('@', 'q'); - helpers.assertCursorAt(0,4); - helpers.doKeys('@', '@'); - helpers.assertCursorAt(0,6); -}, { value: ' '}); -var jumplistScene = ''+ - 'word\n'+ - '(word)\n'+ - '{word\n'+ - 'word.\n'+ - '\n'+ - 'word search\n'+ - '}word\n'+ - 'word\n'+ - 'word\n'; -function testJumplist(name, keys, endPos, startPos, dialog) { - endPos = makeCursor(endPos[0], endPos[1]); - startPos = makeCursor(startPos[0], startPos[1]); - testVim(name, function(cm, vim, helpers) { - CodeMirror.Vim.resetVimGlobalState_(); - if(dialog)cm.openDialog = helpers.fakeOpenDialog('word'); - cm.setCursor(startPos); - helpers.doKeys.apply(null, keys); - helpers.assertCursorAt(endPos); - }, {value: jumplistScene}); -}; -testJumplist('jumplist_H', ['H', ''], [5,2], [5,2]); -testJumplist('jumplist_M', ['M', ''], [2,2], [2,2]); -testJumplist('jumplist_L', ['L', ''], [2,2], [2,2]); -testJumplist('jumplist_[[', ['[', '[', ''], [5,2], [5,2]); -testJumplist('jumplist_]]', [']', ']', ''], [2,2], [2,2]); -testJumplist('jumplist_G', ['G', ''], [5,2], [5,2]); -testJumplist('jumplist_gg', ['g', 'g', ''], [5,2], [5,2]); -testJumplist('jumplist_%', ['%', ''], [1,5], [1,5]); -testJumplist('jumplist_{', ['{', ''], [1,5], [1,5]); -testJumplist('jumplist_}', ['}', ''], [1,5], [1,5]); -testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', ''], [1,0], [1,5]); -testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', ''], [1,5], [1,5]); -testJumplist('jumplist_*_cachedCursor', ['*', ''], [1,3], [1,3]); -testJumplist('jumplist_#_cachedCursor', ['#', ''], [1,3], [1,3]); -testJumplist('jumplist_n', ['#', 'n', ''], [1,1], [2,3]); -testJumplist('jumplist_N', ['#', 'N', ''], [1,1], [2,3]); -testJumplist('jumplist_repeat_', ['*', '*', '*', '3', ''], [2,3], [2,3]); -testJumplist('jumplist_repeat_', ['*', '*', '*', '3', '', '2', ''], [5,0], [2,3]); -testJumplist('jumplist_repeated_motion', ['3', '*', ''], [2,3], [2,3]); -testJumplist('jumplist_/', ['/', ''], [2,3], [2,3], 'dialog'); -testJumplist('jumplist_?', ['?', ''], [2,3], [2,3], 'dialog'); -testJumplist('jumplist_skip_delted_mark', - ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], - [0,2], [0,2]); -testJumplist('jumplist_skip_delted_mark', - ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], - [1,0], [0,2]); - -/** - * @param name Name of the test - * @param keys An array of keys or a string with a single key to simulate. - * @param endPos The expected end position of the cursor. - * @param startPos The position the cursor should start at, defaults to 0, 0. - */ -function testMotion(name, keys, endPos, startPos) { - testVim(name, function(cm, vim, helpers) { - if (!startPos) { - startPos = { line: 0, ch: 0 }; - } - cm.setCursor(startPos); - helpers.doKeys(keys); - helpers.assertCursorAt(endPos); - }); -}; - -function makeCursor(line, ch) { - return { line: line, ch: ch }; -}; - -function offsetCursor(cur, offsetLine, offsetCh) { - return { line: cur.line + offsetLine, ch: cur.ch + offsetCh }; -}; - -// Motion tests -testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4)); -testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4)); -testMotion('h', 'h', makeCursor(0, 0), word1.start); -testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end); -testMotion('l', 'l', makeCursor(0, 1)); -testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2)); -testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end); -testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end); -testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument); -testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end); -testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4)); -testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4)); -testMotion('w', 'w', word1.start); -testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2)); -testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51)); -testMotion('w_repeat', ['2', 'w'], word2.start); -testMotion('w_wrap', ['w'], word3.start, word2.start); -testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument); -testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0)); -testMotion('W', 'W', bigWord1.start); -testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start); -testMotion('e', 'e', word1.end); -testMotion('e_repeat', ['2', 'e'], word2.end); -testMotion('e_wrap', 'e', word3.end, word2.end); -testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument); -testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0)); -testMotion('b', 'b', word3.start, word3.end); -testMotion('b_repeat', ['2', 'b'], word2.start, word3.end); -testMotion('b_wrap', 'b', word2.start, word3.start); -testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0)); -testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument); -testMotion('ge', ['g', 'e'], word2.end, word3.end); -testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start); -testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start); -testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0), - makeCursor(0, 0)); -testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument); -testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart), - makeCursor(3, 1)); -testMotion('gg_repeat', ['3', 'g', 'g'], - makeCursor(lines[2].line, lines[2].textStart)); -testMotion('G', 'G', - makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart), - makeCursor(3, 1)); -testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line, - lines[2].textStart)); -// TODO: Make the test code long enough to test Ctrl-F and Ctrl-B. -testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8)); -testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8)); -testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8)); -testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4)); -testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8)); -testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1)); -testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1), - makeCursor(0, 3)); -testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0)); -testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]); -testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0)); -testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1), - makeCursor(charLine.line, 0)); -testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1), - pChars[0]); -testMotion('F', ['F', 'p'], pChars[0], pChars[1]); -testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]); -testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]); -testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]); -testMotion('%_parens', ['%'], parens1.end, parens1.start); -testMotion('%_squares', ['%'], squares1.end, squares1.start); -testMotion('%_braces', ['%'], curlys1.end, curlys1.start); -testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start); -testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start); -testVim('%_seek_skip', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,9); -}, {value:'01234"("()'}); -testVim('%_skip_string', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,4); - cm.setCursor(0,2); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,0); -}, {value:'(")")'}); -(')') -testVim('%_skip_comment', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,6); - cm.setCursor(0,3); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,0); -}, {value:'(/*)*/)'}); -// Make sure that moving down after going to the end of a line always leaves you -// at the end of a line, but preserves the offset in other cases -testVim('Changing lines after Eol operation', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['$']); - helpers.doKeys(['j']); - // After moving to Eol and then down, we should be at Eol of line 2 - helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 }); - helpers.doKeys(['j']); - // After moving down, we should be at Eol of line 3 - helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 }); - helpers.doKeys(['h']); - helpers.doKeys(['j']); - // After moving back one space and then down, since line 4 is shorter than line 2, we should - // be at Eol of line 2 - 1 - helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 }); - helpers.doKeys(['j']); - helpers.doKeys(['j']); - // After moving down again, since line 3 has enough characters, we should be back to the - // same place we were at on line 1 - helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 }); -}); -//making sure gj and gk recover from clipping -testVim('gj_gk_clipping', function(cm,vim,helpers){ - cm.setCursor(0, 1); - helpers.doKeys('g','j','g','j'); - helpers.assertCursorAt(2, 1); - helpers.doKeys('g','k','g','k'); - helpers.assertCursorAt(0, 1); -},{value: 'line 1\n\nline 2'}); -//testing a mix of j/k and gj/gk -testVim('j_k_and_gj_gk', function(cm,vim,helpers){ - cm.setSize(120); - cm.setCursor(0, 0); - //go to the last character on the first line - helpers.doKeys('$'); - //move up/down on the column within the wrapped line - //side-effect: cursor is not locked to eol anymore - helpers.doKeys('g','k'); - var cur=cm.getCursor(); - eq(cur.line,0); - is((cur.ch<176),'gk didn\'t move cursor back (1)'); - helpers.doKeys('g','j'); - helpers.assertCursorAt(0, 176); - //should move to character 177 on line 2 (j/k preserve character index within line) - helpers.doKeys('j'); - //due to different line wrapping, the cursor can be on a different screen-x now - //gj and gk preserve screen-x on movement, much like moveV - helpers.doKeys('3','g','k'); - cur=cm.getCursor(); - eq(cur.line,1); - is((cur.ch<176),'gk didn\'t move cursor back (2)'); - helpers.doKeys('g','j','2','g','j'); - //should return to the same character-index - helpers.doKeys('k'); - helpers.assertCursorAt(0, 176); -},{ lineWrapping:true, value: 'This line is intentially long to test movement of gj and gk over wrapped lines. I will start on the end of this line, then make a step up and back to set the origin for j and k.\nThis line is supposed to be even longer than the previous. I will jump here and make another wiggle with gj and gk, before I jump back to the line above. Both wiggles should not change my cursor\'s target character but both j/k and gj/gk change each other\'s reference position.'}); -testVim('gj_gk', function(cm, vim, helpers) { - if (phantom) return; - cm.setSize(120); - // Test top of document edge case. - cm.setCursor(0, 4); - helpers.doKeys('g', 'j'); - helpers.doKeys('10', 'g', 'k'); - helpers.assertCursorAt(0, 4); - - // Test moving down preserves column position. - helpers.doKeys('g', 'j'); - var pos1 = cm.getCursor(); - var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4}; - helpers.doKeys('g', 'j'); - helpers.assertCursorAt(expectedPos2); - - // Move to the last character - cm.setCursor(0, 0); - // Move left to reset HSPos - helpers.doKeys('h'); - // Test bottom of document edge case. - helpers.doKeys('100', 'g', 'j'); - var endingPos = cm.getCursor(); - is(endingPos != 0, 'gj should not be on wrapped line 0'); - var topLeftCharCoords = cm.charCoords(makeCursor(0, 0)); - var endingCharCoords = cm.charCoords(endingPos); - is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0'); -},{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' }); -testVim('}', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('}'); - helpers.assertCursorAt(1, 0); - cm.setCursor(0, 0); - helpers.doKeys('2', '}'); - helpers.assertCursorAt(4, 0); - cm.setCursor(0, 0); - helpers.doKeys('6', '}'); - helpers.assertCursorAt(5, 0); -}, { value: 'a\n\nb\nc\n\nd' }); -testVim('{', function(cm, vim, helpers) { - cm.setCursor(5, 0); - helpers.doKeys('{'); - helpers.assertCursorAt(4, 0); - cm.setCursor(5, 0); - helpers.doKeys('2', '{'); - helpers.assertCursorAt(1, 0); - cm.setCursor(5, 0); - helpers.doKeys('6', '{'); - helpers.assertCursorAt(0, 0); -}, { value: 'a\n\nb\nc\n\nd' }); - -// Operator tests -testVim('dl', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('d', 'l'); - eq('word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dl_eol', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('d', 'l'); - eq(' word1', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 6); -}, { value: ' word1 ' }); -testVim('dl_repeat', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('2', 'd', 'l'); - eq('ord1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' w', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dh', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'h'); - eq(' wrd1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('o', register.toString()); - is(!register.linewise); - eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dj', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'j'); - eq(' word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' word1\nword2\n', register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2\n word3' }); -testVim('dj_end_of_document', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'j'); - eq(' word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1 ' }); -testVim('dk', function(cm, vim, helpers) { - var curStart = makeCursor(1, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'k'); - eq(' word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' word1\nword2\n', register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2\n word3' }); -testVim('dk_start_of_document', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'k'); - eq(' word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1 ' }); -testVim('dw_space', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('d', 'w'); - eq('word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dw_word', function(cm, vim, helpers) { - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('d', 'w'); - eq(' word2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1 ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 word2' }); -testVim('dw_only_word', function(cm, vim, helpers) { - // Test that if there is only 1 word left, dw deletes till the end of the - // line. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1 ', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1 ' }); -testVim('dw_eol', function(cm, vim, helpers) { - // Assert that dw does not delete the newline if last word to delete is at end - // of line. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' \nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2' }); -testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) { - // Assert that dw does not delete the newline if last word to delete is at end - // of line and it is followed by multiple newlines. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' \n\nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\n\nword2' }); -testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq(' \nword', cm.getValue()); -}, { value: '\n \nword' }); -testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('word', cm.getValue()); -}, { value: '\nword' }); -testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n', cm.getValue()); -}, { value: '\n\n' }); -testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n \n', cm.getValue()); -}, { value: ' \n \n' }); -testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n\n', cm.getValue()); -}, { value: ' \n\n' }); -testVim('dw_word_whitespace_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n \nword2', cm.getValue()); -}, { value: 'word1\n \nword2'}) -testVim('dw_end_of_document', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('d', 'w'); - eq('\nab', cm.getValue()); -}, { value: '\nabc' }); -testVim('dw_repeat', function(cm, vim, helpers) { - // Assert that dw does delete newline if it should go to the next line, and - // that repeat works properly. - cm.setCursor(0, 1); - helpers.doKeys('d', '2', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2' }); -testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'e'); - eq('\n\n', cm.getValue()); -}, { value: 'word\n\n' }); -testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('d', 'e'); - eq('wor', cm.getValue()); -}, { value: 'word\n\n\n' }); -testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'e'); - eq('', cm.getValue()); -}, { value: ' \n\n\n' }); -testVim('de_end_of_document', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('d', 'e'); - eq('\nab', cm.getValue()); -}, { value: '\nabc' }); -testVim('db_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('\n\n', cm.getValue()); -}, { value: '\n\n\n' }); -testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('\nword', cm.getValue()); -}, { value: '\n\nword' }); -testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 3); - helpers.doKeys('d', 'b'); - eq('\n\nd', cm.getValue()); -}, { value: '\n\nword' }); -testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('', cm.getValue()); -}, { value: '\n \n' }); -testVim('db_start_of_document', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'b'); - eq('abc\n', cm.getValue()); -}, { value: 'abc\n' }); -testVim('dge_empty_lines', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doKeys('d', 'g', 'e'); - // Note: In real VIM the result should be '', but it's not quite consistent, - // since 2 newlines are deleted. But in the similar case of word\n\n, only - // 1 newline is deleted. We'll diverge from VIM's behavior since it's much - // easier this way. - eq('\n', cm.getValue()); -}, { value: '\n\n' }); -testVim('dge_word_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doKeys('d', 'g', 'e'); - eq('wor\n', cm.getValue()); -}, { value: 'word\n\n'}); -testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'g', 'e'); - eq('', cm.getValue()); -}, { value: '\n \n' }); -testVim('dge_start_of_document', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'g', 'e'); - eq('bc\n', cm.getValue()); -}, { value: 'abc\n' }); -testVim('d_inclusive', function(cm, vim, helpers) { - // Assert that when inclusive is set, the character the cursor is on gets - // deleted too. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('d', 'e'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('d_reverse', function(cm, vim, helpers) { - // Test that deleting in reverse works. - cm.setCursor(1, 0); - helpers.doKeys('d', 'b'); - eq(' word2 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\n', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2 ' }); -testVim('dd', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 1, ch: 0 }); - var expectedLineCount = cm.lineCount() - 1; - helpers.doKeys('d', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[1].textStart); -}); -testVim('dd_prefix_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 2, ch: 0 }); - var expectedLineCount = cm.lineCount() - 2; - helpers.doKeys('2', 'd', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[2].textStart); -}); -testVim('dd_motion_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 2, ch: 0 }); - var expectedLineCount = cm.lineCount() - 2; - helpers.doKeys('d', '2', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[2].textStart); -}); -testVim('dd_multiply_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount() - 6; - helpers.doKeys('2', 'd', '3', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[6].textStart); -}); -testVim('dd_lastline', function(cm, vim, helpers) { - cm.setCursor(cm.lineCount(), 0); - var expectedLineCount = cm.lineCount() - 1; - helpers.doKeys('d', 'd'); - eq(expectedLineCount, cm.lineCount()); - helpers.assertCursorAt(cm.lineCount() - 1, 0); -}); -testVim('dd_only_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - var expectedRegister = cm.getValue() + "\n"; - helpers.doKeys('d','d'); - eq(1, cm.lineCount()); - eq('', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedRegister, register.toString()); -}, { value: "thisistheonlyline" }); -// Yank commands should behave the exact same as d commands, expect that nothing -// gets deleted. -testVim('yw_repeat', function(cm, vim, helpers) { - // Assert that yw does yank newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('y', '2', 'w'); - eq(' word1\nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2' }); -testVim('yy_multiply_repeat', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount(); - helpers.doKeys('2', 'y', '3', 'y'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - eqPos(curStart, cm.getCursor()); -}); -// Change commands behave like d commands except that it also enters insert -// mode. In addition, when the change is linewise, an additional newline is -// inserted so that insert mode starts on that line. -testVim('cw', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('c', '2', 'w'); - eq(' word3', cm.getValue()); - helpers.assertCursorAt(0, 0); -}, { value: 'word1 word2 word3'}); -testVim('cw_repeat', function(cm, vim, helpers) { - // Assert that cw does delete newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('c', '2', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: ' word1\nword2' }); -testVim('cc_multiply_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount() - 5; - helpers.doKeys('2', 'c', '3', 'c'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('cc_append', function(cm, vim, helpers) { - var expectedLineCount = cm.lineCount(); - cm.setCursor(cm.lastLine(), 0); - helpers.doKeys('c', 'c'); - eq(expectedLineCount, cm.lineCount()); -}); -testVim('c_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'c'); - var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); - replacement.pop(); - cm.replaceSelections(replacement); - eq('1hello\n5hello\nahellofg', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(2, 3); - helpers.doKeys('', '2', 'k', 'h', 'C'); - replacement = new Array(cm.listSelections().length+1).join('world ').split(' '); - replacement.pop(); - cm.replaceSelections(replacement); - eq('1hworld\n5hworld\nahworld', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('c_visual_block_replay', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'c'); - var replacement = new Array(cm.listSelections().length+1).join('fo ').split(' '); - replacement.pop(); - cm.replaceSelections(replacement); - eq('1fo4\n5fo8\nafodefg', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(0, 0); - helpers.doKeys('.'); - eq('foo4\nfoo8\nfoodefg', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); - -// Swapcase commands edit in place and do not modify registers. -testVim('g~w_repeat', function(cm, vim, helpers) { - // Assert that dw does delete newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('g', '~', '2', 'w'); - eq(' WORD1\nWORD2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2' }); -testVim('g~g~', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - var expectedLineCount = cm.lineCount(); - var expectedValue = cm.getValue().toUpperCase(); - helpers.doKeys('2', 'g', '~', '3', 'g', '~'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - eqPos({line: curStart.line, ch:0}, cm.getCursor()); -}, { value: ' word1\nword2\nword3\nword4\nword5\nword6' }); -testVim('gu_and_gU', function(cm, vim, helpers) { - var curStart = makeCursor(0, 7); - var value = cm.getValue(); - cm.setCursor(curStart); - helpers.doKeys('2', 'g', 'U', 'w'); - eq(cm.getValue(), 'wa wb xX WC wd'); - eqPos(curStart, cm.getCursor()); - helpers.doKeys('2', 'g', 'u', 'w'); - eq(cm.getValue(), value); - - helpers.doKeys('2', 'g', 'U', 'B'); - eq(cm.getValue(), 'wa WB Xx wc wd'); - eqPos(makeCursor(0, 3), cm.getCursor()); - - cm.setCursor(makeCursor(0, 4)); - helpers.doKeys('g', 'u', 'i', 'w'); - eq(cm.getValue(), 'wa wb Xx wc wd'); - eqPos(makeCursor(0, 3), cm.getCursor()); - - // TODO: support gUgU guu - // eqPos(makeCursor(0, 0), cm.getCursor()); - - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); -}, { value: 'wa wb xx wc wd' }); -testVim('visual_block_~', function(cm, vim, helpers) { - cm.setCursor(1, 1); - helpers.doKeys('', 'l', 'l', 'j', '~'); - helpers.assertCursorAt(1, 1); - eq('hello\nwoRLd\naBCDe', cm.getValue()); - cm.setCursor(2, 0); - helpers.doKeys('v', 'l', 'l', '~'); - helpers.assertCursorAt(2, 0); - eq('hello\nwoRLd\nAbcDe', cm.getValue()); -},{value: 'hello\nwOrld\nabcde' }); -testVim('._swapCase_visualBlock', function(cm, vim, helpers) { - helpers.doKeys('', 'j', 'j', 'l', '~'); - cm.setCursor(0, 3); - helpers.doKeys('.'); - eq('HelLO\nWorLd\nAbcdE', cm.getValue()); -},{value: 'hEllo\nwOrlD\naBcDe' }); -testVim('._delete_visualBlock', function(cm, vim, helpers) { - helpers.doKeys('', 'j', 'x'); - eq('ive\ne\nsome\nsugar', cm.getValue()); - helpers.doKeys('.'); - eq('ve\n\nsome\nsugar', cm.getValue()); - helpers.doKeys('j', 'j', '.'); - eq('ve\n\nome\nugar', cm.getValue()); - helpers.doKeys('u', '', '.'); - eq('ve\n\nme\ngar', cm.getValue()); -},{value: 'give\nme\nsome\nsugar' }); -testVim('>{motion}', function(cm, vim, helpers) { - cm.setCursor(1, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\n word2\nword3 '; - helpers.doKeys('>', 'k'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); -testVim('>>', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\n word2\nword3 '; - helpers.doKeys('2', '>', '>'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); -testVim('<{motion}', function(cm, vim, helpers) { - cm.setCursor(1, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\nword2\nword3 '; - helpers.doKeys('<', 'k'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); -testVim('<<', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\nword2\nword3 '; - helpers.doKeys('2', '<', '<'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); - -// Edit tests -function testEdit(name, before, pos, edit, after) { - return testVim(name, function(cm, vim, helpers) { - var ch = before.search(pos) - var line = before.substring(0, ch).split('\n').length - 1; - if (line) { - ch = before.substring(0, ch).split('\n').pop().length; - } - cm.setCursor(line, ch); - helpers.doKeys.apply(this, edit.split('')); - eq(after, cm.getValue()); - }, {value: before}); -} - -// These Delete tests effectively cover word-wise Change, Visual & Yank. -// Tabs are used as differentiated whitespace to catch edge cases. -// Normal word: -testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz'); -testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz'); -testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz'); -testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz'); -testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz'); -testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz'); -testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz'); -testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz'); -testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz'); -testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz'); -testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t'); -testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo'); -testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.'); -testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.'); -// Big word: -testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz'); -testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz'); -testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz'); -testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz'); -testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t'); -testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo'); -testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t'); -testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo'); -// Deleting text objects -// Open and close on same line -testEdit('di(_open_spc', 'foo (bAr) baz', /\(/, 'di(', 'foo () baz'); -testEdit('di)_open_spc', 'foo (bAr) baz', /\(/, 'di)', 'foo () baz'); -testEdit('dib_open_spc', 'foo (bAr) baz', /\(/, 'dib', 'foo () baz'); -testEdit('da(_open_spc', 'foo (bAr) baz', /\(/, 'da(', 'foo baz'); -testEdit('da)_open_spc', 'foo (bAr) baz', /\(/, 'da)', 'foo baz'); - -testEdit('di(_middle_spc', 'foo (bAr) baz', /A/, 'di(', 'foo () baz'); -testEdit('di)_middle_spc', 'foo (bAr) baz', /A/, 'di)', 'foo () baz'); -testEdit('da(_middle_spc', 'foo (bAr) baz', /A/, 'da(', 'foo baz'); -testEdit('da)_middle_spc', 'foo (bAr) baz', /A/, 'da)', 'foo baz'); - -testEdit('di(_close_spc', 'foo (bAr) baz', /\)/, 'di(', 'foo () baz'); -testEdit('di)_close_spc', 'foo (bAr) baz', /\)/, 'di)', 'foo () baz'); -testEdit('da(_close_spc', 'foo (bAr) baz', /\)/, 'da(', 'foo baz'); -testEdit('da)_close_spc', 'foo (bAr) baz', /\)/, 'da)', 'foo baz'); - -// delete around and inner b. -testEdit('dab_on_(_should_delete_around_()block', 'o( in(abc) )', /\(a/, 'dab', 'o( in )'); - -// delete around and inner B. -testEdit('daB_on_{_should_delete_around_{}block', 'o{ in{abc} }', /{a/, 'daB', 'o{ in }'); -testEdit('diB_on_{_should_delete_inner_{}block', 'o{ in{abc} }', /{a/, 'diB', 'o{ in{} }'); - -testEdit('da{_on_{_should_delete_inner_block', 'o{ in{abc} }', /{a/, 'da{', 'o{ in }'); -testEdit('di[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'di[', 'foo (bAr) baz'); -testEdit('di[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'di[', 'foo (bAr) baz'); -testEdit('da[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'da[', 'foo (bAr) baz'); -testEdit('da[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'da[', 'foo (bAr) baz'); -testMotion('di(_outside_should_stay', ['d', 'i', '('], { line: 0, ch: 0}, { line: 0, ch: 0}); - -// Open and close on different lines, equally indented -testEdit('di{_middle_spc', 'a{\n\tbar\n}b', /r/, 'di{', 'a{}b'); -testEdit('di}_middle_spc', 'a{\n\tbar\n}b', /r/, 'di}', 'a{}b'); -testEdit('da{_middle_spc', 'a{\n\tbar\n}b', /r/, 'da{', 'ab'); -testEdit('da}_middle_spc', 'a{\n\tbar\n}b', /r/, 'da}', 'ab'); -testEdit('daB_middle_spc', 'a{\n\tbar\n}b', /r/, 'daB', 'ab'); - -// open and close on diff lines, open indented less than close -testEdit('di{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di{', 'a{}b'); -testEdit('di}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di}', 'a{}b'); -testEdit('da{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da{', 'ab'); -testEdit('da}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da}', 'ab'); - -// open and close on diff lines, open indented more than close -testEdit('di[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di[', 'a\t[]b'); -testEdit('di]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di]', 'a\t[]b'); -testEdit('da[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da[', 'a\tb'); -testEdit('da]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da]', 'a\tb'); - -function testSelection(name, before, pos, keys, sel) { - return testVim(name, function(cm, vim, helpers) { - var ch = before.search(pos) - var line = before.substring(0, ch).split('\n').length - 1; - if (line) { - ch = before.substring(0, ch).split('\n').pop().length; - } - cm.setCursor(line, ch); - helpers.doKeys.apply(this, keys.split('')); - eq(sel, cm.getSelection()); - }, {value: before}); -} -testSelection('viw_middle_spc', 'foo \tbAr\t baz', /A/, 'viw', 'bAr'); -testSelection('vaw_middle_spc', 'foo \tbAr\t baz', /A/, 'vaw', 'bAr\t '); -testSelection('viw_middle_punct', 'foo \tbAr,\t baz', /A/, 'viw', 'bAr'); -testSelection('vaW_middle_punct', 'foo \tbAr,\t baz', /A/, 'vaW', 'bAr,\t '); -testSelection('viw_start_spc', 'foo \tbAr\t baz', /b/, 'viw', 'bAr'); -testSelection('viw_end_spc', 'foo \tbAr\t baz', /r/, 'viw', 'bAr'); -testSelection('viw_eol', 'foo \tbAr', /r/, 'viw', 'bAr'); -testSelection('vi{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'vi{', '\n\tbar\n\t'); -testSelection('va{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'va{', '{\n\tbar\n\t}'); - -testVim('mouse_select', function(cm, vim, helpers) { - cm.setSelection(Pos(0, 2), Pos(0, 4), {origin: '*mouse'}); - is(cm.state.vim.visualMode); - is(!cm.state.vim.visualLine); - is(!cm.state.vim.visualBlock); - helpers.doKeys(''); - is(!cm.somethingSelected()); - helpers.doKeys('g', 'v'); - eq('cd', cm.getSelection()); -}, {value: 'abcdef'}); - -// Operator-motion tests -testVim('D', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('D'); - eq(' wo\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\n word3' }); -testVim('C', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('C'); - eq(' wo\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: ' word1\nword2\n word3' }); -testVim('Y', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('Y'); - eq(' word1\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\n word3' }); -testVim('~', function(cm, vim, helpers) { - helpers.doKeys('3', '~'); - eq('ABCdefg', cm.getValue()); - helpers.assertCursorAt(0, 3); -}, { value: 'abcdefg' }); - -// Action tests -testVim('ctrl-a', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(''); - eq('-9', cm.getValue()); - helpers.assertCursorAt(0, 1); - helpers.doKeys('2',''); - eq('-7', cm.getValue()); -}, {value: '-10'}); -testVim('ctrl-x', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(''); - eq('-1', cm.getValue()); - helpers.assertCursorAt(0, 1); - helpers.doKeys('2',''); - eq('-3', cm.getValue()); -}, {value: '0'}); -testVim('/ search forward', function(cm, vim, helpers) { - forEach(['', ''], function(key) { - cm.setCursor(0, 0); - helpers.doKeys(key); - helpers.assertCursorAt(0, 5); - helpers.doKeys('l'); - helpers.doKeys(key); - helpers.assertCursorAt(0, 10); - cm.setCursor(0, 11); - helpers.doKeys(key); - helpers.assertCursorAt(0, 11); - }); -}, {value: '__jmp1 jmp2 jmp'}); -testVim('a', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('a'); - helpers.assertCursorAt(0, 2); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('a_eol', function(cm, vim, helpers) { - cm.setCursor(0, lines[0].length - 1); - helpers.doKeys('a'); - helpers.assertCursorAt(0, lines[0].length); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('a_endOfSelectedArea', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'j', 'l'); - helpers.doKeys('A'); - helpers.assertCursorAt(1, 2); - eq('vim-insert', cm.getOption('keyMap')); -}, {value: 'foo\nbar'}); -testVim('i', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('i'); - helpers.assertCursorAt(0, 1); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('i_repeat', function(cm, vim, helpers) { - helpers.doKeys('3', 'i'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('testtesttest', cm.getValue()); - helpers.assertCursorAt(0, 11); -}, { value: '' }); -testVim('i_repeat_delete', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('2', 'i'); - cm.replaceRange('z', cm.getCursor()); - helpers.doInsertModeKeys('Backspace', 'Backspace'); - helpers.doKeys(''); - eq('abe', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'abcde' }); -testVim('A', function(cm, vim, helpers) { - helpers.doKeys('A'); - helpers.assertCursorAt(0, lines[0].length); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('A_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'A'); - var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); - replacement.pop(); - cm.replaceSelections(replacement); - eq('testhello\nmehello\npleahellose', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(0, 0); - helpers.doKeys('.'); - // TODO this doesn't work yet - // eq('teshellothello\nme hello hello\nplehelloahellose', cm.getValue()); -}, {value: 'test\nme\nplease'}); -testVim('I', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('I'); - helpers.assertCursorAt(0, lines[0].textStart); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('I_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('3', 'I'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('testtesttestblah', cm.getValue()); - helpers.assertCursorAt(0, 11); -}, { value: 'blah' }); -testVim('I_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'l', 'l', 'I'); - var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); - replacement.pop(); - cm.replaceSelections(replacement); - eq('hellotest\nhellome\nhelloplease', cm.getValue()); -}, {value: 'test\nme\nplease'}); -testVim('o', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('o'); - eq('word1\n\nword2', cm.getValue()); - helpers.assertCursorAt(1, 0); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'word1\nword2' }); -testVim('o_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('3', 'o'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('\ntest\ntest\ntest', cm.getValue()); - helpers.assertCursorAt(3, 3); -}, { value: '' }); -testVim('O', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('O'); - eq('\nword1\nword2', cm.getValue()); - helpers.assertCursorAt(0, 0); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'word1\nword2' }); -testVim('J', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('J'); - var expectedValue = 'word1 word2\nword3\n word4'; - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1); -}, { value: 'word1 \n word2\nword3\n word4' }); -testVim('J_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('3', 'J'); - var expectedValue = 'word1 word2 word3\n word4'; - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1); -}, { value: 'word1 \n word2\nword3\n word4' }); -testVim('p', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); - helpers.doKeys('p'); - eq('__abc\ndef_', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_register', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); - helpers.doKeys('"', 'a', 'p'); - eq('__abc\ndef_', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_wrong_register', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); - helpers.doKeys('p'); - eq('___', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: '___' }); -testVim('p_line', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); - helpers.doKeys('2', 'p'); - eq('___\n a\nd\n a\nd', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_lastline', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd', true); - helpers.doKeys('2', 'p'); - eq('___\n a\nd\n a\nd', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim(']p_first_indent_is_smaller', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq(' ___\n abc\n def', cm.getValue()); -}, { value: ' ___' }); -testVim(']p_first_indent_is_larger', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq(' ___\n abc\ndef', cm.getValue()); -}, { value: ' ___' }); -testVim(']p_with_tab_indents', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', '\t\tabc\n\t\t\tdef\n', true); - helpers.doKeys(']', 'p'); - eq('\t___\n\tabc\n\t\tdef', cm.getValue()); -}, { value: '\t___', indentWithTabs: true}); -testVim(']p_with_spaces_translated_to_tabs', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq('\t___\n\tabc\n\t\tdef', cm.getValue()); -}, { value: '\t___', indentWithTabs: true, tabSize: 2 }); -testVim('[p', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys('[', 'p'); - eq(' abc\n def\n ___', cm.getValue()); -}, { value: ' ___' }); -testVim('P', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); - helpers.doKeys('P'); - eq('_abc\ndef__', cm.getValue()); - helpers.assertCursorAt(1, 3); -}, { value: '___' }); -testVim('P_line', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); - helpers.doKeys('2', 'P'); - eq(' a\nd\n a\nd\n___', cm.getValue()); - helpers.assertCursorAt(0, 2); -}, { value: '___' }); -testVim('r', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('3', 'r', 'u'); - eq('wuuuet\nanother', cm.getValue(),'3r failed'); - helpers.assertCursorAt(0, 3); - cm.setCursor(0, 4); - helpers.doKeys('v', 'j', 'h', 'r', ''); - eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed'); -}, { value: 'wordet\nanother' }); -testVim('r_visual_block', function(cm, vim, helpers) { - cm.setCursor(2, 3); - helpers.doKeys('', 'k', 'k', 'h', 'h', 'r', 'l'); - eq('1lll\n5lll\nalllefg', cm.getValue()); - helpers.doKeys('', 'l', 'j', 'r', ''); - eq('1 l\n5 l\nalllefg', cm.getValue()); - cm.setCursor(2, 0); - helpers.doKeys('o'); - helpers.doKeys(''); - cm.replaceRange('\t\t', cm.getCursor()); - helpers.doKeys('', 'h', 'h', 'r', 'r'); - eq('1 l\n5 l\nalllefg\nrrrrrrrr', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('R', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('R'); - helpers.assertCursorAt(0, 1); - eq('vim-replace', cm.getOption('keyMap')); - is(cm.state.overwrite, 'Setting overwrite state failed'); -}); -testVim('mark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('`', 't'); - helpers.assertCursorAt(2, 2); - cm.setCursor(2, 0); - cm.replaceRange(' h', cm.getCursor()); - cm.setCursor(0, 0); - helpers.doKeys('\'', 't'); - helpers.assertCursorAt(2, 3); -}); -testVim('jumpToMark_next', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 2); - cm.setCursor(0, 0); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_next_repeat', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(0, 0); - helpers.doKeys('2', ']', '`'); - helpers.assertCursorAt(3, 2); - cm.setCursor(0, 0); - helpers.doKeys('2', ']', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_next_sameline', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 2); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 4); -}); -testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(4, 0); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(4, 0); -}); -testVim('jumpToMark_next_nomark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 2); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 1); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_next_action', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('d', ']', '`'); - helpers.assertCursorAt(0, 0); - var actual = cm.getLine(0); - var expected = 'pop pop 0 1 2 3 4'; - eq(actual, expected, "Deleting while jumping to the next mark failed."); -}); -testVim('jumpToMark_next_line_action', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('d', ']', '\''); - helpers.assertCursorAt(0, 1); - var actual = cm.getLine(0); - var expected = ' (a) [b] {c} ' - eq(actual, expected, "Deleting while jumping to the next mark line failed."); -}); -testVim('jumpToMark_prev', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(4, 0); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 2); - cm.setCursor(4, 0); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(5, 0); - helpers.doKeys('2', '[', '`'); - helpers.assertCursorAt(3, 2); - cm.setCursor(5, 0); - helpers.doKeys('2', '[', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 2); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) { - cm.setCursor(4, 4); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 0); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 2); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 6); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('delmark_single', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 't'); - helpers.doEx('delmarks t'); - cm.setCursor(0, 0); - helpers.doKeys('`', 't'); - helpers.assertCursorAt(0, 0); -}); -testVim('delmark_range', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks b-d'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_multi', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks bcd'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_multi_space', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks b c d'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_all', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks a b-de'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(0, 0); -}); -testVim('visual', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l'); - helpers.assertCursorAt(0, 4); - eqPos(makeCursor(0, 1), cm.getCursor('anchor')); - helpers.doKeys('d'); - eq('15', cm.getValue()); -}, { value: '12345' }); -testVim('visual_exit', function(cm, vim, helpers) { - helpers.doKeys('', 'l', 'j', 'j', ''); - eqPos(cm.getCursor('anchor'), cm.getCursor('head')); - eq(vim.visualMode, false); -}, { value: 'hello\nworld\nfoo' }); -testVim('visual_line', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd'); - eq(' 4\n 5', cm.getValue()); -}, { value: ' 1\n 2\n 3\n 4\n 5' }); -testVim('visual_block', function(cm, vim, helpers) { - // test the block selection with lines of different length - // i.e. extending the selection - // till the end of the longest line. - helpers.doKeys('', 'l', 'j', 'j', '6', 'l', 'd'); - helpers.doKeys('d', 'd', 'd', 'd'); - eq('', cm.getValue()); - // check for left side selection in case - // of moving up to a shorter line. - cm.replaceRange('hello world\n{\nthis is\nsparta!', cm.getCursor()); - cm.setCursor(3, 4); - helpers.doKeys('', 'l', 'k', 'k', 'd'); - eq('hello world\n{\ntis\nsa!', cm.getValue()); - cm.replaceRange('12345\n67891\nabcde', {line: 0, ch: 0}, {line: cm.lastLine(), ch: 6}); - cm.setCursor(1, 2); - helpers.doKeys('', '2', 'l', 'k'); - // circle around the anchor - // and check the selections - var selections = cm.getSelections(); - eq('345891', selections.join('')); - helpers.doKeys('4', 'h'); - selections = cm.getSelections(); - eq('123678', selections.join('')); - helpers.doKeys('j', 'j'); - selections = cm.getSelections(); - eq('678abc', selections.join('')); - helpers.doKeys('4', 'l'); - selections = cm.getSelections(); - eq('891cde', selections.join('')); - // switch between visual modes - cm.setCursor(1, 1); - // blockwise to characterwise visual - helpers.doKeys('', 'j', 'l', 'v'); - selections = cm.getSelections(); - eq('7891\nabc', selections.join('')); - // characterwise to blockwise - helpers.doKeys(''); - selections = cm.getSelections(); - eq('78bc', selections.join('')); - // blockwise to linewise visual - helpers.doKeys('V'); - selections = cm.getSelections(); - eq('67891\nabcde', selections.join('')); -}, {value: '1234\n5678\nabcdefg'}); -testVim('visual_block_crossing_short_line', function(cm, vim, helpers) { - // visual block with long and short lines - cm.setCursor(0, 3); - helpers.doKeys('', 'j', 'j', 'j'); - var selections = cm.getSelections().join(); - eq('4,,d,b', selections); - helpers.doKeys('3', 'k'); - selections = cm.getSelections().join(); - eq('4', selections); - helpers.doKeys('5', 'j', 'k'); - selections = cm.getSelections().join(""); - eq(10, selections.length); -}, {value: '123456\n78\nabcdefg\nfoobar\n}\n'}); -testVim('visual_block_curPos_on_exit', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '3' , 'l', ''); - eqPos(makeCursor(0, 3), cm.getCursor()); - helpers.doKeys('h', '', '2' , 'j' ,'3' , 'l'); - eq(cm.getSelections().join(), "3456,,cdef"); - helpers.doKeys('4' , 'h'); - eq(cm.getSelections().join(), "23,8,bc"); - helpers.doKeys('2' , 'l'); - eq(cm.getSelections().join(), "34,,cd"); -}, {value: '123456\n78\nabcdefg\nfoobar'}); - -testVim('visual_marks', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l', 'j', 'j', 'v'); - // Test visual mode marks - cm.setCursor(2, 1); - helpers.doKeys('\'', '<'); - helpers.assertCursorAt(0, 1); - helpers.doKeys('\'', '>'); - helpers.assertCursorAt(2, 0); -}); -testVim('visual_join', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J'); - eq(' 1 2 3\n 4\n 5', cm.getValue()); - is(!vim.visualMode); -}, { value: ' 1\n 2\n 3\n 4\n 5' }); -testVim('visual_blank', function(cm, vim, helpers) { - helpers.doKeys('v', 'k'); - eq(vim.visualMode, true); -}, { value: '\n' }); -testVim('reselect_visual', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l', 'l', 'y', 'g', 'v'); - helpers.assertCursorAt(0, 5); - eqPos(makeCursor(0, 1), cm.getCursor('anchor')); - helpers.doKeys('v'); - cm.setCursor(1, 0); - helpers.doKeys('v', 'l', 'l', 'p'); - eq('123456\n2345\nbar', cm.getValue()); - cm.setCursor(0, 0); - helpers.doKeys('g', 'v'); - // here the fake cursor is at (1, 3) - helpers.assertCursorAt(1, 4); - eqPos(makeCursor(1, 0), cm.getCursor('anchor')); - helpers.doKeys('v'); - cm.setCursor(2, 0); - helpers.doKeys('v', 'l', 'l', 'g', 'v'); - helpers.assertCursorAt(1, 4); - eqPos(makeCursor(1, 0), cm.getCursor('anchor')); - helpers.doKeys('g', 'v'); - helpers.assertCursorAt(2, 3); - eqPos(makeCursor(2, 0), cm.getCursor('anchor')); - eq('123456\n2345\nbar', cm.getValue()); -}, { value: '123456\nfoo\nbar' }); -testVim('reselect_visual_line', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'j', 'j', 'V', 'g', 'v', 'd'); - eq('foo\nand\nbar', cm.getValue()); - cm.setCursor(1, 0); - helpers.doKeys('V', 'y', 'j'); - helpers.doKeys('V', 'p' , 'g', 'v', 'd'); - eq('foo\nand', cm.getValue()); -}, { value: 'hello\nthis\nis\nfoo\nand\nbar' }); -testVim('reselect_visual_block', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('', 'k', 'h', ''); - cm.setCursor(2, 1); - helpers.doKeys('v', 'l', 'g', 'v'); - helpers.assertCursorAt(0, 1); - // Ensure selection is done with visual block mode rather than one - // continuous range. - eq(cm.getSelections().join(''), '23oo') - helpers.doKeys('g', 'v'); - helpers.assertCursorAt(2, 3); - // Ensure selection of deleted range - cm.setCursor(1, 1); - helpers.doKeys('v', '', 'j', 'd', 'g', 'v'); - eq(cm.getSelections().join(''), 'or'); -}, { value: '123456\nfoo\nbar' }); -testVim('s_normal', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('s'); - helpers.doKeys(''); - eq('ac', cm.getValue()); -}, { value: 'abc'}); -testVim('s_visual', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v', 's'); - helpers.doKeys(''); - helpers.assertCursorAt(0, 0); - eq('ac', cm.getValue()); -}, { value: 'abc'}); -testVim('o_visual', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys('v','l','l','l','o'); - helpers.assertCursorAt(0,0); - helpers.doKeys('v','v','j','j','j','o'); - helpers.assertCursorAt(0,0); - helpers.doKeys('O'); - helpers.doKeys('l','l') - helpers.assertCursorAt(3, 3); - helpers.doKeys('d'); - eq('p',cm.getValue()); -}, { value: 'abcd\nefgh\nijkl\nmnop'}); -testVim('o_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('','3','j','l','l', 'o'); - helpers.assertCursorAt(0, 1); - helpers.doKeys('O'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('o'); - helpers.assertCursorAt(3, 1); -}, { value: 'abcd\nefgh\nijkl\nmnop'}); -testVim('changeCase_visual', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'l', 'l'); - helpers.doKeys('U'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('v', 'l', 'l'); - helpers.doKeys('u'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('l', 'l', 'l', '.'); - helpers.assertCursorAt(0, 3); - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'v', 'j', 'U', 'q'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('j', '@', 'a'); - helpers.assertCursorAt(1, 0); - cm.setCursor(3, 0); - helpers.doKeys('V', 'U', 'j', '.'); - eq('ABCDEF\nGHIJKL\nMnopq\nSHORT LINE\nLONG LINE OF TEXT', cm.getValue()); -}, { value: 'abcdef\nghijkl\nmnopq\nshort line\nlong line of text'}); -testVim('changeCase_visual_block', function(cm, vim, helpers) { - cm.setCursor(2, 1); - helpers.doKeys('', 'k', 'k', 'h', 'U'); - eq('ABcdef\nGHijkl\nMNopq\nfoo', cm.getValue()); - cm.setCursor(0, 2); - helpers.doKeys('.'); - eq('ABCDef\nGHIJkl\nMNOPq\nfoo', cm.getValue()); - // check when last line is shorter. - cm.setCursor(2, 2); - helpers.doKeys('.'); - eq('ABCDef\nGHIJkl\nMNOPq\nfoO', cm.getValue()); -}, { value: 'abcdef\nghijkl\nmnopq\nfoo'}); -testVim('visual_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'l', 'l', 'y', 'j', 'v', 'l', 'p'); - helpers.assertCursorAt(1, 5); - eq('this is a\nunithitest for visual paste', cm.getValue()); - cm.setCursor(0, 0); - // in case of pasting whole line - helpers.doKeys('y', 'y'); - cm.setCursor(1, 6); - helpers.doKeys('v', 'l', 'l', 'l', 'p'); - helpers.assertCursorAt(2, 0); - eq('this is a\nunithi\nthis is a\n for visual paste', cm.getValue()); -}, { value: 'this is a\nunit test for visual paste'}); - -// This checks the contents of the register used to paste the text -testVim('v_paste_from_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - cm.setCursor(1, 0); - helpers.doKeys('v', 'p'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+register/.test(text)); - }); -}, { value: 'register contents\nare not erased'}); -testVim('S_normal', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('j', 'S'); - helpers.doKeys(''); - helpers.assertCursorAt(1, 0); - eq('aa\n\ncc', cm.getValue()); -}, { value: 'aa\nbb\ncc'}); -testVim('blockwise_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '3', 'j', 'l', 'y'); - cm.setCursor(0, 2); - // paste one char after the current cursor position - helpers.doKeys('p'); - eq('helhelo\nworwold\nfoofo\nbarba', cm.getValue()); - cm.setCursor(0, 0); - helpers.doKeys('v', '4', 'l', 'y'); - cm.setCursor(0, 0); - helpers.doKeys('', '3', 'j', 'p'); - eq('helheelhelo\norwold\noofo\narba', cm.getValue()); -}, { value: 'hello\nworld\nfoo\nbar'}); -testVim('blockwise_paste_long/short_line', function(cm, vim, helpers) { - // extend short lines in case of different line lengths. - cm.setCursor(0, 0); - helpers.doKeys('', 'j', 'j', 'y'); - cm.setCursor(0, 3); - helpers.doKeys('p'); - eq('hellho\nfoo f\nbar b', cm.getValue()); -}, { value: 'hello\nfoo\nbar'}); -testVim('blockwise_paste_cut_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'x'); - cm.setCursor(0, 0); - helpers.doKeys('P'); - eq('cut\nand\npaste\nme', cm.getValue()); -}, { value: 'cut\nand\npaste\nme'}); -testVim('blockwise_paste_from_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', '"', 'a', 'y'); - cm.setCursor(0, 3); - helpers.doKeys('"', 'a', 'p'); - eq('foobfar\nhellho\nworlwd', cm.getValue()); -}, { value: 'foobar\nhello\nworld'}); -testVim('blockwise_paste_last_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'l', 'y'); - cm.setCursor(3, 0); - helpers.doKeys('p'); - eq('cut\nand\npaste\nmcue\n an\n pa', cm.getValue()); -}, { value: 'cut\nand\npaste\nme'}); - -testVim('S_visual', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v', 'j', 'S'); - helpers.doKeys(''); - helpers.assertCursorAt(0, 0); - eq('\ncc', cm.getValue()); -}, { value: 'aa\nbb\ncc'}); - -testVim('/ and n/N', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 11); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 6); - helpers.doKeys('N'); - helpers.assertCursorAt(0, 11); - - cm.setCursor(0, 0); - helpers.doKeys('2', '/'); - helpers.assertCursorAt(1, 6); -}, { value: 'match nope match \n nope Match' }); -testVim('/_case', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('Match'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 6); -}, { value: 'match nope match \n nope Match' }); -testVim('/_2_pcre', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', true); - cm.openDialog = helpers.fakeOpenDialog('(word){2}'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 9); - helpers.doKeys('n'); - helpers.assertCursorAt(2, 1); -}, { value: 'word\n another wordword\n wordwordword\n' }); -testVim('/_2_nopcre', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', false); - cm.openDialog = helpers.fakeOpenDialog('\\(word\\)\\{2}'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 9); - helpers.doKeys('n'); - helpers.assertCursorAt(2, 1); -}, { value: 'word\n another wordword\n wordwordword\n' }); -testVim('/_nongreedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('aa'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('?_nongreedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('aa'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('/_greedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a+'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('?_greedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a+'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('/_greedy_0_or_more', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a*'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 5); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 0); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa\n aa'}); -testVim('?_greedy_0_or_more', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a*'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 0); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 5); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa\n aa'}); -testVim('? and n/N', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 6); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 11); - helpers.doKeys('N'); - helpers.assertCursorAt(1, 6); - - cm.setCursor(0, 0); - helpers.doKeys('2', '?'); - helpers.assertCursorAt(0, 11); -}, { value: 'match nope match \n nope Match' }); -testVim('*', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 22); - - cm.setCursor(0, 9); - helpers.doKeys('2', '*'); - helpers.assertCursorAt(1, 8); -}, { value: 'nomatch match nomatch match \nnomatch Match' }); -testVim('*_no_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 0); -}, { value: ' \n match \n' }); -testVim('*_symbol', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('*'); - helpers.assertCursorAt(1, 0); -}, { value: ' /}\n/} match \n' }); -testVim('#', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('#'); - helpers.assertCursorAt(1, 8); - - cm.setCursor(0, 9); - helpers.doKeys('2', '#'); - helpers.assertCursorAt(0, 22); -}, { value: 'nomatch match nomatch match \nnomatch Match' }); -testVim('*_seek', function(cm, vim, helpers) { - // Should skip over space and symbols. - cm.setCursor(0, 3); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 22); -}, { value: ' := match nomatch match \nnomatch Match' }); -testVim('#', function(cm, vim, helpers) { - // Should skip over space and symbols. - cm.setCursor(0, 3); - helpers.doKeys('#'); - helpers.assertCursorAt(1, 8); -}, { value: ' := match nomatch match \nnomatch Match' }); -testVim('g*', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('g', '*'); - helpers.assertCursorAt(0, 18); - cm.setCursor(0, 8); - helpers.doKeys('3', 'g', '*'); - helpers.assertCursorAt(1, 8); -}, { value: 'matches match alsoMatch\nmatchme matching' }); -testVim('g#', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('g', '#'); - helpers.assertCursorAt(0, 0); - cm.setCursor(0, 8); - helpers.doKeys('3', 'g', '#'); - helpers.assertCursorAt(1, 0); -}, { value: 'matches match alsoMatch\nmatchme matching' }); -testVim('macro_insert', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '0', 'i'); - cm.replaceRange('foo', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q', '@', 'a'); - eq('foofoo', cm.getValue()); -}, { value: ''}); -testVim('macro_insert_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '$', 'a'); - cm.replaceRange('larry.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('a'); - cm.replaceRange('curly.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('a'); - cm.replaceRange('moe.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('@', 'a'); - // At this point, the most recent edit should be the 2nd insert change - // inside the macro, i.e. "curly.". - helpers.doKeys('.'); - eq('larry.curly.moe.larry.curly.curly.', cm.getValue()); -}, { value: ''}); -testVim('macro_space', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', ''); - helpers.assertCursorAt(0, 2); - helpers.doKeys('q', 'a', '', '', 'q'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0, 6); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0, 8); -}, { value: 'one line of text.'}); -testVim('macro_t_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 't', 'e', 'q'); - helpers.assertCursorAt(0, 1); - helpers.doKeys('l', '@', 'a'); - helpers.assertCursorAt(0, 6); - helpers.doKeys('l', ';'); - helpers.assertCursorAt(0, 12); -}, { value: 'one line of text.'}); -testVim('macro_f_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'b', 'f', 'e', 'q'); - helpers.assertCursorAt(0, 2); - helpers.doKeys('@', 'b'); - helpers.assertCursorAt(0, 7); - helpers.doKeys(';'); - helpers.assertCursorAt(0, 13); -}, { value: 'one line of text.'}); -testVim('macro_slash_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'c'); - cm.openDialog = helpers.fakeOpenDialog('e'); - helpers.doKeys('/', 'q'); - helpers.assertCursorAt(0, 2); - helpers.doKeys('@', 'c'); - helpers.assertCursorAt(0, 7); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 13); -}, { value: 'one line of text.'}); -testVim('macro_multislash_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'd'); - cm.openDialog = helpers.fakeOpenDialog('e'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('t'); - helpers.doKeys('/', 'q'); - helpers.assertCursorAt(0, 12); - helpers.doKeys('@', 'd'); - helpers.assertCursorAt(0, 15); -}, { value: 'one line of text to rule them all.'}); -testVim('macro_parens', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'z', 'i'); - cm.replaceRange('(', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('e', 'a'); - cm.replaceRange(')', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('w', '@', 'z'); - helpers.doKeys('w', '@', 'z'); - eq('(see) (spot) (run)', cm.getValue()); -}, { value: 'see spot run'}); -testVim('macro_overwrite', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'z', '0', 'i'); - cm.replaceRange('I ', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('e'); - // Now replace the macro with something else. - helpers.doKeys('q', 'z', 'a'); - cm.replaceRange('.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('e', '@', 'z'); - helpers.doKeys('e', '@', 'z'); - eq('I see. spot. run.', cm.getValue()); -}, { value: 'see spot run'}); -testVim('macro_search_f', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'f', ' '); - helpers.assertCursorAt(0,3); - helpers.doKeys('q', '0'); - helpers.assertCursorAt(0,0); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0,3); -}, { value: 'The quick brown fox jumped over the lazy dog.'}); -testVim('macro_search_2f', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '2', 'f', ' '); - helpers.assertCursorAt(0,9); - helpers.doKeys('q', '0'); - helpers.assertCursorAt(0,0); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0,9); -}, { value: 'The quick brown fox jumped over the lazy dog.'}); -testVim('yank_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'b', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo/.test(text)); - is(/b\s+bar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', 'l', 'j', '"', 'a', 'y'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+oo\nar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_line_to_line_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'A', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_word_to_word_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - helpers.doKeys('j', '"', 'A', 'y', 'w'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foobar/.test(text)); - is(/"\s+foobar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_line_to_word_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - helpers.doKeys('j', '"', 'A', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_word_to_line_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'A', 'y', 'w'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('macro_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'i'); - cm.replaceRange('gangnam', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('q', 'b', 'o'); - cm.replaceRange('style', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+i/.test(text)); - is(/b\s+o/.test(text)); - }); - helpers.doKeys(':'); -}, { value: ''}); -testVim('._register', function(cm,vim,helpers) { - cm.setCursor(0,0); - helpers.doKeys('i'); - cm.replaceRange('foo',cm.getCursor()); - helpers.doKeys(''); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/\.\s+foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim(':_register', function(cm,vim,helpers) { - helpers.doEx('bar'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/:\s+bar/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_register_escape', function(cm, vim, helpers) { - // Check that the register is restored if the user escapes rather than confirms. - cm.openDialog = helpers.fakeOpenDialog('waldo'); - helpers.doKeys('/'); - var onKeyDown; - var onKeyUp; - var KEYCODES = { - f: 70, - o: 79, - Esc: 27 - }; - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - onKeyUp = options.onKeyUp; - }; - var close = function() {}; - helpers.doKeys('/'); - // Fake some keyboard events coming in. - onKeyDown({keyCode: KEYCODES.f}, '', close); - onKeyUp({keyCode: KEYCODES.f}, '', close); - onKeyDown({keyCode: KEYCODES.o}, 'f', close); - onKeyUp({keyCode: KEYCODES.o}, 'f', close); - onKeyDown({keyCode: KEYCODES.o}, 'fo', close); - onKeyUp({keyCode: KEYCODES.o}, 'fo', close); - onKeyDown({keyCode: KEYCODES.Esc}, 'foo', close); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/waldo/.test(text)); - is(!/foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_register', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('foo'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/\/\s+foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_history', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('this'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('checks'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('search'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('history'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('checks'); - helpers.doKeys('/'); - var onKeyDown; - var onKeyUp; - var query = ''; - var keyCodes = { - Up: 38, - Down: 40 - }; - cm.openDialog = function(template, callback, options) { - onKeyUp = options.onKeyUp; - onKeyDown = options.onKeyDown; - }; - var close = function(newVal) { - if (typeof newVal == 'string') query = newVal; - } - helpers.doKeys('/'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'checks'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'history'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'search'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'this'); - onKeyDown({keyCode: keyCodes.Down}, query, close); - onKeyUp({keyCode: keyCodes.Down}, query, close); - eq(query, 'search'); -}, {value: ''}); -testVim('exCommand_history', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('registers'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('sort'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('map'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('invalid'); - helpers.doKeys(':'); - var onKeyDown; - var onKeyUp; - var input = ''; - var keyCodes = { - Up: 38, - Down: 40, - s: 115 - }; - cm.openDialog = function(template, callback, options) { - onKeyUp = options.onKeyUp; - onKeyDown = options.onKeyDown; - }; - var close = function(newVal) { - if (typeof newVal == 'string') input = newVal; - } - helpers.doKeys(':'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'invalid'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'map'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'sort'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'registers'); - onKeyDown({keyCode: keyCodes.s}, '', close); - input = 's'; - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'sort'); -}, {value: ''}); -testVim('.', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('2', 'd', 'w'); - helpers.doKeys('.'); - eq('5 6', cm.getValue()); -}, { value: '1 2 3 4 5 6'}); -testVim('._repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('2', 'd', 'w'); - helpers.doKeys('3', '.'); - eq('6', cm.getValue()); -}, { value: '1 2 3 4 5 6'}); -testVim('._insert', function(cm, vim, helpers) { - helpers.doKeys('i'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('testestt', cm.getValue()); - helpers.assertCursorAt(0, 6); -}, { value: ''}); -testVim('._insert_repeat', function(cm, vim, helpers) { - helpers.doKeys('i'); - cm.replaceRange('test', cm.getCursor()); - cm.setCursor(0, 4); - helpers.doKeys(''); - helpers.doKeys('2', '.'); - eq('testesttestt', cm.getValue()); - helpers.assertCursorAt(0, 10); -}, { value: ''}); -testVim('._repeat_insert', function(cm, vim, helpers) { - helpers.doKeys('3', 'i'); - cm.replaceRange('te', cm.getCursor()); - cm.setCursor(0, 2); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('tetettetetee', cm.getValue()); - helpers.assertCursorAt(0, 10); -}, { value: ''}); -testVim('._insert_o', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - cm.setCursor(1, 1); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('\nz\nz', cm.getValue()); - helpers.assertCursorAt(2, 0); -}, { value: ''}); -testVim('._insert_o_repeat', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(1, 0); - helpers.doKeys('2', '.'); - eq('\nz\nz\nz', cm.getValue()); - helpers.assertCursorAt(3, 0); -}, { value: ''}); -testVim('._insert_o_indent', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(1, 2); - helpers.doKeys('.'); - eq('{\n z\n z', cm.getValue()); - helpers.assertCursorAt(2, 2); -}, { value: '{'}); -testVim('._insert_cw', function(cm, vim, helpers) { - helpers.doKeys('c', 'w'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(0, 3); - helpers.doKeys('2', 'l'); - helpers.doKeys('.'); - eq('test test word3', cm.getValue()); - helpers.assertCursorAt(0, 8); -}, { value: 'word1 word2 word3' }); -testVim('._insert_cw_repeat', function(cm, vim, helpers) { - // For some reason, repeat cw in desktop VIM will does not repeat insert mode - // changes. Will conform to that behavior. - helpers.doKeys('c', 'w'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(0, 4); - helpers.doKeys('l'); - helpers.doKeys('2', '.'); - eq('test test', cm.getValue()); - helpers.assertCursorAt(0, 8); -}, { value: 'word1 word2 word3' }); -testVim('._delete', function(cm, vim, helpers) { - cm.setCursor(0, 5); - helpers.doKeys('i'); - helpers.doInsertModeKeys('Backspace'); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('zace', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'zabcde'}); -testVim('._delete_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('i'); - helpers.doInsertModeKeys('Backspace'); - helpers.doKeys(''); - helpers.doKeys('2', '.'); - eq('zzce', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'zzabcde'}); -testVim('._visual_>', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('V', 'j', '>'); - cm.setCursor(2, 0) - helpers.doKeys('.'); - eq(' 1\n 2\n 3\n 4', cm.getValue()); - helpers.assertCursorAt(2, 2); -}, { value: '1\n2\n3\n4'}); -testVim('f;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(9, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('F;', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('F', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(2, cm.getCursor().ch); -}, { value: '01x3xx6x8x'}); -testVim('t;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(8, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('T;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(2, cm.getCursor().ch); -}, { value: '0xx3xx678x'}); -testVim('f,', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('f', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(2, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('F,', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('F', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(9, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('t,', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('t', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(3, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('T,', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('T', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(8, cm.getCursor().ch); -}, { value: '01x3xx67xx'}); -testVim('fd,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('d', ';'); - eq('56789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('d', ','); - eq('01239', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fd,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('d', ';'); - eq('01239', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('d', ','); - eq('56789', cm.getValue()); -}, { value: '0123456789'}); -testVim('td,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('d', ';'); - eq('456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('d', ','); - eq('012349', cm.getValue()); -}, { value: '0123456789'}); -testVim('Td,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('d', ';'); - eq('012349', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('d', ','); - eq('456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('fc,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('c', ';', ''); - eq('56789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('c', ','); - eq('01239', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fc,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('c', ';', ''); - eq('01239', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('c', ','); - eq('56789', cm.getValue()); -}, { value: '0123456789'}); -testVim('tc,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('c', ';', ''); - eq('456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('c', ','); - eq('012349', cm.getValue()); -}, { value: '0123456789'}); -testVim('Tc,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('c', ';', ''); - eq('012349', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('c', ','); - eq('456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('fy,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('y', ';', 'P'); - eq('012340123456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('y', ',', 'P'); - eq('012345678456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fy,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('y', ';', 'p'); - eq('012345678945678', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('y', ',', 'P'); - eq('012340123456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('ty,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('y', ';', 'P'); - eq('01230123456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('y', ',', 'p'); - eq('01234567895678', cm.getValue()); -}, { value: '0123456789'}); -testVim('Ty,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('y', ';', 'p'); - eq('01234567895678', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('y', ',', 'P'); - eq('01230123456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('HML', function(cm, vim, helpers) { - var lines = 35; - var textHeight = cm.defaultTextHeight(); - cm.setSize(600, lines*textHeight); - cm.setCursor(120, 0); - cm.refresh(); //ace! - helpers.doKeys('H'); - helpers.assertCursorAt(86, 2); - helpers.doKeys('L'); - helpers.assertCursorAt(120, 4); - helpers.doKeys('M'); - helpers.assertCursorAt(103,4); -}, { value: (function(){ - var lines = new Array(100); - var upper = ' xx\n'; - var lower = ' xx\n'; - upper = lines.join(upper); - lower = lines.join(lower); - return upper + lower; -})()}); - -var zVals = []; -forEach(['zb','zz','zt','z-','z.','z'], function(e, idx){ - var lineNum = 250; - var lines = 35; - testVim(e, function(cm, vim, helpers) { - var k1 = e[0]; - var k2 = e.substring(1); - var textHeight = cm.defaultTextHeight(); - cm.setSize(600, lines*textHeight); - cm.setCursor(lineNum, 0); - helpers.doKeys(k1, k2); - zVals[idx] = cm.getScrollInfo().top; - }, { value: (function(){ - return new Array(500).join('\n'); - })()}); -}); -testVim('zb', function(cm, vim, helpers){ - eq(zVals[2], zVals[5]); -}); - -var moveTillCharacterSandbox = - 'The quick brown fox \n' - 'jumped over the lazy dog.' -testVim('moveTillCharacter', function(cm, vim, helpers){ - cm.setCursor(0, 0); - // Search for the 'q'. - cm.openDialog = helpers.fakeOpenDialog('q'); - helpers.doKeys('/'); - eq(4, cm.getCursor().ch); - // Jump to just before the first o in the list. - helpers.doKeys('t'); - helpers.doKeys('o'); - eq('The quick brown fox \n', cm.getValue()); - // Delete that one character. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('o'); - eq('The quick bown fox \n', cm.getValue()); - // Delete everything until the next 'o'. - helpers.doKeys('.'); - eq('The quick box \n', cm.getValue()); - // An unmatched character should have no effect. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('q'); - eq('The quick box \n', cm.getValue()); - // Matches should only be possible on single lines. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('z'); - eq('The quick box \n', cm.getValue()); - // After all that, the search for 'q' should still be active, so the 'N' command - // can run it again in reverse. Use that to delete everything back to the 'q'. - helpers.doKeys('d'); - helpers.doKeys('N'); - eq('The ox \n', cm.getValue()); - eq(4, cm.getCursor().ch); -}, { value: moveTillCharacterSandbox}); -testVim('searchForPipe', function(cm, vim, helpers){ - CodeMirror.Vim.setOption('pcre', false); - cm.setCursor(0, 0); - // Search for the '|'. - cm.openDialog = helpers.fakeOpenDialog('|'); - helpers.doKeys('/'); - eq(4, cm.getCursor().ch); -}, { value: 'this|that'}); - - -var scrollMotionSandbox = - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'; -testVim('scrollMotion', function(cm, vim, helpers){ - var prevCursor, prevScrollInfo; - cm.setCursor(0, 0); - // ctrl-y at the top of the file should have no effect. - helpers.doKeys(''); - eq(0, cm.getCursor().line); - prevScrollInfo = cm.getScrollInfo(); - helpers.doKeys(''); - eq(1, cm.getCursor().line); - is(prevScrollInfo.top < cm.getScrollInfo().top); - // Jump to the end of the sandbox. - cm.setCursor(1000, 0); - cm.refresh(); //ace! - prevCursor = cm.getCursor(); - // ctrl-e at the bottom of the file should have no effect. - helpers.doKeys(''); - eq(prevCursor.line, cm.getCursor().line); - cm.refresh(); //ace! - prevScrollInfo = cm.getScrollInfo(); - helpers.doKeys(''); - eq(prevCursor.line - 1, cm.getCursor().line); - is(prevScrollInfo.top > cm.getScrollInfo().top); -}, { value: scrollMotionSandbox}); - -var squareBracketMotionSandbox = ''+ - '({\n'+//0 - ' ({\n'+//11 - ' /*comment {\n'+//2 - ' */(\n'+//3 - '#else \n'+//4 - ' /* )\n'+//5 - '#if }\n'+//6 - ' )}*/\n'+//7 - ')}\n'+//8 - '{}\n'+//9 - '#else {{\n'+//10 - '{}\n'+//11 - '}\n'+//12 - '{\n'+//13 - '#endif\n'+//14 - '}\n'+//15 - '}\n'+//16 - '#else';//17 -testVim('[[, ]]', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(']', ']'); - helpers.assertCursorAt(9,0); - helpers.doKeys('2', ']', ']'); - helpers.assertCursorAt(13,0); - helpers.doKeys(']', ']'); - helpers.assertCursorAt(17,0); - helpers.doKeys('[', '['); - helpers.assertCursorAt(13,0); - helpers.doKeys('2', '[', '['); - helpers.assertCursorAt(9,0); - helpers.doKeys('[', '['); - helpers.assertCursorAt(0,0); -}, { value: squareBracketMotionSandbox}); -testVim('[], ][', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(']', '['); - helpers.assertCursorAt(12,0); - helpers.doKeys('2', ']', '['); - helpers.assertCursorAt(16,0); - helpers.doKeys(']', '['); - helpers.assertCursorAt(17,0); - helpers.doKeys('[', ']'); - helpers.assertCursorAt(16,0); - helpers.doKeys('2', '[', ']'); - helpers.assertCursorAt(12,0); - helpers.doKeys('[', ']'); - helpers.assertCursorAt(0,0); -}, { value: squareBracketMotionSandbox}); -testVim('[{, ]}', function(cm, vim, helpers) { - cm.setCursor(4, 10); - helpers.doKeys('[', '{'); - helpers.assertCursorAt(2,12); - helpers.doKeys('2', '[', '{'); - helpers.assertCursorAt(0,1); - cm.setCursor(4, 10); - helpers.doKeys(']', '}'); - helpers.assertCursorAt(6,11); - helpers.doKeys('2', ']', '}'); - helpers.assertCursorAt(8,1); - cm.setCursor(0,1); - helpers.doKeys(']', '}'); - helpers.assertCursorAt(8,1); - helpers.doKeys('[', '{'); - helpers.assertCursorAt(0,1); -}, { value: squareBracketMotionSandbox}); -testVim('[(, ])', function(cm, vim, helpers) { - cm.setCursor(4, 10); - helpers.doKeys('[', '('); - helpers.assertCursorAt(3,14); - helpers.doKeys('2', '[', '('); - helpers.assertCursorAt(0,0); - cm.setCursor(4, 10); - helpers.doKeys(']', ')'); - helpers.assertCursorAt(5,11); - helpers.doKeys('2', ']', ')'); - helpers.assertCursorAt(8,0); - helpers.doKeys('[', '('); - helpers.assertCursorAt(0,0); - helpers.doKeys(']', ')'); - helpers.assertCursorAt(8,0); -}, { value: squareBracketMotionSandbox}); -testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) { - forEach(['*', '/'], function(key){ - cm.setCursor(7, 0); - helpers.doKeys('2', '[', key); - helpers.assertCursorAt(2,2); - helpers.doKeys('2', ']', key); - helpers.assertCursorAt(7,5); - }); -}, { value: squareBracketMotionSandbox}); -testVim('[#, ]#', function(cm, vim, helpers) { - cm.setCursor(10, 3); - helpers.doKeys('2', '[', '#'); - helpers.assertCursorAt(4,0); - helpers.doKeys('5', ']', '#'); - helpers.assertCursorAt(17,0); - cm.setCursor(10, 3); - helpers.doKeys(']', '#'); - helpers.assertCursorAt(14,0); -}, { value: squareBracketMotionSandbox}); -testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) { - cm.setCursor(11, 0); - helpers.doKeys('[', 'm'); - helpers.assertCursorAt(10,7); - helpers.doKeys('4', '[', 'm'); - helpers.assertCursorAt(1,3); - helpers.doKeys('5', ']', 'm'); - helpers.assertCursorAt(11,0); - helpers.doKeys('[', 'M'); - helpers.assertCursorAt(9,1); - helpers.doKeys('3', ']', 'M'); - helpers.assertCursorAt(15,0); - helpers.doKeys('5', '[', 'M'); - helpers.assertCursorAt(7,3); -}, { value: squareBracketMotionSandbox}); - -// Ex mode tests -testVim('ex_go_to_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doEx('4'); - helpers.assertCursorAt(3, 0); -}, { value: 'a\nb\nc\nd\ne\n'}); -testVim('ex_write', function(cm, vim, helpers) { - var tmp = CodeMirror.commands.save; - var written; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - // Test that w, wr, wri ... write all trigger :write. - var command = 'write'; - for (var i = 1; i < command.length; i++) { - written = false; - actualCm = null; - helpers.doEx(command.substring(0, i)); - eq(written, true); - eq(actualCm, cm); - } - CodeMirror.commands.save = tmp; -}); -testVim('ex_sort', function(cm, vim, helpers) { - helpers.doEx('sort'); - eq('Z\na\nb\nc\nd', cm.getValue()); -}, { value: 'b\nZ\nd\nc\na'}); -testVim('ex_sort_reverse', function(cm, vim, helpers) { - helpers.doEx('sort!'); - eq('d\nc\nb\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_range', function(cm, vim, helpers) { - helpers.doEx('2,3sort'); - eq('b\nc\nd\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_oneline', function(cm, vim, helpers) { - helpers.doEx('2sort'); - // Expect no change. - eq('b\nd\nc\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_ignoreCase', function(cm, vim, helpers) { - helpers.doEx('sort i'); - eq('a\nb\nc\nd\nZ', cm.getValue()); -}, { value: 'b\nZ\nd\nc\na'}); -testVim('ex_sort_unique', function(cm, vim, helpers) { - helpers.doEx('sort u'); - eq('Z\na\nb\nc\nd', cm.getValue()); -}, { value: 'b\nZ\na\na\nd\na\nc\na'}); -testVim('ex_sort_decimal', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('d3\n s5\n6\n.9', cm.getValue()); -}, { value: '6\nd3\n s5\n.9'}); -testVim('ex_sort_decimal_negative', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('z-9\nd3\n s5\n6\n.9', cm.getValue()); -}, { value: '6\nd3\n s5\n.9\nz-9'}); -testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) { - helpers.doEx('sort! d'); - eq('.9\n6\n s5\nd3', cm.getValue()); -}, { value: '6\nd3\n s5\n.9'}); -testVim('ex_sort_hex', function(cm, vim, helpers) { - helpers.doEx('sort x'); - eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue()); -}, { value: '6\nd3\n s5\n&0xB\n.9'}); -testVim('ex_sort_octal', function(cm, vim, helpers) { - helpers.doEx('sort o'); - eq('.8\n.9\nd3\n s5\n6', cm.getValue()); -}, { value: '6\nd3\n s5\n.9\n.8'}); -testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('y\nz\nc1\nb2\na3', cm.getValue()); -}, { value: 'a3\nz\nc1\ny\nb2'}); -testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) { - helpers.doEx('sort! d'); - eq('a3\nb2\nc1\nz\ny', cm.getValue()); -}, { value: 'a3\nz\nc1\ny\nb2'}); -// test for :global command -testVim('ex_global', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doEx('g/one/s//two'); - eq('two two\n two two\n two two', cm.getValue()); - helpers.doEx('1,2g/two/s//one'); - eq('one one\n one one\n two two', cm.getValue()); -}, {value: 'one one\n one one\n one one'}); -testVim('ex_global_confirm', function(cm, vim, helpers) { - cm.setCursor(0, 0); - var onKeyDown; - var openDialogSave = cm.openDialog; - var KEYCODES = { - a: 65, - n: 78, - q: 81, - y: 89 - }; - // Intercept the ex command, 'global' - cm.openDialog = function(template, callback, options) { - // Intercept the prompt for the embedded ex command, 'substitute' - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - }; - callback('g/one/s//two/gc'); - }; - helpers.doKeys(':'); - var close = function() {}; - onKeyDown({keyCode: KEYCODES.n}, '', close); - onKeyDown({keyCode: KEYCODES.y}, '', close); - onKeyDown({keyCode: KEYCODES.a}, '', close); - onKeyDown({keyCode: KEYCODES.q}, '', close); - onKeyDown({keyCode: KEYCODES.y}, '', close); - eq('one two\n two two\n one one\n two one\n one one', cm.getValue()); -}, {value: 'one one\n one one\n one one\n one one\n one one'}); -// Basic substitute tests. -testVim('ex_substitute_same_line', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('s/one/two/g'); - eq('one one\n two two', cm.getValue()); -}, { value: 'one one\n one one'}); -testVim('ex_substitute_full_file', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('%s/one/two/g'); - eq('two two\n two two', cm.getValue()); -}, { value: 'one one\n one one'}); -testVim('ex_substitute_input_range', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('1,3s/\\d/0/g'); - eq('0\n0\n0\n4', cm.getValue()); -}, { value: '1\n2\n3\n4' }); -testVim('ex_substitute_visual_range', function(cm, vim, helpers) { - cm.setCursor(1, 0); - // Set last visual mode selection marks '< and '> at lines 2 and 4 - helpers.doKeys('V', '2', 'j', 'v'); - helpers.doEx('\'<,\'>s/\\d/0/g'); - eq('1\n0\n0\n0\n5', cm.getValue()); -}, { value: '1\n2\n3\n4\n5' }); -testVim('ex_substitute_empty_query', function(cm, vim, helpers) { - // If the query is empty, use last query. - cm.setCursor(1, 0); - cm.openDialog = helpers.fakeOpenDialog('1'); - helpers.doKeys('/'); - helpers.doEx('s//b/g'); - eq('abb ab2 ab3', cm.getValue()); -}, { value: 'a11 a12 a13' }); -testVim('ex_substitute_javascript', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', false); - cm.setCursor(1, 0); - // Throw all the things that javascript likes to treat as special values - // into the replace part. All should be literal (this is VIM). - helpers.doEx('s/\\(\\d+\\)/$$ $\' $` $& \\1/g') - eq('a $$ $\' $` $& 0 b', cm.getValue()); -}, { value: 'a 0 b' }); -testVim('ex_substitute_empty_arguments', function(cm,vim,helpers) { - cm.setCursor(0, 0); - helpers.doEx('s/a/b/g'); - cm.setCursor(1, 0); - helpers.doEx('s'); - eq('b b\nb a', cm.getValue()); -}, {value: 'a a\na a'}); - -// More complex substitute tests that test both pcre and nopcre options. -function testSubstitute(name, options) { - testVim(name + '_pcre', function(cm, vim, helpers) { - cm.setCursor(1, 0); - CodeMirror.Vim.setOption('pcre', true); - helpers.doEx(options.expr); - eq(options.expectedValue, cm.getValue()); - }, options); - // If no noPcreExpr is defined, assume that it's the same as the expr. - var noPcreExpr = options.noPcreExpr ? options.noPcreExpr : options.expr; - testVim(name + '_nopcre', function(cm, vim, helpers) { - cm.setCursor(1, 0); - CodeMirror.Vim.setOption('pcre', false); - helpers.doEx(noPcreExpr); - eq(options.expectedValue, cm.getValue()); - }, options); -} -testSubstitute('ex_substitute_capture', { - value: 'a11 a12 a13', - expectedValue: 'a1111 a1212 a1313', - // $n is a backreference - expr: 's/(\\d+)/$1$1/g', - // \n is a backreference. - noPcreExpr: 's/\\(\\d+\\)/\\1\\1/g'}); -testSubstitute('ex_substitute_capture2', { - value: 'a 0 b', - expectedValue: 'a $00 b', - expr: 's/(\\d+)/$$$1$1/g', - noPcreExpr: 's/\\(\\d+\\)/$\\1\\1/g'}); -testSubstitute('ex_substitute_nocapture', { - value: 'a11 a12 a13', - expectedValue: 'a$1$1 a$1$1 a$1$1', - expr: 's/(\\d+)/$$1$$1/g', - noPcreExpr: 's/\\(\\d+\\)/$1$1/g'}); -testSubstitute('ex_substitute_nocapture2', { - value: 'a 0 b', - expectedValue: 'a $10 b', - expr: 's/(\\d+)/$$1$1/g', - noPcreExpr: 's/\\(\\d+\\)/\\$1\\1/g'}); -testSubstitute('ex_substitute_nocapture', { - value: 'a b c', - expectedValue: 'a $ c', - expr: 's/b/$$/', - noPcreExpr: 's/b/$/'}); -testSubstitute('ex_substitute_slash_regex', { - value: 'one/two \n three/four', - expectedValue: 'one|two \n three|four', - expr: '%s/\\//|'}); -testSubstitute('ex_substitute_pipe_regex', { - value: 'one|two \n three|four', - expectedValue: 'one,two \n three,four', - expr: '%s/\\|/,/', - noPcreExpr: '%s/|/,/'}); -testSubstitute('ex_substitute_or_regex', { - value: 'one|two \n three|four', - expectedValue: 'ana|twa \n thraa|faar', - expr: '%s/o|e|u/a/g', - noPcreExpr: '%s/o\\|e\\|u/a/g'}); -testSubstitute('ex_substitute_or_word_regex', { - value: 'one|two \n three|four', - expectedValue: 'five|five \n three|four', - expr: '%s/(one|two)/five/g', - noPcreExpr: '%s/\\(one\\|two\\)/five/g'}); -testSubstitute('ex_substitute_backslashslash_regex', { - value: 'one\\two \n three\\four', - expectedValue: 'one,two \n three,four', - expr: '%s/\\\\/,'}); -testSubstitute('ex_substitute_slash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one/two \n three/four', - expr: '%s/,/\\/'}); -testSubstitute('ex_substitute_backslash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one\\two \n three\\four', - expr: '%s/,/\\\\/g'}); -testSubstitute('ex_substitute_multibackslash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one\\\\\\\\two \n three\\\\\\\\four', // 2*8 backslashes. - expr: '%s/,/\\\\\\\\\\\\\\\\/g'}); // 16 backslashes. -testSubstitute('ex_substitute_braces_word', { - value: 'ababab abb ab{2}', - expectedValue: 'ab abb ab{2}', - expr: '%s/(ab){2}//g', - noPcreExpr: '%s/\\(ab\\)\\{2\\}//g'}); -testSubstitute('ex_substitute_braces_range', { - value: 'a aa aaa aaaa', - expectedValue: 'a a', - expr: '%s/a{2,3}//g', - noPcreExpr: '%s/a\\{2,3\\}//g'}); -testSubstitute('ex_substitute_braces_literal', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab abb ', - expr: '%s/ab\\{2\\}//g', - noPcreExpr: '%s/ab{2}//g'}); -testSubstitute('ex_substitute_braces_char', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab ab{2}', - expr: '%s/ab{2}//g', - noPcreExpr: '%s/ab\\{2\\}//g'}); -testSubstitute('ex_substitute_braces_no_escape', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab ab{2}', - expr: '%s/ab{2}//g', - noPcreExpr: '%s/ab\\{2}//g'}); -testSubstitute('ex_substitute_count', { - value: '1\n2\n3\n4', - expectedValue: '1\n0\n0\n4', - expr: 's/\\d/0/i 2'}); -testSubstitute('ex_substitute_count_with_range', { - value: '1\n2\n3\n4', - expectedValue: '1\n2\n0\n0', - expr: '1,3s/\\d/0/ 3'}); -testSubstitute('ex_substitute_not_global', { - value: 'aaa\nbaa\ncaa', - expectedValue: 'xaa\nbxa\ncxa', - expr: '%s/a/x/'}); -function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) { - testVim(name, function(cm, vim, helpers) { - var savedOpenDialog = cm.openDialog; - var savedKeyName = CodeMirror.keyName; - var onKeyDown; - var recordedCallback; - var closed = true; // Start out closed, set false on second openDialog. - function close() { - closed = true; - } - // First openDialog should save callback. - cm.openDialog = function(template, callback, options) { - recordedCallback = callback; - } - // Do first openDialog. - helpers.doKeys(':'); - // Second openDialog should save keyDown handler. - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - closed = false; - }; - // Return the command to Vim and trigger second openDialog. - recordedCallback(command); - // The event should really use keyCode, but here just mock it out and use - // key and replace keyName to just return key. - CodeMirror.keyName = function (e) { return e.key; } - keys = keys.toUpperCase(); - for (var i = 0; i < keys.length; i++) { - is(!closed); - onKeyDown({ key: keys.charAt(i) }, '', close); - } - try { - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(finalPos); - is(closed); - } catch(e) { - throw e - } finally { - // Restore overriden functions. - CodeMirror.keyName = savedKeyName; - cm.openDialog = savedOpenDialog; - } - }, { value: initialValue }); -}; -testSubstituteConfirm('ex_substitute_confirm_emptydoc', - '%s/x/b/c', '', '', '', makeCursor(0, 0)); -testSubstituteConfirm('ex_substitute_confirm_nomatch', - '%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0)); -testSubstituteConfirm('ex_substitute_confirm_accept', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_random_keys', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_some', - '%s/a/b/cg', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_all', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_accept_then_all', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_quit', - '%s/a/b/cg', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_last', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_oneline', - '1s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_range_accept', - '1,2s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_some', - '1,3s/a/b/cg', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_all', - '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_last', - '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0)); -//:noh should clear highlighting of search-results but allow to resume search through n -testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('?'); - helpers.doEx('noh'); - eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared'); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting'); -}, { value: 'match nope match \n nope Match' }); -testVim('set_boolean', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', true, 'boolean'); - // Test default value is set. - is(CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set to non-boolean - CodeMirror.Vim.setOption('testoption', '5'); - fail(); - } catch (expected) {}; - // Test setOption - CodeMirror.Vim.setOption('testoption', false); - is(!CodeMirror.Vim.getOption('testoption')); -}); -testVim('ex_set_boolean', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', true, 'boolean'); - // Test default value is set. - is(CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set to non-boolean - helpers.doEx('set testoption=22'); - fail(); - } catch (expected) {}; - // Test setOption - helpers.doEx('set notestoption'); - is(!CodeMirror.Vim.getOption('testoption')); -}); -testVim('set_string', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', 'a', 'string'); - // Test default value is set. - eq('a', CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set non-string. - CodeMirror.Vim.setOption('testoption', true); - fail(); - } catch (expected) {}; - try { - // Test fail to set 'notestoption' - CodeMirror.Vim.setOption('notestoption', 'b'); - fail(); - } catch (expected) {}; - // Test setOption - CodeMirror.Vim.setOption('testoption', 'c'); - eq('c', CodeMirror.Vim.getOption('testoption')); -}); -testVim('ex_set_string', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', 'a', 'string'); - // Test default value is set. - eq('a', CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set 'notestoption' - helpers.doEx('set notestoption=b'); - fail(); - } catch (expected) {}; - // Test setOption - helpers.doEx('set testoption=c') - eq('c', CodeMirror.Vim.getOption('testoption')); -}); -// TODO: Reset key maps after each test. -testVim('ex_map_key2key', function(cm, vim, helpers) { - helpers.doEx('map a x'); - helpers.doKeys('a'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); -testVim('ex_unmap_key2key', function(cm, vim, helpers) { - helpers.doEx('unmap a'); - helpers.doKeys('a'); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'abc' }); -testVim('ex_unmap_key2key_does_not_remove_default', function(cm, vim, helpers) { - try { - helpers.doEx('unmap a'); - fail(); - } catch (expected) {} - helpers.doKeys('a'); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'abc' }); -testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) { - helpers.doEx('map ; :'); - var dialogOpened = false; - cm.openDialog = function() { - dialogOpened = true; - } - helpers.doKeys(';'); - eq(dialogOpened, true); -}); -testVim('ex_map_ex2key:', function(cm, vim, helpers) { - helpers.doEx('map :del x'); - helpers.doEx('del'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); -testVim('ex_map_ex2ex', function(cm, vim, helpers) { - helpers.doEx('map :del :w'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - helpers.doEx('del'); - CodeMirror.commands.save = tmp; - eq(written, true); - eq(actualCm, cm); -}); -testVim('ex_map_key2ex', function(cm, vim, helpers) { - helpers.doEx('map a :w'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - helpers.doKeys('a'); - CodeMirror.commands.save = tmp; - eq(written, true); - eq(actualCm, cm); -}); -testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) { - CodeMirror.Vim.map('b', ':w', 'visual'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - // Mapping should not work in normal mode. - helpers.doKeys('b'); - eq(written, false); - // Mapping should work in visual mode. - helpers.doKeys('v', 'b'); - eq(written, true); - eq(actualCm, cm); - - CodeMirror.commands.save = tmp; -}); -testVim('ex_imap', function(cm, vim, helpers) { - CodeMirror.Vim.map('jk', '', 'insert'); - helpers.doKeys('i'); - is(vim.insertMode); - helpers.doKeys('j', 'k'); - is(!vim.insertMode); -}) - -// Testing registration of functions as ex-commands and mapping to -keys -testVim('ex_api_test', function(cm, vim, helpers) { - var res=false; - var val='from'; - CodeMirror.Vim.defineEx('extest','ext',function(cm,params){ - if(params.args)val=params.args[0]; - else res=true; - }); - helpers.doEx(':ext to'); - eq(val,'to','Defining ex-command failed'); - CodeMirror.Vim.map('',':ext'); - helpers.doKeys('',''); - is(res,'Mapping to key failed'); -}); -// For now, this test needs to be last because it messes up : for future tests. -testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) { - helpers.doEx('map : x'); - helpers.doKeys(':'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); - -// Test event handlers -testVim('beforeSelectionChange', function(cm, vim, helpers) { - cm.setCursor(0, 100); - eqPos(cm.getCursor('head'), cm.getCursor('anchor')); -}, { value: 'abc' }); - - -}); - - -if (typeof module !== "undefined" && module === require.main) { - require("asyncjs").test.testcase(module.exports).exec(); -} diff --git a/lib/ace/keyboard/vim_test.js b/lib/ace/keyboard/vim_test.js index 3e81c007..1fd8c320 100644 --- a/lib/ace/keyboard/vim_test.js +++ b/lib/ace/keyboard/vim_test.js @@ -1,527 +1,3709 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2014, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ if (typeof process !== "undefined") { require("amd-loader"); } define(function(require, exports, module) { -"use strict"; -function repeat(str, times) { - return new Array(times + 1).join(str); -} +var EditSession = require("./../edit_session").EditSession; +var Editor = require("./../editor").Editor; +var UndoManager = require("./../undomanager").UndoManager; +var MockRenderer = require("./../test/mockrenderer").MockRenderer; +var JavaScriptMode = require("./../mode/javascript").Mode; +var VirtualRenderer = require("./../virtual_renderer").VirtualRenderer; +var assert = require("./../test/assertions"); +var keys = require("./../lib/keys"); +var vim = require("./vim"); -var EditSession = require("./../edit_session").EditSession, - Editor = require("./../editor").Editor, - UndoManager = require("./../undomanager").UndoManager, - MockRenderer = require("./../test/mockrenderer").MockRenderer, - assert = require("./../test/assertions"), - keys = require("./../lib/keys"), - vim = require("./vim"), - editor, - keyCodeByFuncKey = {}, - tests = {}; +var el = document.createElement("div"); +el.style.position = "fixed"; +el.style.left = "20px"; +el.style.top = "30px"; +el.style.width = "500px"; +el.style.height = "300px"; +document.body.appendChild(el); -//Helper functions +if (!el.getBoundingClientRect) + return console.log("Skipping test: This test only runs in the browser"); -function initKeyCodeByFuncKey() { - for (var keyCode in keys.FUNCTION_KEYS) { - var funcKey = keys.FUNCTION_KEYS[keyCode]; - keyCodeByFuncKey[funcKey] = keyCode; - } -} - -function initEditor(docString) { - var session = new EditSession(docString.split("\n")); - var undoManager = new UndoManager(); - session.setUndoManager(undoManager); - editor = new Editor(new MockRenderer(), session); +var renderer = new VirtualRenderer(el); +editor = new Editor(renderer);//(new MockRenderer()); +editor.session.setUndoManager(new UndoManager()); +editor.session.setUseWorker(false); +editor.session.setMode(new JavaScriptMode()); +function CodeMirror(place, opts) { + if (opts.value != null) + editor.session.setValue(opts.value); + editor.setOption("wrap", opts.lineWrapping); + editor.setOption("useSoftTabs", !opts.indentWithTabs); + editor.setKeyboardHandler(null); editor.setKeyboardHandler(vim.handler); + var cm = editor.state.cm; + cm.setOption("tabSize", opts.tabSize || 4); + cm.setOption("indentUnit", opts.indentUnit || 2); + + cm.setSize = function(w, h) { + var changed = false; + if (w && editor.w != w) { + changed = true; + el.style.width = (editor.w = w) + "px"; + } + if (h && editor.h != h) { + changed = true; + el.style.height = (editor.h = h) + "px"; + } + if (changed) + editor.resize(true); + }; + cm.setSize(500, 300); + return cm; +} +for (var key in vim.CodeMirror) + CodeMirror[key] = vim.CodeMirror[key]; +var editor; +var i = 0; +function test(name, fn) { + // if (name != 'vim_search_history') return + // for (i = 0; i < 1000; i++) + // exports["test " + name + i] = fn; // vim_ex_global_confirm + if (i++ < 0 || /- /.test(name)) + exports["test " + name] = function() {}; + else + exports["test " + name] = fn; } -function sendKeys() { - //Vim handler needs to be sent a key at a time for undo to work - //Handle any mix of command keys and text input arguments - for (var argInt=0; argInt= 0) ? (unsigned char) *bufp++ : EOF;\n' + +' \n' + +'}\n'; + +var lines = (function() { + lineText = code.split('\n'); + var ret = []; + for (var i = 0; i < lineText.length; i++) { + ret[i] = { + line: i, + length: lineText[i].length, + lineText: lineText[i], + textStart: /^\s*/.exec(lineText[i])[0].length + }; + } + return ret; +})(); +var endOfDocument = makeCursor(lines.length - 1, + lines[lines.length - 1].length); +var wordLine = lines[0]; +var bigWordLine = lines[1]; +var charLine = lines[2]; +var bracesLine = lines[3]; +var seekBraceLine = lines[4]; + +var word1 = { + start: { line: wordLine.line, ch: 1 }, + end: { line: wordLine.line, ch: 5 } +}; +var word2 = { + start: { line: wordLine.line, ch: word1.end.ch + 2 }, + end: { line: wordLine.line, ch: word1.end.ch + 4 } +}; +var word3 = { + start: { line: bigWordLine.line, ch: 1 }, + end: { line: bigWordLine.line, ch: 5 } +}; +var bigWord1 = word1; +var bigWord2 = word2; +var bigWord3 = { + start: { line: bigWordLine.line, ch: 1 }, + end: { line: bigWordLine.line, ch: 7 } +}; +var bigWord4 = { + start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 }, + end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 } +}; + +var oChars = [ { line: charLine.line, ch: 1 }, + { line: charLine.line, ch: 3 }, + { line: charLine.line, ch: 7 } ]; +var pChars = [ { line: charLine.line, ch: 2 }, + { line: charLine.line, ch: 4 }, + { line: charLine.line, ch: 6 }, + { line: charLine.line, ch: 8 } ]; +var numChars = [ { line: charLine.line, ch: 10 }, + { line: charLine.line, ch: 12 }, + { line: charLine.line, ch: 14 }, + { line: charLine.line, ch: 16 }, + { line: charLine.line, ch: 18 }]; +var parens1 = { + start: { line: bracesLine.line, ch: 1 }, + end: { line: bracesLine.line, ch: 3 } +}; +var squares1 = { + start: { line: bracesLine.line, ch: 5 }, + end: { line: bracesLine.line, ch: 7 } +}; +var curlys1 = { + start: { line: bracesLine.line, ch: 9 }, + end: { line: bracesLine.line, ch: 11 } +}; +var seekOutside = { + start: { line: seekBraceLine.line, ch: 1 }, + end: { line: seekBraceLine.line, ch: 16 } +}; +var seekInside = { + start: { line: seekBraceLine.line, ch: 14 }, + end: { line: seekBraceLine.line, ch: 11 } +}; + +function copyCursor(cur) { + return { ch: cur.ch, line: cur.line }; +} + +function forEach(arr, func) { + for (var i = 0; i < arr.length; i++) { + func(arr[i], i, arr); + } +} + +function testVim(name, run, opts, expectedFail) { + var vimOpts = { + lineNumbers: true, + vimMode: true, + showCursorWhenSelecting: true, + value: code + }; + for (var prop in opts) { + if (opts.hasOwnProperty(prop)) { + vimOpts[prop] = opts[prop]; + } + } + return test('vim_' + name, function() { + var place = document.getElementById("testground"); + var cm = CodeMirror(place, vimOpts); + var vim = CodeMirror.Vim.maybeInitVimState_(cm); + + function doKeysFn(cm) { + return function(args) { + if (args instanceof Array) { + arguments = args; + } + for (var i = 0; i < arguments.length; i++) { + CodeMirror.Vim.handleKey(cm, arguments[i]); + } + } + } + function doInsertModeKeysFn(cm) { + return function(args) { + if (args instanceof Array) { arguments = args; } + function executeHandler(handler) { + if (typeof handler == 'string') { + CodeMirror.commands[handler](cm); + } else { + handler(cm); + } + return true; + } + for (var i = 0; i < arguments.length; i++) { + var key = arguments[i]; + // Find key in keymap and handle. + var handled = CodeMirror.lookupKey(key, 'vim-insert', executeHandler); + // Record for insert mode. + if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') { + var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges; + if (lastChange) { + lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key)); } + } } - if (hashId === 0) { - trailingKeys = arg; - } - var keyCode; - if (keyCodeByFuncKey.hasOwnProperty(trailingKeys)) { - keyCode = keyCodeByFuncKey[trailingKeys]; - editor.onCommandKey({}, hashId, keyCode); + } + } + function doExFn(cm) { + return function(command) { + cm.openDialog = helpers.fakeOpenDialog(command); + helpers.doKeys(':'); + } + } + function assertCursorAtFn(cm) { + return function(line, ch) { + var pos; + if (ch == null && typeof line.line == 'number') { + pos = line; } else { - if (hashId !== 0) { - keyCode = trailingKeys.toUpperCase().charCodeAt(0); - editor.onCommandKey({}, hashId, keyCode); - } else { - for (var i=0; i" + title + ""; + function fakeOpenDialog(result) { + return function(text, callback) { + return callback(result); + } } - tests[testName] = testFunction; + function fakeOpenNotification(matcher) { + return function(text) { + matcher(text); + } + } + var helpers = { + doKeys: doKeysFn(cm), + // Warning: Only emulates keymap events, not character insertions. Use + // replaceRange to simulate character insertions. + // Keys are in CodeMirror format, NOT vim format. + doInsertModeKeys: doInsertModeKeysFn(cm), + doEx: doExFn(cm), + assertCursorAt: assertCursorAtFn(cm), + fakeOpenDialog: fakeOpenDialog, + fakeOpenNotification: fakeOpenNotification, + getRegisterController: function() { + return CodeMirror.Vim.getRegisterController(); + } + } + CodeMirror.Vim.resetVimGlobalState_(); + var successful = false; + var savedOpenNotification = cm.openNotification; + try { + run(cm, vim, helpers); + successful = true; + } finally { + cm.openNotification = savedOpenNotification; + // if (!successful || verbose) { + // place.style.visibility = "visible"; + // } else { + // place.removeChild(cm.getWrapperElement()); + // } + } + }, expectedFail); +}; +testVim('qq@q', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'q', 'l', 'l', 'q'); + helpers.assertCursorAt(0,2); + helpers.doKeys('@', 'q'); + helpers.assertCursorAt(0,4); +}, { value: ' '}); +testVim('@@', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'q', 'l', 'l', 'q'); + helpers.assertCursorAt(0,2); + helpers.doKeys('@', 'q'); + helpers.assertCursorAt(0,4); + helpers.doKeys('@', '@'); + helpers.assertCursorAt(0,6); +}, { value: ' '}); +var jumplistScene = ''+ + 'word\n'+ + '(word)\n'+ + '{word\n'+ + 'word.\n'+ + '\n'+ + 'word search\n'+ + '}word\n'+ + 'word\n'+ + 'word\n'; +function testJumplist(name, keys, endPos, startPos, dialog) { + endPos = makeCursor(endPos[0], endPos[1]); + startPos = makeCursor(startPos[0], startPos[1]); + testVim(name, function(cm, vim, helpers) { + CodeMirror.Vim.resetVimGlobalState_(); + if(dialog)cm.openDialog = helpers.fakeOpenDialog('word'); + cm.setCursor(startPos); + helpers.doKeys.apply(null, keys); + helpers.assertCursorAt(endPos); + }, {value: jumplistScene}); +}; +testJumplist('jumplist_H', ['H', ''], [5,2], [5,2]); +testJumplist('jumplist_M', ['M', ''], [2,2], [2,2]); +testJumplist('jumplist_L', ['L', ''], [2,2], [2,2]); +testJumplist('jumplist_[[', ['[', '[', ''], [5,2], [5,2]); +testJumplist('jumplist_]]', [']', ']', ''], [2,2], [2,2]); +testJumplist('jumplist_G', ['G', ''], [5,2], [5,2]); +testJumplist('jumplist_gg', ['g', 'g', ''], [5,2], [5,2]); +testJumplist('jumplist_%', ['%', ''], [1,5], [1,5]); +testJumplist('jumplist_{', ['{', ''], [1,5], [1,5]); +testJumplist('jumplist_}', ['}', ''], [1,5], [1,5]); +testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', ''], [1,0], [1,5]); +testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', ''], [1,5], [1,5]); +testJumplist('jumplist_*_cachedCursor', ['*', ''], [1,3], [1,3]); +testJumplist('jumplist_#_cachedCursor', ['#', ''], [1,3], [1,3]); +testJumplist('jumplist_n', ['#', 'n', ''], [1,1], [2,3]); +testJumplist('jumplist_N', ['#', 'N', ''], [1,1], [2,3]); +testJumplist('jumplist_repeat_', ['*', '*', '*', '3', ''], [2,3], [2,3]); +testJumplist('jumplist_repeat_', ['*', '*', '*', '3', '', '2', ''], [5,0], [2,3]); +testJumplist('jumplist_repeated_motion', ['3', '*', ''], [2,3], [2,3]); +testJumplist('jumplist_/', ['/', ''], [2,3], [2,3], 'dialog'); +testJumplist('jumplist_?', ['?', ''], [2,3], [2,3], 'dialog'); +testJumplist('jumplist_skip_delted_mark', + ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], + [0,2], [0,2]); +testJumplist('jumplist_skip_delted_mark', + ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], + [1,0], [0,2]); + +/** + * @param name Name of the test + * @param keys An array of keys or a string with a single key to simulate. + * @param endPos The expected end position of the cursor. + * @param startPos The position the cursor should start at, defaults to 0, 0. + */ +function testMotion(name, keys, endPos, startPos) { + testVim(name, function(cm, vim, helpers) { + if (!startPos) { + startPos = { line: 0, ch: 0 }; + } + cm.setCursor(startPos); + helpers.doKeys(keys); + helpers.assertCursorAt(endPos); + }); +}; + +function makeCursor(line, ch) { + return { line: line, ch: ch }; +}; + +function offsetCursor(cur, offsetLine, offsetCh) { + return { line: cur.line + offsetLine, ch: cur.ch + offsetCh }; +}; + +// Motion tests +testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4)); +testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4)); +testMotion('h', 'h', makeCursor(0, 0), word1.start); +testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end); +testMotion('l', 'l', makeCursor(0, 1)); +testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2)); +testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end); +testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end); +testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument); +testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end); +testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4)); +testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4)); +testMotion('w', 'w', word1.start); +testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2)); +testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51)); +testMotion('w_repeat', ['2', 'w'], word2.start); +testMotion('w_wrap', ['w'], word3.start, word2.start); +testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument); +testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0)); +testMotion('W', 'W', bigWord1.start); +testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start); +testMotion('e', 'e', word1.end); +testMotion('e_repeat', ['2', 'e'], word2.end); +testMotion('e_wrap', 'e', word3.end, word2.end); +testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument); +testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0)); +testMotion('b', 'b', word3.start, word3.end); +testMotion('b_repeat', ['2', 'b'], word2.start, word3.end); +testMotion('b_wrap', 'b', word2.start, word3.start); +testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0)); +testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument); +testMotion('ge', ['g', 'e'], word2.end, word3.end); +testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start); +testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start); +testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0), + makeCursor(0, 0)); +testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument); +testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart), + makeCursor(3, 1)); +testMotion('gg_repeat', ['3', 'g', 'g'], + makeCursor(lines[2].line, lines[2].textStart)); +testMotion('G', 'G', + makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart), + makeCursor(3, 1)); +testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line, + lines[2].textStart)); +// TODO: Make the test code long enough to test Ctrl-F and Ctrl-B. +testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8)); +testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8)); +testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8)); +testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4)); +testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8)); +testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1)); +testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1), + makeCursor(0, 3)); +testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0)); +testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]); +testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0)); +testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1), + makeCursor(charLine.line, 0)); +testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1), + pChars[0]); +testMotion('F', ['F', 'p'], pChars[0], pChars[1]); +testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]); +testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]); +testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]); +testMotion('%_parens', ['%'], parens1.end, parens1.start); +testMotion('%_squares', ['%'], squares1.end, squares1.start); +testMotion('%_braces', ['%'], curlys1.end, curlys1.start); +testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start); +testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start); +testVim('%_seek_skip', function(cm, vim, helpers) { + cm.setCursor(0,0); + helpers.doKeys(['%']); + helpers.assertCursorAt(0,9); +}, {value:'01234"("()'}); +testVim('%_skip_string', function(cm, vim, helpers) { + cm.setCursor(0,0); + helpers.doKeys(['%']); + helpers.assertCursorAt(0,4); + cm.setCursor(0,2); + helpers.doKeys(['%']); + helpers.assertCursorAt(0,0); +}, {value:'(")")'}); +(')') +testVim('%_skip_comment', function(cm, vim, helpers) { + cm.setCursor(0,0); + helpers.doKeys(['%']); + helpers.assertCursorAt(0,6); + cm.setCursor(0,3); + helpers.doKeys(['%']); + helpers.assertCursorAt(0,0); +}, {value:'(/*)*/)'}); +// Make sure that moving down after going to the end of a line always leaves you +// at the end of a line, but preserves the offset in other cases +testVim('Changing lines after Eol operation', function(cm, vim, helpers) { + cm.setCursor(0,0); + helpers.doKeys(['$']); + helpers.doKeys(['j']); + // After moving to Eol and then down, we should be at Eol of line 2 + helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 }); + helpers.doKeys(['j']); + // After moving down, we should be at Eol of line 3 + helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 }); + helpers.doKeys(['h']); + helpers.doKeys(['j']); + // After moving back one space and then down, since line 4 is shorter than line 2, we should + // be at Eol of line 2 - 1 + helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 }); + helpers.doKeys(['j']); + helpers.doKeys(['j']); + // After moving down again, since line 3 has enough characters, we should be back to the + // same place we were at on line 1 + helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 }); +}); +//making sure gj and gk recover from clipping +testVim('gj_gk_clipping', function(cm,vim,helpers){ + cm.setCursor(0, 1); + helpers.doKeys('g','j','g','j'); + helpers.assertCursorAt(2, 1); + helpers.doKeys('g','k','g','k'); + helpers.assertCursorAt(0, 1); +},{value: 'line 1\n\nline 2'}); +//testing a mix of j/k and gj/gk +testVim('j_k_and_gj_gk', function(cm,vim,helpers){ + cm.setSize(120); + cm.setCursor(0, 0); + //go to the last character on the first line + helpers.doKeys('$'); + //move up/down on the column within the wrapped line + //side-effect: cursor is not locked to eol anymore + helpers.doKeys('g','k'); + var cur=cm.getCursor(); + eq(cur.line,0); + is((cur.ch<176),'gk didn\'t move cursor back (1)'); + helpers.doKeys('g','j'); + helpers.assertCursorAt(0, 176); + //should move to character 177 on line 2 (j/k preserve character index within line) + helpers.doKeys('j'); + //due to different line wrapping, the cursor can be on a different screen-x now + //gj and gk preserve screen-x on movement, much like moveV + helpers.doKeys('3','g','k'); + cur=cm.getCursor(); + eq(cur.line,1); + is((cur.ch<176),'gk didn\'t move cursor back (2)'); + helpers.doKeys('g','j','2','g','j'); + //should return to the same character-index + helpers.doKeys('k'); + helpers.assertCursorAt(0, 176); +},{ lineWrapping:true, value: 'This line is intentially long to test movement of gj and gk over wrapped lines. I will start on the end of this line, then make a step up and back to set the origin for j and k.\nThis line is supposed to be even longer than the previous. I will jump here and make another wiggle with gj and gk, before I jump back to the line above. Both wiggles should not change my cursor\'s target character but both j/k and gj/gk change each other\'s reference position.'}); +testVim('gj_gk', function(cm, vim, helpers) { + if (phantom) return; + cm.setSize(120); + // Test top of document edge case. + cm.setCursor(0, 4); + helpers.doKeys('g', 'j'); + helpers.doKeys('10', 'g', 'k'); + helpers.assertCursorAt(0, 4); + + // Test moving down preserves column position. + helpers.doKeys('g', 'j'); + var pos1 = cm.getCursor(); + var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4}; + helpers.doKeys('g', 'j'); + helpers.assertCursorAt(expectedPos2); + + // Move to the last character + cm.setCursor(0, 0); + // Move left to reset HSPos + helpers.doKeys('h'); + // Test bottom of document edge case. + helpers.doKeys('100', 'g', 'j'); + var endingPos = cm.getCursor(); + is(endingPos != 0, 'gj should not be on wrapped line 0'); + var topLeftCharCoords = cm.charCoords(makeCursor(0, 0)); + var endingCharCoords = cm.charCoords(endingPos); + is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0'); +},{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' }); +testVim('}', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('}'); + helpers.assertCursorAt(1, 0); + cm.setCursor(0, 0); + helpers.doKeys('2', '}'); + helpers.assertCursorAt(4, 0); + cm.setCursor(0, 0); + helpers.doKeys('6', '}'); + helpers.assertCursorAt(5, 0); +}, { value: 'a\n\nb\nc\n\nd' }); +testVim('{', function(cm, vim, helpers) { + cm.setCursor(5, 0); + helpers.doKeys('{'); + helpers.assertCursorAt(4, 0); + cm.setCursor(5, 0); + helpers.doKeys('2', '{'); + helpers.assertCursorAt(1, 0); + cm.setCursor(5, 0); + helpers.doKeys('6', '{'); + helpers.assertCursorAt(0, 0); +}, { value: 'a\n\nb\nc\n\nd' }); + +// Operator tests +testVim('dl', function(cm, vim, helpers) { + var curStart = makeCursor(0, 0); + cm.setCursor(curStart); + helpers.doKeys('d', 'l'); + eq('word1 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(' ', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1 ' }); +testVim('dl_eol', function(cm, vim, helpers) { + cm.setCursor(0, 6); + helpers.doKeys('d', 'l'); + eq(' word1', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(' ', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 6); +}, { value: ' word1 ' }); +testVim('dl_repeat', function(cm, vim, helpers) { + var curStart = makeCursor(0, 0); + cm.setCursor(curStart); + helpers.doKeys('2', 'd', 'l'); + eq('ord1 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(' w', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1 ' }); +testVim('dh', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + helpers.doKeys('d', 'h'); + eq(' wrd1 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('o', register.toString()); + is(!register.linewise); + eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor()); +}, { value: ' word1 ' }); +testVim('dj', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + helpers.doKeys('d', 'j'); + eq(' word3', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(' word1\nword2\n', register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\nword2\n word3' }); +testVim('dj_end_of_document', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + helpers.doKeys('d', 'j'); + eq(' word1 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 3); +}, { value: ' word1 ' }); +testVim('dk', function(cm, vim, helpers) { + var curStart = makeCursor(1, 3); + cm.setCursor(curStart); + helpers.doKeys('d', 'k'); + eq(' word3', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(' word1\nword2\n', register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\nword2\n word3' }); +testVim('dk_start_of_document', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + helpers.doKeys('d', 'k'); + eq(' word1 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 3); +}, { value: ' word1 ' }); +testVim('dw_space', function(cm, vim, helpers) { + var curStart = makeCursor(0, 0); + cm.setCursor(curStart); + helpers.doKeys('d', 'w'); + eq('word1 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(' ', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1 ' }); +testVim('dw_word', function(cm, vim, helpers) { + var curStart = makeCursor(0, 1); + cm.setCursor(curStart); + helpers.doKeys('d', 'w'); + eq(' word2', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1 ', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1 word2' }); +testVim('dw_only_word', function(cm, vim, helpers) { + // Test that if there is only 1 word left, dw deletes till the end of the + // line. + cm.setCursor(0, 1); + helpers.doKeys('d', 'w'); + eq(' ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1 ', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1 ' }); +testVim('dw_eol', function(cm, vim, helpers) { + // Assert that dw does not delete the newline if last word to delete is at end + // of line. + cm.setCursor(0, 1); + helpers.doKeys('d', 'w'); + eq(' \nword2', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\nword2' }); +testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) { + // Assert that dw does not delete the newline if last word to delete is at end + // of line and it is followed by multiple newlines. + cm.setCursor(0, 1); + helpers.doKeys('d', 'w'); + eq(' \n\nword2', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\n\nword2' }); +testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'w'); + eq(' \nword', cm.getValue()); +}, { value: '\n \nword' }); +testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'w'); + eq('word', cm.getValue()); +}, { value: '\nword' }); +testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'w'); + eq('\n', cm.getValue()); +}, { value: '\n\n' }); +testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'w'); + eq('\n \n', cm.getValue()); +}, { value: ' \n \n' }); +testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'w'); + eq('\n\n', cm.getValue()); +}, { value: ' \n\n' }); +testVim('dw_word_whitespace_word', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'w'); + eq('\n \nword2', cm.getValue()); +}, { value: 'word1\n \nword2'}) +testVim('dw_end_of_document', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('d', 'w'); + eq('\nab', cm.getValue()); +}, { value: '\nabc' }); +testVim('dw_repeat', function(cm, vim, helpers) { + // Assert that dw does delete newline if it should go to the next line, and + // that repeat works properly. + cm.setCursor(0, 1); + helpers.doKeys('d', '2', 'w'); + eq(' ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1\nword2', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\nword2' }); +testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'e'); + eq('\n\n', cm.getValue()); +}, { value: 'word\n\n' }); +testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(0, 3); + helpers.doKeys('d', 'e'); + eq('wor', cm.getValue()); +}, { value: 'word\n\n\n' }); +testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'e'); + eq('', cm.getValue()); +}, { value: ' \n\n\n' }); +testVim('de_end_of_document', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('d', 'e'); + eq('\nab', cm.getValue()); +}, { value: '\nabc' }); +testVim('db_empty_lines', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('d', 'b'); + eq('\n\n', cm.getValue()); +}, { value: '\n\n\n' }); +testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('d', 'b'); + eq('\nword', cm.getValue()); +}, { value: '\n\nword' }); +testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(2, 3); + helpers.doKeys('d', 'b'); + eq('\n\nd', cm.getValue()); +}, { value: '\n\nword' }); +testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('d', 'b'); + eq('', cm.getValue()); +}, { value: '\n \n' }); +testVim('db_start_of_document', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'b'); + eq('abc\n', cm.getValue()); +}, { value: 'abc\n' }); +testVim('dge_empty_lines', function(cm, vim, helpers) { + cm.setCursor(1, 0); + helpers.doKeys('d', 'g', 'e'); + // Note: In real VIM the result should be '', but it's not quite consistent, + // since 2 newlines are deleted. But in the similar case of word\n\n, only + // 1 newline is deleted. We'll diverge from VIM's behavior since it's much + // easier this way. + eq('\n', cm.getValue()); +}, { value: '\n\n' }); +testVim('dge_word_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(1, 0); + helpers.doKeys('d', 'g', 'e'); + eq('wor\n', cm.getValue()); +}, { value: 'word\n\n'}); +testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('d', 'g', 'e'); + eq('', cm.getValue()); +}, { value: '\n \n' }); +testVim('dge_start_of_document', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('d', 'g', 'e'); + eq('bc\n', cm.getValue()); +}, { value: 'abc\n' }); +testVim('d_inclusive', function(cm, vim, helpers) { + // Assert that when inclusive is set, the character the cursor is on gets + // deleted too. + var curStart = makeCursor(0, 1); + cm.setCursor(curStart); + helpers.doKeys('d', 'e'); + eq(' ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1 ' }); +testVim('d_reverse', function(cm, vim, helpers) { + // Test that deleting in reverse works. + cm.setCursor(1, 0); + helpers.doKeys('d', 'b'); + eq(' word2 ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1\n', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\nword2 ' }); +testVim('dd', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, + { line: 1, ch: 0 }); + var expectedLineCount = cm.lineCount() - 1; + helpers.doKeys('d', 'd'); + eq(expectedLineCount, cm.lineCount()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedBuffer, register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, lines[1].textStart); +}); +testVim('dd_prefix_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, + { line: 2, ch: 0 }); + var expectedLineCount = cm.lineCount() - 2; + helpers.doKeys('2', 'd', 'd'); + eq(expectedLineCount, cm.lineCount()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedBuffer, register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, lines[2].textStart); +}); +testVim('dd_motion_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, + { line: 2, ch: 0 }); + var expectedLineCount = cm.lineCount() - 2; + helpers.doKeys('d', '2', 'd'); + eq(expectedLineCount, cm.lineCount()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedBuffer, register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, lines[2].textStart); +}); +testVim('dd_multiply_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, + { line: 6, ch: 0 }); + var expectedLineCount = cm.lineCount() - 6; + helpers.doKeys('2', 'd', '3', 'd'); + eq(expectedLineCount, cm.lineCount()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedBuffer, register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, lines[6].textStart); +}); +testVim('dd_lastline', function(cm, vim, helpers) { + cm.setCursor(cm.lineCount(), 0); + var expectedLineCount = cm.lineCount() - 1; + helpers.doKeys('d', 'd'); + eq(expectedLineCount, cm.lineCount()); + helpers.assertCursorAt(cm.lineCount() - 1, 0); +}); +testVim('dd_only_line', function(cm, vim, helpers) { + cm.setCursor(0, 0); + var expectedRegister = cm.getValue() + "\n"; + helpers.doKeys('d','d'); + eq(1, cm.lineCount()); + eq('', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedRegister, register.toString()); +}, { value: "thisistheonlyline" }); +// Yank commands should behave the exact same as d commands, expect that nothing +// gets deleted. +testVim('yw_repeat', function(cm, vim, helpers) { + // Assert that yw does yank newline if it should go to the next line, and + // that repeat works properly. + var curStart = makeCursor(0, 1); + cm.setCursor(curStart); + helpers.doKeys('y', '2', 'w'); + eq(' word1\nword2', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1\nword2', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1\nword2' }); +testVim('yy_multiply_repeat', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, + { line: 6, ch: 0 }); + var expectedLineCount = cm.lineCount(); + helpers.doKeys('2', 'y', '3', 'y'); + eq(expectedLineCount, cm.lineCount()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedBuffer, register.toString()); + is(register.linewise); + eqPos(curStart, cm.getCursor()); +}); +// Change commands behave like d commands except that it also enters insert +// mode. In addition, when the change is linewise, an additional newline is +// inserted so that insert mode starts on that line. +testVim('cw', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('c', '2', 'w'); + eq(' word3', cm.getValue()); + helpers.assertCursorAt(0, 0); +}, { value: 'word1 word2 word3'}); +testVim('cw_repeat', function(cm, vim, helpers) { + // Assert that cw does delete newline if it should go to the next line, and + // that repeat works properly. + var curStart = makeCursor(0, 1); + cm.setCursor(curStart); + helpers.doKeys('c', '2', 'w'); + eq(' ', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word1\nword2', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); + eq('vim-insert', cm.getOption('keyMap')); +}, { value: ' word1\nword2' }); +testVim('cc_multiply_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, + { line: 6, ch: 0 }); + var expectedLineCount = cm.lineCount() - 5; + helpers.doKeys('2', 'c', '3', 'c'); + eq(expectedLineCount, cm.lineCount()); + var register = helpers.getRegisterController().getRegister(); + eq(expectedBuffer, register.toString()); + is(register.linewise); + eq('vim-insert', cm.getOption('keyMap')); +}); +testVim('cc_append', function(cm, vim, helpers) { + var expectedLineCount = cm.lineCount(); + cm.setCursor(cm.lastLine(), 0); + helpers.doKeys('c', 'c'); + eq(expectedLineCount, cm.lineCount()); +}); +testVim('c_visual_block', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'c'); + var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); + replacement.pop(); + cm.replaceSelections(replacement); + eq('1hello\n5hello\nahellofg', cm.getValue()); + helpers.doKeys(''); + cm.setCursor(2, 3); + helpers.doKeys('', '2', 'k', 'h', 'C'); + replacement = new Array(cm.listSelections().length+1).join('world ').split(' '); + replacement.pop(); + cm.replaceSelections(replacement); + eq('1hworld\n5hworld\nahworld', cm.getValue()); +}, {value: '1234\n5678\nabcdefg'}); +testVim('c_visual_block_replay', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('', '2', 'j', 'l', 'c'); + var replacement = new Array(cm.listSelections().length+1).join('fo ').split(' '); + replacement.pop(); + cm.replaceSelections(replacement); + eq('1fo4\n5fo8\nafodefg', cm.getValue()); + helpers.doKeys(''); + cm.setCursor(0, 0); + helpers.doKeys('.'); + eq('foo4\nfoo8\nfoodefg', cm.getValue()); +}, {value: '1234\n5678\nabcdefg'}); + +// Swapcase commands edit in place and do not modify registers. +testVim('g~w_repeat', function(cm, vim, helpers) { + // Assert that dw does delete newline if it should go to the next line, and + // that repeat works properly. + var curStart = makeCursor(0, 1); + cm.setCursor(curStart); + helpers.doKeys('g', '~', '2', 'w'); + eq(' WORD1\nWORD2', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); +}, { value: ' word1\nword2' }); +testVim('g~g~', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + var expectedLineCount = cm.lineCount(); + var expectedValue = cm.getValue().toUpperCase(); + helpers.doKeys('2', 'g', '~', '3', 'g', '~'); + eq(expectedValue, cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + eqPos({line: curStart.line, ch:0}, cm.getCursor()); +}, { value: ' word1\nword2\nword3\nword4\nword5\nword6' }); +testVim('gu_and_gU', function(cm, vim, helpers) { + var curStart = makeCursor(0, 7); + var value = cm.getValue(); + cm.setCursor(curStart); + helpers.doKeys('2', 'g', 'U', 'w'); + eq(cm.getValue(), 'wa wb xX WC wd'); + eqPos(curStart, cm.getCursor()); + helpers.doKeys('2', 'g', 'u', 'w'); + eq(cm.getValue(), value); + + helpers.doKeys('2', 'g', 'U', 'B'); + eq(cm.getValue(), 'wa WB Xx wc wd'); + eqPos(makeCursor(0, 3), cm.getCursor()); + + cm.setCursor(makeCursor(0, 4)); + helpers.doKeys('g', 'u', 'i', 'w'); + eq(cm.getValue(), 'wa wb Xx wc wd'); + eqPos(makeCursor(0, 3), cm.getCursor()); + + // TODO: support gUgU guu + // eqPos(makeCursor(0, 0), cm.getCursor()); + + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); +}, { value: 'wa wb xx wc wd' }); +testVim('visual_block_~', function(cm, vim, helpers) { + cm.setCursor(1, 1); + helpers.doKeys('', 'l', 'l', 'j', '~'); + helpers.assertCursorAt(1, 1); + eq('hello\nwoRLd\naBCDe', cm.getValue()); + cm.setCursor(2, 0); + helpers.doKeys('v', 'l', 'l', '~'); + helpers.assertCursorAt(2, 0); + eq('hello\nwoRLd\nAbcDe', cm.getValue()); +},{value: 'hello\nwOrld\nabcde' }); +testVim('._swapCase_visualBlock', function(cm, vim, helpers) { + helpers.doKeys('', 'j', 'j', 'l', '~'); + cm.setCursor(0, 3); + helpers.doKeys('.'); + eq('HelLO\nWorLd\nAbcdE', cm.getValue()); +},{value: 'hEllo\nwOrlD\naBcDe' }); +testVim('._delete_visualBlock', function(cm, vim, helpers) { + helpers.doKeys('', 'j', 'x'); + eq('ive\ne\nsome\nsugar', cm.getValue()); + helpers.doKeys('.'); + eq('ve\n\nsome\nsugar', cm.getValue()); + helpers.doKeys('j', 'j', '.'); + eq('ve\n\nome\nugar', cm.getValue()); + helpers.doKeys('u', '', '.'); + eq('ve\n\nme\ngar', cm.getValue()); +},{value: 'give\nme\nsome\nsugar' }); +testVim('>{motion}', function(cm, vim, helpers) { + cm.setCursor(1, 3); + var expectedLineCount = cm.lineCount(); + var expectedValue = ' word1\n word2\nword3 '; + helpers.doKeys('>', 'k'); + eq(expectedValue, cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 3); +}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); +testVim('>>', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedLineCount = cm.lineCount(); + var expectedValue = ' word1\n word2\nword3 '; + helpers.doKeys('2', '>', '>'); + eq(expectedValue, cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 3); +}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); +testVim('<{motion}', function(cm, vim, helpers) { + cm.setCursor(1, 3); + var expectedLineCount = cm.lineCount(); + var expectedValue = ' word1\nword2\nword3 '; + helpers.doKeys('<', 'k'); + eq(expectedValue, cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); +testVim('<<', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedLineCount = cm.lineCount(); + var expectedValue = ' word1\nword2\nword3 '; + helpers.doKeys('2', '<', '<'); + eq(expectedValue, cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); + +// Edit tests +function testEdit(name, before, pos, edit, after) { + return testVim(name, function(cm, vim, helpers) { + var ch = before.search(pos) + var line = before.substring(0, ch).split('\n').length - 1; + if (line) { + ch = before.substring(0, ch).split('\n').pop().length; + } + cm.setCursor(line, ch); + helpers.doKeys.apply(this, edit.split('')); + eq(after, cm.getValue()); + }, {value: before}); } -//Define the tests +// These Delete tests effectively cover word-wise Change, Visual & Yank. +// Tabs are used as differentiated whitespace to catch edge cases. +// Normal word: +testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz'); +testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz'); +testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz'); +testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz'); +testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz'); +testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz'); +testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz'); +testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz'); +testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz'); +testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz'); +testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t'); +testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo'); +testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.'); +testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.'); +// Big word: +testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz'); +testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz'); +testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz'); +testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz'); +testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz'); +testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz'); +testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz'); +testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz'); +testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz'); +testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz'); +testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t'); +testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo'); +testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t'); +testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo'); +// Deleting text objects +// Open and close on same line +testEdit('di(_open_spc', 'foo (bAr) baz', /\(/, 'di(', 'foo () baz'); +testEdit('di)_open_spc', 'foo (bAr) baz', /\(/, 'di)', 'foo () baz'); +testEdit('dib_open_spc', 'foo (bAr) baz', /\(/, 'dib', 'foo () baz'); +testEdit('da(_open_spc', 'foo (bAr) baz', /\(/, 'da(', 'foo baz'); +testEdit('da)_open_spc', 'foo (bAr) baz', /\(/, 'da)', 'foo baz'); -initKeyCodeByFuncKey(); +testEdit('di(_middle_spc', 'foo (bAr) baz', /A/, 'di(', 'foo () baz'); +testEdit('di)_middle_spc', 'foo (bAr) baz', /A/, 'di)', 'foo () baz'); +testEdit('da(_middle_spc', 'foo (bAr) baz', /A/, 'da(', 'foo baz'); +testEdit('da)_middle_spc', 'foo (bAr) baz', /A/, 'da)', 'foo baz'); -addTest("Insert text", "02", "2", function() { - var text = "A very intelligent turtle\nFound programming UNIX a hurdle"; - initEditor(""); - sendKeys("i", text, "Esc"); - assertContent(text); - sendKeys("Esc", "Esc"); - assertContent(text); +testEdit('di(_close_spc', 'foo (bAr) baz', /\)/, 'di(', 'foo () baz'); +testEdit('di)_close_spc', 'foo (bAr) baz', /\)/, 'di)', 'foo () baz'); +testEdit('da(_close_spc', 'foo (bAr) baz', /\)/, 'da(', 'foo baz'); +testEdit('da)_close_spc', 'foo (bAr) baz', /\)/, 'da)', 'foo baz'); + +// delete around and inner b. +testEdit('dab_on_(_should_delete_around_()block', 'o( in(abc) )', /\(a/, 'dab', 'o( in )'); + +// delete around and inner B. +testEdit('daB_on_{_should_delete_around_{}block', 'o{ in{abc} }', /{a/, 'daB', 'o{ in }'); +testEdit('diB_on_{_should_delete_inner_{}block', 'o{ in{abc} }', /{a/, 'diB', 'o{ in{} }'); + +testEdit('da{_on_{_should_delete_inner_block', 'o{ in{abc} }', /{a/, 'da{', 'o{ in }'); +testEdit('di[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'di[', 'foo (bAr) baz'); +testEdit('di[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'di[', 'foo (bAr) baz'); +testEdit('da[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'da[', 'foo (bAr) baz'); +testEdit('da[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'da[', 'foo (bAr) baz'); +testMotion('di(_outside_should_stay', ['d', 'i', '('], { line: 0, ch: 0}, { line: 0, ch: 0}); + +// Open and close on different lines, equally indented +testEdit('di{_middle_spc', 'a{\n\tbar\n}b', /r/, 'di{', 'a{}b'); +testEdit('di}_middle_spc', 'a{\n\tbar\n}b', /r/, 'di}', 'a{}b'); +testEdit('da{_middle_spc', 'a{\n\tbar\n}b', /r/, 'da{', 'ab'); +testEdit('da}_middle_spc', 'a{\n\tbar\n}b', /r/, 'da}', 'ab'); +testEdit('daB_middle_spc', 'a{\n\tbar\n}b', /r/, 'daB', 'ab'); + +// open and close on diff lines, open indented less than close +testEdit('di{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di{', 'a{}b'); +testEdit('di}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di}', 'a{}b'); +testEdit('da{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da{', 'ab'); +testEdit('da}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da}', 'ab'); + +// open and close on diff lines, open indented more than close +testEdit('di[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di[', 'a\t[]b'); +testEdit('di]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di]', 'a\t[]b'); +testEdit('da[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da[', 'a\tb'); +testEdit('da]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da]', 'a\tb'); + +function testSelection(name, before, pos, keys, sel) { + return testVim(name, function(cm, vim, helpers) { + var ch = before.search(pos) + var line = before.substring(0, ch).split('\n').length - 1; + if (line) { + ch = before.substring(0, ch).split('\n').pop().length; + } + cm.setCursor(line, ch); + helpers.doKeys.apply(this, keys.split('')); + eq(sel, cm.getSelection()); + }, {value: before}); +} +testSelection('viw_middle_spc', 'foo \tbAr\t baz', /A/, 'viw', 'bAr'); +testSelection('vaw_middle_spc', 'foo \tbAr\t baz', /A/, 'vaw', 'bAr\t '); +testSelection('viw_middle_punct', 'foo \tbAr,\t baz', /A/, 'viw', 'bAr'); +testSelection('vaW_middle_punct', 'foo \tbAr,\t baz', /A/, 'vaW', 'bAr,\t '); +testSelection('viw_start_spc', 'foo \tbAr\t baz', /b/, 'viw', 'bAr'); +testSelection('viw_end_spc', 'foo \tbAr\t baz', /r/, 'viw', 'bAr'); +testSelection('viw_eol', 'foo \tbAr', /r/, 'viw', 'bAr'); +testSelection('vi{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'vi{', '\n\tbar\n\t'); +testSelection('va{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'va{', '{\n\tbar\n\t}'); + +testVim('mouse_select', function(cm, vim, helpers) { + cm.setSelection(Pos(0, 2), Pos(0, 4), {origin: '*mouse'}); + is(cm.state.vim.visualMode); + is(!cm.state.vim.visualLine); + is(!cm.state.vim.visualBlock); + helpers.doKeys(''); + is(!cm.somethingSelected()); + helpers.doKeys('g', 'v'); + eq('cd', cm.getSelection()); +}, {value: 'abcdef'}); + +// Operator-motion tests +testVim('D', function(cm, vim, helpers) { + cm.setCursor(0, 3); + helpers.doKeys('D'); + eq(' wo\nword2\n word3', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('rd1', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 3); +}, { value: ' word1\nword2\n word3' }); +testVim('C', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + helpers.doKeys('C'); + eq(' wo\nword2\n word3', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('rd1', register.toString()); + is(!register.linewise); + eqPos(curStart, cm.getCursor()); + eq('vim-insert', cm.getOption('keyMap')); +}, { value: ' word1\nword2\n word3' }); +testVim('Y', function(cm, vim, helpers) { + var curStart = makeCursor(0, 3); + cm.setCursor(curStart); + helpers.doKeys('Y'); + eq(' word1\nword2\n word3', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('rd1', register.toString()); + is(!register.linewise); + helpers.assertCursorAt(0, 3); +}, { value: ' word1\nword2\n word3' }); +testVim('~', function(cm, vim, helpers) { + helpers.doKeys('3', '~'); + eq('ABCdefg', cm.getValue()); + helpers.assertCursorAt(0, 3); +}, { value: 'abcdefg' }); + +// Action tests +testVim('ctrl-a', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys(''); + eq('-9', cm.getValue()); + helpers.assertCursorAt(0, 1); + helpers.doKeys('2',''); + eq('-7', cm.getValue()); +}, {value: '-10'}); +testVim('ctrl-x', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys(''); + eq('-1', cm.getValue()); + helpers.assertCursorAt(0, 1); + helpers.doKeys('2',''); + eq('-3', cm.getValue()); +}, {value: '0'}); +testVim('/ search forward', function(cm, vim, helpers) { + forEach(['', ''], function(key) { + cm.setCursor(0, 0); + helpers.doKeys(key); + helpers.assertCursorAt(0, 5); + helpers.doKeys('l'); + helpers.doKeys(key); + helpers.assertCursorAt(0, 10); + cm.setCursor(0, 11); + helpers.doKeys(key); + helpers.assertCursorAt(0, 11); + }); +}, {value: '__jmp1 jmp2 jmp'}); +testVim('a', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('a'); + helpers.assertCursorAt(0, 2); + eq('vim-insert', cm.getOption('keyMap')); +}); +testVim('a_eol', function(cm, vim, helpers) { + cm.setCursor(0, lines[0].length - 1); + helpers.doKeys('a'); + helpers.assertCursorAt(0, lines[0].length); + eq('vim-insert', cm.getOption('keyMap')); +}); +testVim('a_endOfSelectedArea', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('v', 'j', 'l'); + helpers.doKeys('A'); + helpers.assertCursorAt(1, 2); + eq('vim-insert', cm.getOption('keyMap')); +}, {value: 'foo\nbar'}); +testVim('i', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('i'); + helpers.assertCursorAt(0, 1); + eq('vim-insert', cm.getOption('keyMap')); +}); +testVim('i_repeat', function(cm, vim, helpers) { + helpers.doKeys('3', 'i'); + cm.replaceRange('test', cm.getCursor()); + helpers.doKeys(''); + eq('testtesttest', cm.getValue()); + helpers.assertCursorAt(0, 11); +}, { value: '' }); +testVim('i_repeat_delete', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('2', 'i'); + cm.replaceRange('z', cm.getCursor()); + helpers.doInsertModeKeys('Backspace', 'Backspace'); + helpers.doKeys(''); + eq('abe', cm.getValue()); + helpers.assertCursorAt(0, 1); +}, { value: 'abcde' }); +testVim('A', function(cm, vim, helpers) { + helpers.doKeys('A'); + helpers.assertCursorAt(0, lines[0].length); + eq('vim-insert', cm.getOption('keyMap')); +}); +testVim('A_visual_block', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('', '2', 'j', 'l', 'l', 'A'); + var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); + replacement.pop(); + cm.replaceSelections(replacement); + eq('testhello\nmehello\npleahellose', cm.getValue()); + helpers.doKeys(''); + cm.setCursor(0, 0); + helpers.doKeys('.'); + // TODO this doesn't work yet + // eq('teshellothello\nme hello hello\nplehelloahellose', cm.getValue()); +}, {value: 'test\nme\nplease'}); +testVim('I', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('I'); + helpers.assertCursorAt(0, lines[0].textStart); + eq('vim-insert', cm.getOption('keyMap')); +}); +testVim('I_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('3', 'I'); + cm.replaceRange('test', cm.getCursor()); + helpers.doKeys(''); + eq('testtesttestblah', cm.getValue()); + helpers.assertCursorAt(0, 11); +}, { value: 'blah' }); +testVim('I_visual_block', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', '2', 'j', 'l', 'l', 'I'); + var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); + replacement.pop(); + cm.replaceSelections(replacement); + eq('hellotest\nhellome\nhelloplease', cm.getValue()); +}, {value: 'test\nme\nplease'}); +testVim('o', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('o'); + eq('word1\n\nword2', cm.getValue()); + helpers.assertCursorAt(1, 0); + eq('vim-insert', cm.getOption('keyMap')); +}, { value: 'word1\nword2' }); +testVim('o_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('3', 'o'); + cm.replaceRange('test', cm.getCursor()); + helpers.doKeys(''); + eq('\ntest\ntest\ntest', cm.getValue()); + helpers.assertCursorAt(3, 3); +}, { value: '' }); +testVim('O', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('O'); + eq('\nword1\nword2', cm.getValue()); + helpers.assertCursorAt(0, 0); + eq('vim-insert', cm.getOption('keyMap')); +}, { value: 'word1\nword2' }); +testVim('J', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('J'); + var expectedValue = 'word1 word2\nword3\n word4'; + eq(expectedValue, cm.getValue()); + helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1); +}, { value: 'word1 \n word2\nword3\n word4' }); +testVim('J_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('3', 'J'); + var expectedValue = 'word1 word2 word3\n word4'; + eq(expectedValue, cm.getValue()); + helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1); +}, { value: 'word1 \n word2\nword3\n word4' }); +testVim('p', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); + helpers.doKeys('p'); + eq('__abc\ndef_', cm.getValue()); + helpers.assertCursorAt(1, 2); +}, { value: '___' }); +testVim('p_register', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); + helpers.doKeys('"', 'a', 'p'); + eq('__abc\ndef_', cm.getValue()); + helpers.assertCursorAt(1, 2); +}, { value: '___' }); +testVim('p_wrong_register', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); + helpers.doKeys('p'); + eq('___', cm.getValue()); + helpers.assertCursorAt(0, 1); +}, { value: '___' }); +testVim('p_line', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); + helpers.doKeys('2', 'p'); + eq('___\n a\nd\n a\nd', cm.getValue()); + helpers.assertCursorAt(1, 2); +}, { value: '___' }); +testVim('p_lastline', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().pushText('"', 'yank', ' a\nd', true); + helpers.doKeys('2', 'p'); + eq('___\n a\nd\n a\nd', cm.getValue()); + helpers.assertCursorAt(1, 2); +}, { value: '___' }); +testVim(']p_first_indent_is_smaller', function(cm, vim, helpers) { + helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); + helpers.doKeys(']', 'p'); + eq(' ___\n abc\n def', cm.getValue()); +}, { value: ' ___' }); +testVim(']p_first_indent_is_larger', function(cm, vim, helpers) { + helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); + helpers.doKeys(']', 'p'); + eq(' ___\n abc\ndef', cm.getValue()); +}, { value: ' ___' }); +testVim(']p_with_tab_indents', function(cm, vim, helpers) { + helpers.getRegisterController().pushText('"', 'yank', '\t\tabc\n\t\t\tdef\n', true); + helpers.doKeys(']', 'p'); + eq('\t___\n\tabc\n\t\tdef', cm.getValue()); +}, { value: '\t___', indentWithTabs: true}); +testVim(']p_with_spaces_translated_to_tabs', function(cm, vim, helpers) { + helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); + helpers.doKeys(']', 'p'); + eq('\t___\n\tabc\n\t\tdef', cm.getValue()); +}, { value: '\t___', indentWithTabs: true, tabSize: 2 }); +testVim('[p', function(cm, vim, helpers) { + helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); + helpers.doKeys('[', 'p'); + eq(' abc\n def\n ___', cm.getValue()); +}, { value: ' ___' }); +testVim('P', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); + helpers.doKeys('P'); + eq('_abc\ndef__', cm.getValue()); + helpers.assertCursorAt(1, 3); +}, { value: '___' }); +testVim('P_line', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); + helpers.doKeys('2', 'P'); + eq(' a\nd\n a\nd\n___', cm.getValue()); + helpers.assertCursorAt(0, 2); +}, { value: '___' }); +testVim('r', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('3', 'r', 'u'); + eq('wuuuet\nanother', cm.getValue(),'3r failed'); + helpers.assertCursorAt(0, 3); + cm.setCursor(0, 4); + helpers.doKeys('v', 'j', 'h', 'r', ''); + eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed'); +}, { value: 'wordet\nanother' }); +testVim('r_visual_block', function(cm, vim, helpers) { + cm.setCursor(2, 3); + helpers.doKeys('', 'k', 'k', 'h', 'h', 'r', 'l'); + eq('1lll\n5lll\nalllefg', cm.getValue()); + helpers.doKeys('', 'l', 'j', 'r', ''); + eq('1 l\n5 l\nalllefg', cm.getValue()); + cm.setCursor(2, 0); + helpers.doKeys('o'); + helpers.doKeys(''); + cm.replaceRange('\t\t', cm.getCursor()); + helpers.doKeys('', 'h', 'h', 'r', 'r'); + eq('1 l\n5 l\nalllefg\nrrrrrrrr', cm.getValue()); +}, {value: '1234\n5678\nabcdefg'}); +testVim('R', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('R'); + helpers.assertCursorAt(0, 1); + eq('vim-replace', cm.getOption('keyMap')); + is(cm.state.overwrite, 'Setting overwrite state failed'); +}); +testVim('mark', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 't'); + cm.setCursor(0, 0); + helpers.doKeys('`', 't'); + helpers.assertCursorAt(2, 2); + cm.setCursor(2, 0); + cm.replaceRange(' h', cm.getCursor()); + cm.setCursor(0, 0); + helpers.doKeys('\'', 't'); + helpers.assertCursorAt(2, 3); +}); +testVim('jumpToMark_next', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 't'); + cm.setCursor(0, 0); + helpers.doKeys(']', '`'); + helpers.assertCursorAt(2, 2); + cm.setCursor(0, 0); + helpers.doKeys(']', '\''); + helpers.assertCursorAt(2, 0); +}); +testVim('jumpToMark_next_repeat', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(3, 2); + helpers.doKeys('m', 'b'); + cm.setCursor(4, 2); + helpers.doKeys('m', 'c'); + cm.setCursor(0, 0); + helpers.doKeys('2', ']', '`'); + helpers.assertCursorAt(3, 2); + cm.setCursor(0, 0); + helpers.doKeys('2', ']', '\''); + helpers.assertCursorAt(3, 1); +}); +testVim('jumpToMark_next_sameline', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 4); + helpers.doKeys('m', 'b'); + cm.setCursor(2, 2); + helpers.doKeys(']', '`'); + helpers.assertCursorAt(2, 4); +}); +testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('m', 'a'); + cm.setCursor(4, 0); + helpers.doKeys(']', '`'); + helpers.assertCursorAt(4, 0); +}); +testVim('jumpToMark_next_nomark', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys(']', '`'); + helpers.assertCursorAt(2, 2); + helpers.doKeys(']', '\''); + helpers.assertCursorAt(2, 0); +}); +testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(3, 4); + helpers.doKeys('m', 'b'); + cm.setCursor(2, 1); + helpers.doKeys(']', '\''); + helpers.assertCursorAt(3, 1); +}); +testVim('jumpToMark_next_action', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 't'); + cm.setCursor(0, 0); + helpers.doKeys('d', ']', '`'); + helpers.assertCursorAt(0, 0); + var actual = cm.getLine(0); + var expected = 'pop pop 0 1 2 3 4'; + eq(actual, expected, "Deleting while jumping to the next mark failed."); +}); +testVim('jumpToMark_next_line_action', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 't'); + cm.setCursor(0, 0); + helpers.doKeys('d', ']', '\''); + helpers.assertCursorAt(0, 1); + var actual = cm.getLine(0); + var expected = ' (a) [b] {c} ' + eq(actual, expected, "Deleting while jumping to the next mark line failed."); +}); +testVim('jumpToMark_prev', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 't'); + cm.setCursor(4, 0); + helpers.doKeys('[', '`'); + helpers.assertCursorAt(2, 2); + cm.setCursor(4, 0); + helpers.doKeys('[', '\''); + helpers.assertCursorAt(2, 0); +}); +testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(3, 2); + helpers.doKeys('m', 'b'); + cm.setCursor(4, 2); + helpers.doKeys('m', 'c'); + cm.setCursor(5, 0); + helpers.doKeys('2', '[', '`'); + helpers.assertCursorAt(3, 2); + cm.setCursor(5, 0); + helpers.doKeys('2', '[', '\''); + helpers.assertCursorAt(3, 1); +}); +testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 4); + helpers.doKeys('m', 'b'); + cm.setCursor(2, 2); + helpers.doKeys('[', '`'); + helpers.assertCursorAt(2, 0); +}); +testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) { + cm.setCursor(4, 4); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 0); + helpers.doKeys('[', '`'); + helpers.assertCursorAt(2, 0); +}); +testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('[', '`'); + helpers.assertCursorAt(2, 2); + helpers.doKeys('[', '\''); + helpers.assertCursorAt(2, 0); +}); +testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) { + cm.setCursor(2, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(3, 4); + helpers.doKeys('m', 'b'); + cm.setCursor(3, 6); + helpers.doKeys('[', '\''); + helpers.assertCursorAt(2, 0); +}); +testVim('delmark_single', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('m', 't'); + helpers.doEx('delmarks t'); + cm.setCursor(0, 0); + helpers.doKeys('`', 't'); + helpers.assertCursorAt(0, 0); +}); +testVim('delmark_range', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 2); + helpers.doKeys('m', 'b'); + cm.setCursor(3, 2); + helpers.doKeys('m', 'c'); + cm.setCursor(4, 2); + helpers.doKeys('m', 'd'); + cm.setCursor(5, 2); + helpers.doKeys('m', 'e'); + helpers.doEx('delmarks b-d'); + cm.setCursor(0, 0); + helpers.doKeys('`', 'a'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'b'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'c'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'd'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'e'); + helpers.assertCursorAt(5, 2); +}); +testVim('delmark_multi', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 2); + helpers.doKeys('m', 'b'); + cm.setCursor(3, 2); + helpers.doKeys('m', 'c'); + cm.setCursor(4, 2); + helpers.doKeys('m', 'd'); + cm.setCursor(5, 2); + helpers.doKeys('m', 'e'); + helpers.doEx('delmarks bcd'); + cm.setCursor(0, 0); + helpers.doKeys('`', 'a'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'b'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'c'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'd'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'e'); + helpers.assertCursorAt(5, 2); +}); +testVim('delmark_multi_space', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 2); + helpers.doKeys('m', 'b'); + cm.setCursor(3, 2); + helpers.doKeys('m', 'c'); + cm.setCursor(4, 2); + helpers.doKeys('m', 'd'); + cm.setCursor(5, 2); + helpers.doKeys('m', 'e'); + helpers.doEx('delmarks b c d'); + cm.setCursor(0, 0); + helpers.doKeys('`', 'a'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'b'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'c'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'd'); + helpers.assertCursorAt(1, 2); + helpers.doKeys('`', 'e'); + helpers.assertCursorAt(5, 2); +}); +testVim('delmark_all', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('m', 'a'); + cm.setCursor(2, 2); + helpers.doKeys('m', 'b'); + cm.setCursor(3, 2); + helpers.doKeys('m', 'c'); + cm.setCursor(4, 2); + helpers.doKeys('m', 'd'); + cm.setCursor(5, 2); + helpers.doKeys('m', 'e'); + helpers.doEx('delmarks a b-de'); + cm.setCursor(0, 0); + helpers.doKeys('`', 'a'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('`', 'b'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('`', 'c'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('`', 'd'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('`', 'e'); + helpers.assertCursorAt(0, 0); +}); +testVim('visual', function(cm, vim, helpers) { + helpers.doKeys('l', 'v', 'l', 'l'); + helpers.assertCursorAt(0, 4); + eqPos(makeCursor(0, 1), cm.getCursor('anchor')); + helpers.doKeys('d'); + eq('15', cm.getValue()); +}, { value: '12345' }); +testVim('visual_exit', function(cm, vim, helpers) { + helpers.doKeys('', 'l', 'j', 'j', ''); + eqPos(cm.getCursor('anchor'), cm.getCursor('head')); + eq(vim.visualMode, false); +}, { value: 'hello\nworld\nfoo' }); +testVim('visual_line', function(cm, vim, helpers) { + helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd'); + eq(' 4\n 5', cm.getValue()); +}, { value: ' 1\n 2\n 3\n 4\n 5' }); +testVim('visual_block', function(cm, vim, helpers) { + // test the block selection with lines of different length + // i.e. extending the selection + // till the end of the longest line. + helpers.doKeys('', 'l', 'j', 'j', '6', 'l', 'd'); + helpers.doKeys('d', 'd', 'd', 'd'); + eq('', cm.getValue()); + // check for left side selection in case + // of moving up to a shorter line. + cm.replaceRange('hello world\n{\nthis is\nsparta!', cm.getCursor()); + cm.setCursor(3, 4); + helpers.doKeys('', 'l', 'k', 'k', 'd'); + eq('hello world\n{\ntis\nsa!', cm.getValue()); + cm.replaceRange('12345\n67891\nabcde', {line: 0, ch: 0}, {line: cm.lastLine(), ch: 6}); + cm.setCursor(1, 2); + helpers.doKeys('', '2', 'l', 'k'); + // circle around the anchor + // and check the selections + var selections = cm.getSelections(); + eq('345891', selections.join('')); + helpers.doKeys('4', 'h'); + selections = cm.getSelections(); + eq('123678', selections.join('')); + helpers.doKeys('j', 'j'); + selections = cm.getSelections(); + eq('678abc', selections.join('')); + helpers.doKeys('4', 'l'); + selections = cm.getSelections(); + eq('891cde', selections.join('')); + // switch between visual modes + cm.setCursor(1, 1); + // blockwise to characterwise visual + helpers.doKeys('', 'j', 'l', 'v'); + selections = cm.getSelections(); + eq('7891\nabc', selections.join('')); + // characterwise to blockwise + helpers.doKeys(''); + selections = cm.getSelections(); + eq('78bc', selections.join('')); + // blockwise to linewise visual + helpers.doKeys('V'); + selections = cm.getSelections(); + eq('67891\nabcde', selections.join('')); +}, {value: '1234\n5678\nabcdefg'}); +testVim('visual_block_crossing_short_line', function(cm, vim, helpers) { + // visual block with long and short lines + cm.setCursor(0, 3); + helpers.doKeys('', 'j', 'j', 'j'); + var selections = cm.getSelections().join(); + eq('4,,d,b', selections); + helpers.doKeys('3', 'k'); + selections = cm.getSelections().join(); + eq('4', selections); + helpers.doKeys('5', 'j', 'k'); + selections = cm.getSelections().join(""); + eq(10, selections.length); +}, {value: '123456\n78\nabcdefg\nfoobar\n}\n'}); +testVim('visual_block_curPos_on_exit', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', '3' , 'l', ''); + eqPos(makeCursor(0, 3), cm.getCursor()); + helpers.doKeys('h', '', '2' , 'j' ,'3' , 'l'); + eq(cm.getSelections().join(), "3456,,cdef"); + helpers.doKeys('4' , 'h'); + eq(cm.getSelections().join(), "23,8,bc"); + helpers.doKeys('2' , 'l'); + eq(cm.getSelections().join(), "34,,cd"); +}, {value: '123456\n78\nabcdefg\nfoobar'}); + +testVim('visual_marks', function(cm, vim, helpers) { + helpers.doKeys('l', 'v', 'l', 'l', 'j', 'j', 'v'); + // Test visual mode marks + cm.setCursor(2, 1); + helpers.doKeys('\'', '<'); + helpers.assertCursorAt(0, 1); + helpers.doKeys('\'', '>'); + helpers.assertCursorAt(2, 0); +}); +testVim('visual_join', function(cm, vim, helpers) { + helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J'); + eq(' 1 2 3\n 4\n 5', cm.getValue()); + is(!vim.visualMode); +}, { value: ' 1\n 2\n 3\n 4\n 5' }); +testVim('visual_blank', function(cm, vim, helpers) { + helpers.doKeys('v', 'k'); + eq(vim.visualMode, true); +}, { value: '\n' }); +testVim('reselect_visual', function(cm, vim, helpers) { + helpers.doKeys('l', 'v', 'l', 'l', 'l', 'y', 'g', 'v'); + helpers.assertCursorAt(0, 5); + eqPos(makeCursor(0, 1), cm.getCursor('anchor')); + helpers.doKeys('v'); + cm.setCursor(1, 0); + helpers.doKeys('v', 'l', 'l', 'p'); + eq('123456\n2345\nbar', cm.getValue()); + cm.setCursor(0, 0); + helpers.doKeys('g', 'v'); + // here the fake cursor is at (1, 3) + helpers.assertCursorAt(1, 4); + eqPos(makeCursor(1, 0), cm.getCursor('anchor')); + helpers.doKeys('v'); + cm.setCursor(2, 0); + helpers.doKeys('v', 'l', 'l', 'g', 'v'); + helpers.assertCursorAt(1, 4); + eqPos(makeCursor(1, 0), cm.getCursor('anchor')); + helpers.doKeys('g', 'v'); + helpers.assertCursorAt(2, 3); + eqPos(makeCursor(2, 0), cm.getCursor('anchor')); + eq('123456\n2345\nbar', cm.getValue()); +}, { value: '123456\nfoo\nbar' }); +testVim('reselect_visual_line', function(cm, vim, helpers) { + helpers.doKeys('l', 'V', 'j', 'j', 'V', 'g', 'v', 'd'); + eq('foo\nand\nbar', cm.getValue()); + cm.setCursor(1, 0); + helpers.doKeys('V', 'y', 'j'); + helpers.doKeys('V', 'p' , 'g', 'v', 'd'); + eq('foo\nand', cm.getValue()); +}, { value: 'hello\nthis\nis\nfoo\nand\nbar' }); +testVim('reselect_visual_block', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('', 'k', 'h', ''); + cm.setCursor(2, 1); + helpers.doKeys('v', 'l', 'g', 'v'); + helpers.assertCursorAt(0, 1); + // Ensure selection is done with visual block mode rather than one + // continuous range. + eq(cm.getSelections().join(''), '23oo') + helpers.doKeys('g', 'v'); + helpers.assertCursorAt(2, 3); + // Ensure selection of deleted range + cm.setCursor(1, 1); + helpers.doKeys('v', '', 'j', 'd', 'g', 'v'); + eq(cm.getSelections().join(''), 'or'); +}, { value: '123456\nfoo\nbar' }); +testVim('s_normal', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('s'); + helpers.doKeys(''); + eq('ac', cm.getValue()); +}, { value: 'abc'}); +testVim('s_visual', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('v', 's'); + helpers.doKeys(''); + helpers.assertCursorAt(0, 0); + eq('ac', cm.getValue()); +}, { value: 'abc'}); +testVim('o_visual', function(cm, vim, helpers) { + cm.setCursor(0,0); + helpers.doKeys('v','l','l','l','o'); + helpers.assertCursorAt(0,0); + helpers.doKeys('v','v','j','j','j','o'); + helpers.assertCursorAt(0,0); + helpers.doKeys('O'); + helpers.doKeys('l','l') + helpers.assertCursorAt(3, 3); + helpers.doKeys('d'); + eq('p',cm.getValue()); +}, { value: 'abcd\nefgh\nijkl\nmnop'}); +testVim('o_visual_block', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('','3','j','l','l', 'o'); + helpers.assertCursorAt(0, 1); + helpers.doKeys('O'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('o'); + helpers.assertCursorAt(3, 1); +}, { value: 'abcd\nefgh\nijkl\nmnop'}); +testVim('changeCase_visual', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('v', 'l', 'l'); + helpers.doKeys('U'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('v', 'l', 'l'); + helpers.doKeys('u'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('l', 'l', 'l', '.'); + helpers.assertCursorAt(0, 3); + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', 'v', 'j', 'U', 'q'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('j', '@', 'a'); + helpers.assertCursorAt(1, 0); + cm.setCursor(3, 0); + helpers.doKeys('V', 'U', 'j', '.'); + eq('ABCDEF\nGHIJKL\nMnopq\nSHORT LINE\nLONG LINE OF TEXT', cm.getValue()); +}, { value: 'abcdef\nghijkl\nmnopq\nshort line\nlong line of text'}); +testVim('changeCase_visual_block', function(cm, vim, helpers) { + cm.setCursor(2, 1); + helpers.doKeys('', 'k', 'k', 'h', 'U'); + eq('ABcdef\nGHijkl\nMNopq\nfoo', cm.getValue()); + cm.setCursor(0, 2); + helpers.doKeys('.'); + eq('ABCDef\nGHIJkl\nMNOPq\nfoo', cm.getValue()); + // check when last line is shorter. + cm.setCursor(2, 2); + helpers.doKeys('.'); + eq('ABCDef\nGHIJkl\nMNOPq\nfoO', cm.getValue()); +}, { value: 'abcdef\nghijkl\nmnopq\nfoo'}); +testVim('visual_paste', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('v', 'l', 'l', 'y', 'j', 'v', 'l', 'p'); + helpers.assertCursorAt(1, 5); + eq('this is a\nunithitest for visual paste', cm.getValue()); + cm.setCursor(0, 0); + // in case of pasting whole line + helpers.doKeys('y', 'y'); + cm.setCursor(1, 6); + helpers.doKeys('v', 'l', 'l', 'l', 'p'); + helpers.assertCursorAt(2, 0); + eq('this is a\nunithi\nthis is a\n for visual paste', cm.getValue()); +}, { value: 'this is a\nunit test for visual paste'}); + +// This checks the contents of the register used to paste the text +testVim('v_paste_from_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('"', 'a', 'y', 'w'); + cm.setCursor(1, 0); + helpers.doKeys('v', 'p'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+register/.test(text)); + }); +}, { value: 'register contents\nare not erased'}); +testVim('S_normal', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('j', 'S'); + helpers.doKeys(''); + helpers.assertCursorAt(1, 0); + eq('aa\n\ncc', cm.getValue()); +}, { value: 'aa\nbb\ncc'}); +testVim('blockwise_paste', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', '3', 'j', 'l', 'y'); + cm.setCursor(0, 2); + // paste one char after the current cursor position + helpers.doKeys('p'); + eq('helhelo\nworwold\nfoofo\nbarba', cm.getValue()); + cm.setCursor(0, 0); + helpers.doKeys('v', '4', 'l', 'y'); + cm.setCursor(0, 0); + helpers.doKeys('', '3', 'j', 'p'); + eq('helheelhelo\norwold\noofo\narba', cm.getValue()); +}, { value: 'hello\nworld\nfoo\nbar'}); +testVim('blockwise_paste_long/short_line', function(cm, vim, helpers) { + // extend short lines in case of different line lengths. + cm.setCursor(0, 0); + helpers.doKeys('', 'j', 'j', 'y'); + cm.setCursor(0, 3); + helpers.doKeys('p'); + eq('hellho\nfoo f\nbar b', cm.getValue()); +}, { value: 'hello\nfoo\nbar'}); +testVim('blockwise_paste_cut_paste', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', '2', 'j', 'x'); + cm.setCursor(0, 0); + helpers.doKeys('P'); + eq('cut\nand\npaste\nme', cm.getValue()); +}, { value: 'cut\nand\npaste\nme'}); +testVim('blockwise_paste_from_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', '2', 'j', '"', 'a', 'y'); + cm.setCursor(0, 3); + helpers.doKeys('"', 'a', 'p'); + eq('foobfar\nhellho\nworlwd', cm.getValue()); +}, { value: 'foobar\nhello\nworld'}); +testVim('blockwise_paste_last_line', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', '2', 'j', 'l', 'y'); + cm.setCursor(3, 0); + helpers.doKeys('p'); + eq('cut\nand\npaste\nmcue\n an\n pa', cm.getValue()); +}, { value: 'cut\nand\npaste\nme'}); + +testVim('S_visual', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('v', 'j', 'S'); + helpers.doKeys(''); + helpers.assertCursorAt(0, 0); + eq('\ncc', cm.getValue()); +}, { value: 'aa\nbb\ncc'}); + +testVim('/ and n/N', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('match'); + helpers.doKeys('/'); + helpers.assertCursorAt(0, 11); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 6); + helpers.doKeys('N'); + helpers.assertCursorAt(0, 11); + + cm.setCursor(0, 0); + helpers.doKeys('2', '/'); + helpers.assertCursorAt(1, 6); +}, { value: 'match nope match \n nope Match' }); +testVim('/_case', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('Match'); + helpers.doKeys('/'); + helpers.assertCursorAt(1, 6); +}, { value: 'match nope match \n nope Match' }); +testVim('/_2_pcre', function(cm, vim, helpers) { + CodeMirror.Vim.setOption('pcre', true); + cm.openDialog = helpers.fakeOpenDialog('(word){2}'); + helpers.doKeys('/'); + helpers.assertCursorAt(1, 9); + helpers.doKeys('n'); + helpers.assertCursorAt(2, 1); +}, { value: 'word\n another wordword\n wordwordword\n' }); +testVim('/_2_nopcre', function(cm, vim, helpers) { + CodeMirror.Vim.setOption('pcre', false); + cm.openDialog = helpers.fakeOpenDialog('\\(word\\)\\{2}'); + helpers.doKeys('/'); + helpers.assertCursorAt(1, 9); + helpers.doKeys('n'); + helpers.assertCursorAt(2, 1); +}, { value: 'word\n another wordword\n wordwordword\n' }); +testVim('/_nongreedy', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('aa'); + helpers.doKeys('/'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 3); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 0); +}, { value: 'aaa aa \n a aa'}); +testVim('?_nongreedy', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('aa'); + helpers.doKeys('?'); + helpers.assertCursorAt(1, 3); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 0); +}, { value: 'aaa aa \n a aa'}); +testVim('/_greedy', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('a+'); + helpers.doKeys('/'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 1); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 3); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 0); +}, { value: 'aaa aa \n a aa'}); +testVim('?_greedy', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('a+'); + helpers.doKeys('?'); + helpers.assertCursorAt(1, 3); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 1); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 0); +}, { value: 'aaa aa \n a aa'}); +testVim('/_greedy_0_or_more', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('a*'); + helpers.doKeys('/'); + helpers.assertCursorAt(0, 3); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 5); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 0); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 1); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 0); +}, { value: 'aaa aa\n aa'}); +testVim('?_greedy_0_or_more', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('a*'); + helpers.doKeys('?'); + helpers.assertCursorAt(1, 1); + helpers.doKeys('n'); + helpers.assertCursorAt(1, 0); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 5); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 3); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 0); +}, { value: 'aaa aa\n aa'}); +testVim('? and n/N', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('match'); + helpers.doKeys('?'); + helpers.assertCursorAt(1, 6); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 11); + helpers.doKeys('N'); + helpers.assertCursorAt(1, 6); + + cm.setCursor(0, 0); + helpers.doKeys('2', '?'); + helpers.assertCursorAt(0, 11); +}, { value: 'match nope match \n nope Match' }); +testVim('*', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('*'); + helpers.assertCursorAt(0, 22); + + cm.setCursor(0, 9); + helpers.doKeys('2', '*'); + helpers.assertCursorAt(1, 8); +}, { value: 'nomatch match nomatch match \nnomatch Match' }); +testVim('*_no_word', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('*'); + helpers.assertCursorAt(0, 0); +}, { value: ' \n match \n' }); +testVim('*_symbol', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('*'); + helpers.assertCursorAt(1, 0); +}, { value: ' /}\n/} match \n' }); +testVim('#', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('#'); + helpers.assertCursorAt(1, 8); + + cm.setCursor(0, 9); + helpers.doKeys('2', '#'); + helpers.assertCursorAt(0, 22); +}, { value: 'nomatch match nomatch match \nnomatch Match' }); +testVim('*_seek', function(cm, vim, helpers) { + // Should skip over space and symbols. + cm.setCursor(0, 3); + helpers.doKeys('*'); + helpers.assertCursorAt(0, 22); +}, { value: ' := match nomatch match \nnomatch Match' }); +testVim('#', function(cm, vim, helpers) { + // Should skip over space and symbols. + cm.setCursor(0, 3); + helpers.doKeys('#'); + helpers.assertCursorAt(1, 8); +}, { value: ' := match nomatch match \nnomatch Match' }); +testVim('g*', function(cm, vim, helpers) { + cm.setCursor(0, 8); + helpers.doKeys('g', '*'); + helpers.assertCursorAt(0, 18); + cm.setCursor(0, 8); + helpers.doKeys('3', 'g', '*'); + helpers.assertCursorAt(1, 8); +}, { value: 'matches match alsoMatch\nmatchme matching' }); +testVim('g#', function(cm, vim, helpers) { + cm.setCursor(0, 8); + helpers.doKeys('g', '#'); + helpers.assertCursorAt(0, 0); + cm.setCursor(0, 8); + helpers.doKeys('3', 'g', '#'); + helpers.assertCursorAt(1, 0); +}, { value: 'matches match alsoMatch\nmatchme matching' }); +testVim('macro_insert', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', '0', 'i'); + cm.replaceRange('foo', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q', '@', 'a'); + eq('foofoo', cm.getValue()); +}, { value: ''}); +testVim('macro_insert_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', '$', 'a'); + cm.replaceRange('larry.', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('a'); + cm.replaceRange('curly.', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q'); + helpers.doKeys('a'); + cm.replaceRange('moe.', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('@', 'a'); + // At this point, the most recent edit should be the 2nd insert change + // inside the macro, i.e. "curly.". + helpers.doKeys('.'); + eq('larry.curly.moe.larry.curly.curly.', cm.getValue()); +}, { value: ''}); +testVim('macro_space', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('', ''); + helpers.assertCursorAt(0, 2); + helpers.doKeys('q', 'a', '', '', 'q'); + helpers.assertCursorAt(0, 4); + helpers.doKeys('@', 'a'); + helpers.assertCursorAt(0, 6); + helpers.doKeys('@', 'a'); + helpers.assertCursorAt(0, 8); +}, { value: 'one line of text.'}); +testVim('macro_t_search', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', 't', 'e', 'q'); + helpers.assertCursorAt(0, 1); + helpers.doKeys('l', '@', 'a'); + helpers.assertCursorAt(0, 6); + helpers.doKeys('l', ';'); + helpers.assertCursorAt(0, 12); +}, { value: 'one line of text.'}); +testVim('macro_f_search', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'b', 'f', 'e', 'q'); + helpers.assertCursorAt(0, 2); + helpers.doKeys('@', 'b'); + helpers.assertCursorAt(0, 7); + helpers.doKeys(';'); + helpers.assertCursorAt(0, 13); +}, { value: 'one line of text.'}); +testVim('macro_slash_search', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'c'); + cm.openDialog = helpers.fakeOpenDialog('e'); + helpers.doKeys('/', 'q'); + helpers.assertCursorAt(0, 2); + helpers.doKeys('@', 'c'); + helpers.assertCursorAt(0, 7); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 13); +}, { value: 'one line of text.'}); +testVim('macro_multislash_search', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'd'); + cm.openDialog = helpers.fakeOpenDialog('e'); + helpers.doKeys('/'); + cm.openDialog = helpers.fakeOpenDialog('t'); + helpers.doKeys('/', 'q'); + helpers.assertCursorAt(0, 12); + helpers.doKeys('@', 'd'); + helpers.assertCursorAt(0, 15); +}, { value: 'one line of text to rule them all.'}); +testVim('macro_parens', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'z', 'i'); + cm.replaceRange('(', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('e', 'a'); + cm.replaceRange(')', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q'); + helpers.doKeys('w', '@', 'z'); + helpers.doKeys('w', '@', 'z'); + eq('(see) (spot) (run)', cm.getValue()); +}, { value: 'see spot run'}); +testVim('macro_overwrite', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'z', '0', 'i'); + cm.replaceRange('I ', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q'); + helpers.doKeys('e'); + // Now replace the macro with something else. + helpers.doKeys('q', 'z', 'a'); + cm.replaceRange('.', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q'); + helpers.doKeys('e', '@', 'z'); + helpers.doKeys('e', '@', 'z'); + eq('I see. spot. run.', cm.getValue()); +}, { value: 'see spot run'}); +testVim('macro_search_f', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', 'f', ' '); + helpers.assertCursorAt(0,3); + helpers.doKeys('q', '0'); + helpers.assertCursorAt(0,0); + helpers.doKeys('@', 'a'); + helpers.assertCursorAt(0,3); +}, { value: 'The quick brown fox jumped over the lazy dog.'}); +testVim('macro_search_2f', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', '2', 'f', ' '); + helpers.assertCursorAt(0,9); + helpers.doKeys('q', '0'); + helpers.assertCursorAt(0,0); + helpers.doKeys('@', 'a'); + helpers.assertCursorAt(0,9); +}, { value: 'The quick brown fox jumped over the lazy dog.'}); +testVim('yank_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('"', 'a', 'y', 'y'); + helpers.doKeys('j', '"', 'b', 'y', 'y'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+foo/.test(text)); + is(/b\s+bar/.test(text)); + }); + helpers.doKeys(':'); +}, { value: 'foo\nbar'}); +testVim('yank_visual_block', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('', 'l', 'j', '"', 'a', 'y'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+oo\nar/.test(text)); + }); + helpers.doKeys(':'); +}, { value: 'foo\nbar'}); +testVim('yank_append_line_to_line_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('"', 'a', 'y', 'y'); + helpers.doKeys('j', '"', 'A', 'y', 'y'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+foo\nbar/.test(text)); + is(/"\s+foo\nbar/.test(text)); + }); + helpers.doKeys(':'); +}, { value: 'foo\nbar'}); +testVim('yank_append_word_to_word_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('"', 'a', 'y', 'w'); + helpers.doKeys('j', '"', 'A', 'y', 'w'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+foobar/.test(text)); + is(/"\s+foobar/.test(text)); + }); + helpers.doKeys(':'); +}, { value: 'foo\nbar'}); +testVim('yank_append_line_to_word_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('"', 'a', 'y', 'w'); + helpers.doKeys('j', '"', 'A', 'y', 'y'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+foo\nbar/.test(text)); + is(/"\s+foo\nbar/.test(text)); + }); + helpers.doKeys(':'); +}, { value: 'foo\nbar'}); +testVim('yank_append_word_to_line_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('"', 'a', 'y', 'y'); + helpers.doKeys('j', '"', 'A', 'y', 'w'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+foo\nbar/.test(text)); + is(/"\s+foo\nbar/.test(text)); + }); + helpers.doKeys(':'); +}, { value: 'foo\nbar'}); +testVim('macro_register', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('q', 'a', 'i'); + cm.replaceRange('gangnam', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q'); + helpers.doKeys('q', 'b', 'o'); + cm.replaceRange('style', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('q'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/a\s+i/.test(text)); + is(/b\s+o/.test(text)); + }); + helpers.doKeys(':'); +}, { value: ''}); +testVim('._register', function(cm,vim,helpers) { + cm.setCursor(0,0); + helpers.doKeys('i'); + cm.replaceRange('foo',cm.getCursor()); + helpers.doKeys(''); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/\.\s+foo/.test(text)); + }); + helpers.doKeys(':'); +}, {value: ''}); +testVim(':_register', function(cm,vim,helpers) { + helpers.doEx('bar'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/:\s+bar/.test(text)); + }); + helpers.doKeys(':'); +}, {value: ''}); +testVim('search_register_escape', function(cm, vim, helpers) { + // Check that the register is restored if the user escapes rather than confirms. + cm.openDialog = helpers.fakeOpenDialog('waldo'); + helpers.doKeys('/'); + var onKeyDown; + var onKeyUp; + var KEYCODES = { + f: 70, + o: 79, + Esc: 27 + }; + cm.openDialog = function(template, callback, options) { + onKeyDown = options.onKeyDown; + onKeyUp = options.onKeyUp; + }; + var close = function() {}; + helpers.doKeys('/'); + // Fake some keyboard events coming in. + onKeyDown({keyCode: KEYCODES.f}, '', close); + onKeyUp({keyCode: KEYCODES.f}, '', close); + onKeyDown({keyCode: KEYCODES.o}, 'f', close); + onKeyUp({keyCode: KEYCODES.o}, 'f', close); + onKeyDown({keyCode: KEYCODES.o}, 'fo', close); + onKeyUp({keyCode: KEYCODES.o}, 'fo', close); + onKeyDown({keyCode: KEYCODES.Esc}, 'foo', close); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/waldo/.test(text)); + is(!/foo/.test(text)); + }); + helpers.doKeys(':'); +}, {value: ''}); +testVim('search_register', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('foo'); + helpers.doKeys('/'); + cm.openDialog = helpers.fakeOpenDialog('registers'); + cm.openNotification = helpers.fakeOpenNotification(function(text) { + is(/\/\s+foo/.test(text)); + }); + helpers.doKeys(':'); +}, {value: ''}); +testVim('search_history', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('this'); + helpers.doKeys('/'); + cm.openDialog = helpers.fakeOpenDialog('checks'); + helpers.doKeys('/'); + cm.openDialog = helpers.fakeOpenDialog('search'); + helpers.doKeys('/'); + cm.openDialog = helpers.fakeOpenDialog('history'); + helpers.doKeys('/'); + cm.openDialog = helpers.fakeOpenDialog('checks'); + helpers.doKeys('/'); + var onKeyDown; + var onKeyUp; + var query = ''; + var keyCodes = { + Up: 38, + Down: 40 + }; + cm.openDialog = function(template, callback, options) { + onKeyUp = options.onKeyUp; + onKeyDown = options.onKeyDown; + }; + var close = function(newVal) { + if (typeof newVal == 'string') query = newVal; + } + helpers.doKeys('/'); + onKeyDown({keyCode: keyCodes.Up}, query, close); + onKeyUp({keyCode: keyCodes.Up}, query, close); + eq(query, 'checks'); + onKeyDown({keyCode: keyCodes.Up}, query, close); + onKeyUp({keyCode: keyCodes.Up}, query, close); + eq(query, 'history'); + onKeyDown({keyCode: keyCodes.Up}, query, close); + onKeyUp({keyCode: keyCodes.Up}, query, close); + eq(query, 'search'); + onKeyDown({keyCode: keyCodes.Up}, query, close); + onKeyUp({keyCode: keyCodes.Up}, query, close); + eq(query, 'this'); + onKeyDown({keyCode: keyCodes.Down}, query, close); + onKeyUp({keyCode: keyCodes.Down}, query, close); + eq(query, 'search'); +}, {value: ''}); +testVim('exCommand_history', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('registers'); + helpers.doKeys(':'); + cm.openDialog = helpers.fakeOpenDialog('sort'); + helpers.doKeys(':'); + cm.openDialog = helpers.fakeOpenDialog('map'); + helpers.doKeys(':'); + cm.openDialog = helpers.fakeOpenDialog('invalid'); + helpers.doKeys(':'); + var onKeyDown; + var onKeyUp; + var input = ''; + var keyCodes = { + Up: 38, + Down: 40, + s: 115 + }; + cm.openDialog = function(template, callback, options) { + onKeyUp = options.onKeyUp; + onKeyDown = options.onKeyDown; + }; + var close = function(newVal) { + if (typeof newVal == 'string') input = newVal; + } + helpers.doKeys(':'); + onKeyDown({keyCode: keyCodes.Up}, input, close); + eq(input, 'invalid'); + onKeyDown({keyCode: keyCodes.Up}, input, close); + eq(input, 'map'); + onKeyDown({keyCode: keyCodes.Up}, input, close); + eq(input, 'sort'); + onKeyDown({keyCode: keyCodes.Up}, input, close); + eq(input, 'registers'); + onKeyDown({keyCode: keyCodes.s}, '', close); + input = 's'; + onKeyDown({keyCode: keyCodes.Up}, input, close); + eq(input, 'sort'); +}, {value: ''}); +testVim('.', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('2', 'd', 'w'); + helpers.doKeys('.'); + eq('5 6', cm.getValue()); +}, { value: '1 2 3 4 5 6'}); +testVim('._repeat', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('2', 'd', 'w'); + helpers.doKeys('3', '.'); + eq('6', cm.getValue()); +}, { value: '1 2 3 4 5 6'}); +testVim('._insert', function(cm, vim, helpers) { + helpers.doKeys('i'); + cm.replaceRange('test', cm.getCursor()); + helpers.doKeys(''); + helpers.doKeys('.'); + eq('testestt', cm.getValue()); + helpers.assertCursorAt(0, 6); +}, { value: ''}); +testVim('._insert_repeat', function(cm, vim, helpers) { + helpers.doKeys('i'); + cm.replaceRange('test', cm.getCursor()); + cm.setCursor(0, 4); + helpers.doKeys(''); + helpers.doKeys('2', '.'); + eq('testesttestt', cm.getValue()); + helpers.assertCursorAt(0, 10); +}, { value: ''}); +testVim('._repeat_insert', function(cm, vim, helpers) { + helpers.doKeys('3', 'i'); + cm.replaceRange('te', cm.getCursor()); + cm.setCursor(0, 2); + helpers.doKeys(''); + helpers.doKeys('.'); + eq('tetettetetee', cm.getValue()); + helpers.assertCursorAt(0, 10); +}, { value: ''}); +testVim('._insert_o', function(cm, vim, helpers) { + helpers.doKeys('o'); + cm.replaceRange('z', cm.getCursor()); + cm.setCursor(1, 1); + helpers.doKeys(''); + helpers.doKeys('.'); + eq('\nz\nz', cm.getValue()); + helpers.assertCursorAt(2, 0); +}, { value: ''}); +testVim('._insert_o_repeat', function(cm, vim, helpers) { + helpers.doKeys('o'); + cm.replaceRange('z', cm.getCursor()); + helpers.doKeys(''); + cm.setCursor(1, 0); + helpers.doKeys('2', '.'); + eq('\nz\nz\nz', cm.getValue()); + helpers.assertCursorAt(3, 0); +}, { value: ''}); +testVim('._insert_o_indent', function(cm, vim, helpers) { + helpers.doKeys('o'); + cm.replaceRange('z', cm.getCursor()); + helpers.doKeys(''); + cm.setCursor(1, 2); + helpers.doKeys('.'); + eq('{\n z\n z', cm.getValue()); + helpers.assertCursorAt(2, 2); +}, { value: '{'}); +testVim('._insert_cw', function(cm, vim, helpers) { + helpers.doKeys('c', 'w'); + cm.replaceRange('test', cm.getCursor()); + helpers.doKeys(''); + cm.setCursor(0, 3); + helpers.doKeys('2', 'l'); + helpers.doKeys('.'); + eq('test test word3', cm.getValue()); + helpers.assertCursorAt(0, 8); +}, { value: 'word1 word2 word3' }); +testVim('._insert_cw_repeat', function(cm, vim, helpers) { + // For some reason, repeat cw in desktop VIM will does not repeat insert mode + // changes. Will conform to that behavior. + helpers.doKeys('c', 'w'); + cm.replaceRange('test', cm.getCursor()); + helpers.doKeys(''); + cm.setCursor(0, 4); + helpers.doKeys('l'); + helpers.doKeys('2', '.'); + eq('test test', cm.getValue()); + helpers.assertCursorAt(0, 8); +}, { value: 'word1 word2 word3' }); +testVim('._delete', function(cm, vim, helpers) { + cm.setCursor(0, 5); + helpers.doKeys('i'); + helpers.doInsertModeKeys('Backspace'); + helpers.doKeys(''); + helpers.doKeys('.'); + eq('zace', cm.getValue()); + helpers.assertCursorAt(0, 1); +}, { value: 'zabcde'}); +testVim('._delete_repeat', function(cm, vim, helpers) { + cm.setCursor(0, 6); + helpers.doKeys('i'); + helpers.doInsertModeKeys('Backspace'); + helpers.doKeys(''); + helpers.doKeys('2', '.'); + eq('zzce', cm.getValue()); + helpers.assertCursorAt(0, 1); +}, { value: 'zzabcde'}); +testVim('._visual_>', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('V', 'j', '>'); + cm.setCursor(2, 0) + helpers.doKeys('.'); + eq(' 1\n 2\n 3\n 4', cm.getValue()); + helpers.assertCursorAt(2, 2); +}, { value: '1\n2\n3\n4'}); +testVim('f;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('f', 'x'); + helpers.doKeys(';'); + helpers.doKeys('2', ';'); + eq(9, cm.getCursor().ch); +}, { value: '01x3xx678x'}); +testVim('F;', function(cm, vim, helpers) { + cm.setCursor(0, 8); + helpers.doKeys('F', 'x'); + helpers.doKeys(';'); + helpers.doKeys('2', ';'); + eq(2, cm.getCursor().ch); +}, { value: '01x3xx6x8x'}); +testVim('t;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('t', 'x'); + helpers.doKeys(';'); + helpers.doKeys('2', ';'); + eq(8, cm.getCursor().ch); +}, { value: '01x3xx678x'}); +testVim('T;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('T', 'x'); + helpers.doKeys(';'); + helpers.doKeys('2', ';'); + eq(2, cm.getCursor().ch); +}, { value: '0xx3xx678x'}); +testVim('f,', function(cm, vim, helpers) { + cm.setCursor(0, 6); + helpers.doKeys('f', 'x'); + helpers.doKeys(','); + helpers.doKeys('2', ','); + eq(2, cm.getCursor().ch); +}, { value: '01x3xx678x'}); +testVim('F,', function(cm, vim, helpers) { + cm.setCursor(0, 3); + helpers.doKeys('F', 'x'); + helpers.doKeys(','); + helpers.doKeys('2', ','); + eq(9, cm.getCursor().ch); +}, { value: '01x3xx678x'}); +testVim('t,', function(cm, vim, helpers) { + cm.setCursor(0, 6); + helpers.doKeys('t', 'x'); + helpers.doKeys(','); + helpers.doKeys('2', ','); + eq(3, cm.getCursor().ch); +}, { value: '01x3xx678x'}); +testVim('T,', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys('T', 'x'); + helpers.doKeys(','); + helpers.doKeys('2', ','); + eq(8, cm.getCursor().ch); +}, { value: '01x3xx67xx'}); +testVim('fd,;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('f', '4'); + cm.setCursor(0, 0); + helpers.doKeys('d', ';'); + eq('56789', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 9); + helpers.doKeys('d', ','); + eq('01239', cm.getValue()); +}, { value: '0123456789'}); +testVim('Fd,;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('F', '4'); + cm.setCursor(0, 9); + helpers.doKeys('d', ';'); + eq('01239', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 0); + helpers.doKeys('d', ','); + eq('56789', cm.getValue()); +}, { value: '0123456789'}); +testVim('td,;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('t', '4'); + cm.setCursor(0, 0); + helpers.doKeys('d', ';'); + eq('456789', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 9); + helpers.doKeys('d', ','); + eq('012349', cm.getValue()); +}, { value: '0123456789'}); +testVim('Td,;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('T', '4'); + cm.setCursor(0, 9); + helpers.doKeys('d', ';'); + eq('012349', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 0); + helpers.doKeys('d', ','); + eq('456789', cm.getValue()); +}, { value: '0123456789'}); +testVim('fc,;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('f', '4'); + cm.setCursor(0, 0); + helpers.doKeys('c', ';', ''); + eq('56789', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 9); + helpers.doKeys('c', ','); + eq('01239', cm.getValue()); +}, { value: '0123456789'}); +testVim('Fc,;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('F', '4'); + cm.setCursor(0, 9); + helpers.doKeys('c', ';', ''); + eq('01239', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 0); + helpers.doKeys('c', ','); + eq('56789', cm.getValue()); +}, { value: '0123456789'}); +testVim('tc,;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('t', '4'); + cm.setCursor(0, 0); + helpers.doKeys('c', ';', ''); + eq('456789', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 9); + helpers.doKeys('c', ','); + eq('012349', cm.getValue()); +}, { value: '0123456789'}); +testVim('Tc,;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('T', '4'); + cm.setCursor(0, 9); + helpers.doKeys('c', ';', ''); + eq('012349', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 0); + helpers.doKeys('c', ','); + eq('456789', cm.getValue()); +}, { value: '0123456789'}); +testVim('fy,;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('f', '4'); + cm.setCursor(0, 0); + helpers.doKeys('y', ';', 'P'); + eq('012340123456789', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 9); + helpers.doKeys('y', ',', 'P'); + eq('012345678456789', cm.getValue()); +}, { value: '0123456789'}); +testVim('Fy,;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('F', '4'); + cm.setCursor(0, 9); + helpers.doKeys('y', ';', 'p'); + eq('012345678945678', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 0); + helpers.doKeys('y', ',', 'P'); + eq('012340123456789', cm.getValue()); +}, { value: '0123456789'}); +testVim('ty,;', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('t', '4'); + cm.setCursor(0, 0); + helpers.doKeys('y', ';', 'P'); + eq('01230123456789', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 9); + helpers.doKeys('y', ',', 'p'); + eq('01234567895678', cm.getValue()); +}, { value: '0123456789'}); +testVim('Ty,;', function(cm, vim, helpers) { + cm.setCursor(0, 9); + helpers.doKeys('T', '4'); + cm.setCursor(0, 9); + helpers.doKeys('y', ';', 'p'); + eq('01234567895678', cm.getValue()); + helpers.doKeys('u'); + cm.setCursor(0, 0); + helpers.doKeys('y', ',', 'P'); + eq('01230123456789', cm.getValue()); +}, { value: '0123456789'}); +testVim('HML', function(cm, vim, helpers) { + var lines = 35; + var textHeight = cm.defaultTextHeight(); + cm.setSize(600, lines*textHeight); + cm.setCursor(120, 0); + cm.refresh(); //ace! + helpers.doKeys('H'); + helpers.assertCursorAt(86, 2); + helpers.doKeys('L'); + helpers.assertCursorAt(120, 4); + helpers.doKeys('M'); + helpers.assertCursorAt(103,4); +}, { value: (function(){ + var lines = new Array(100); + var upper = ' xx\n'; + var lower = ' xx\n'; + upper = lines.join(upper); + lower = lines.join(lower); + return upper + lower; +})()}); + +var zVals = []; +forEach(['zb','zz','zt','z-','z.','z'], function(e, idx){ + var lineNum = 250; + var lines = 35; + testVim(e, function(cm, vim, helpers) { + var k1 = e[0]; + var k2 = e.substring(1); + var textHeight = cm.defaultTextHeight(); + cm.setSize(600, lines*textHeight); + cm.setCursor(lineNum, 0); + helpers.doKeys(k1, k2); + zVals[idx] = cm.getScrollInfo().top; + }, { value: (function(){ + return new Array(500).join('\n'); + })()}); +}); +testVim('zb', function(cm, vim, helpers){ + eq(zVals[2], zVals[5]); }); -addTest("Moving around", "02", "3", function() { - initEditor(" k \nh l\n j "); - sendKeys("hjj"); - assertPosition(2, 0); - sendKeys("jll"); - assertPosition(2, 2); - sendKeys("lkk"); - assertPosition(0, 2); - sendKeys("khh"); - assertPosition(0, 0); -}); +var moveTillCharacterSandbox = + 'The quick brown fox \n' + 'jumped over the lazy dog.' +testVim('moveTillCharacter', function(cm, vim, helpers){ + cm.setCursor(0, 0); + // Search for the 'q'. + cm.openDialog = helpers.fakeOpenDialog('q'); + helpers.doKeys('/'); + eq(4, cm.getCursor().ch); + // Jump to just before the first o in the list. + helpers.doKeys('t'); + helpers.doKeys('o'); + eq('The quick brown fox \n', cm.getValue()); + // Delete that one character. + helpers.doKeys('d'); + helpers.doKeys('t'); + helpers.doKeys('o'); + eq('The quick bown fox \n', cm.getValue()); + // Delete everything until the next 'o'. + helpers.doKeys('.'); + eq('The quick box \n', cm.getValue()); + // An unmatched character should have no effect. + helpers.doKeys('d'); + helpers.doKeys('t'); + helpers.doKeys('q'); + eq('The quick box \n', cm.getValue()); + // Matches should only be possible on single lines. + helpers.doKeys('d'); + helpers.doKeys('t'); + helpers.doKeys('z'); + eq('The quick box \n', cm.getValue()); + // After all that, the search for 'q' should still be active, so the 'N' command + // can run it again in reverse. Use that to delete everything back to the 'q'. + helpers.doKeys('d'); + helpers.doKeys('N'); + eq('The ox \n', cm.getValue()); + eq(4, cm.getCursor().ch); +}, { value: moveTillCharacterSandbox}); +testVim('searchForPipe', function(cm, vim, helpers){ + CodeMirror.Vim.setOption('pcre', false); + cm.setCursor(0, 0); + // Search for the '|'. + cm.openDialog = helpers.fakeOpenDialog('|'); + helpers.doKeys('/'); + eq(4, cm.getCursor().ch); +}, { value: 'this|that'}); -addTest("Deleting characters", "02", "4", function() { - var text = "A very intelligent turtle\nFound programming UNIX a hurdle"; - initEditor(text); - sendKeys("xxxxxxx"); - assertContent(text.substring(7)); - sendKeys("iA young ", "Esc"); - assertContent("A young intelligent turtle\nFound programming UNIX a hurdle"); - sendKeys("dd"); - assertContent("Found programming UNIX a hurdle"); - sendKeys("ddiA young intelligent\nturtle", "Esc", "kJ"); - assertContent("A young intelligent turtle"); -}); -addTest("Undo and Redo [PARTIAL]", "02", "5", function() { - var text = "A young intelligent turtle"; - initEditor(text); - sendKeys("ddu"); - assertContent(text); - sendKeys("0xxxxxxx"); - assertContent(text.substring(7)); - for (var i=6; i>=0; i--) { - sendKeys("u"); - assertContent(text.substring(i)); +var scrollMotionSandbox = + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'; +testVim('scrollMotion', function(cm, vim, helpers){ + var prevCursor, prevScrollInfo; + cm.setCursor(0, 0); + // ctrl-y at the top of the file should have no effect. + helpers.doKeys(''); + eq(0, cm.getCursor().line); + prevScrollInfo = cm.getScrollInfo(); + helpers.doKeys(''); + eq(1, cm.getCursor().line); + is(prevScrollInfo.top < cm.getScrollInfo().top); + // Jump to the end of the sandbox. + cm.setCursor(1000, 0); + cm.refresh(); //ace! + prevCursor = cm.getCursor(); + // ctrl-e at the bottom of the file should have no effect. + helpers.doKeys(''); + eq(prevCursor.line, cm.getCursor().line); + cm.refresh(); //ace! + prevScrollInfo = cm.getScrollInfo(); + helpers.doKeys(''); + eq(prevCursor.line - 1, cm.getCursor().line); + is(prevScrollInfo.top > cm.getScrollInfo().top); +}, { value: scrollMotionSandbox}); + +var squareBracketMotionSandbox = ''+ + '({\n'+//0 + ' ({\n'+//11 + ' /*comment {\n'+//2 + ' */(\n'+//3 + '#else \n'+//4 + ' /* )\n'+//5 + '#if }\n'+//6 + ' )}*/\n'+//7 + ')}\n'+//8 + '{}\n'+//9 + '#else {{\n'+//10 + '{}\n'+//11 + '}\n'+//12 + '{\n'+//13 + '#endif\n'+//14 + '}\n'+//15 + '}\n'+//16 + '#else';//17 +testVim('[[, ]]', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys(']', ']'); + helpers.assertCursorAt(9,0); + helpers.doKeys('2', ']', ']'); + helpers.assertCursorAt(13,0); + helpers.doKeys(']', ']'); + helpers.assertCursorAt(17,0); + helpers.doKeys('[', '['); + helpers.assertCursorAt(13,0); + helpers.doKeys('2', '[', '['); + helpers.assertCursorAt(9,0); + helpers.doKeys('[', '['); + helpers.assertCursorAt(0,0); +}, { value: squareBracketMotionSandbox}); +testVim('[], ][', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys(']', '['); + helpers.assertCursorAt(12,0); + helpers.doKeys('2', ']', '['); + helpers.assertCursorAt(16,0); + helpers.doKeys(']', '['); + helpers.assertCursorAt(17,0); + helpers.doKeys('[', ']'); + helpers.assertCursorAt(16,0); + helpers.doKeys('2', '[', ']'); + helpers.assertCursorAt(12,0); + helpers.doKeys('[', ']'); + helpers.assertCursorAt(0,0); +}, { value: squareBracketMotionSandbox}); +testVim('[{, ]}', function(cm, vim, helpers) { + cm.setCursor(4, 10); + helpers.doKeys('[', '{'); + helpers.assertCursorAt(2,12); + helpers.doKeys('2', '[', '{'); + helpers.assertCursorAt(0,1); + cm.setCursor(4, 10); + helpers.doKeys(']', '}'); + helpers.assertCursorAt(6,11); + helpers.doKeys('2', ']', '}'); + helpers.assertCursorAt(8,1); + cm.setCursor(0,1); + helpers.doKeys(']', '}'); + helpers.assertCursorAt(8,1); + helpers.doKeys('[', '{'); + helpers.assertCursorAt(0,1); +}, { value: squareBracketMotionSandbox}); +testVim('[(, ])', function(cm, vim, helpers) { + cm.setCursor(4, 10); + helpers.doKeys('[', '('); + helpers.assertCursorAt(3,14); + helpers.doKeys('2', '[', '('); + helpers.assertCursorAt(0,0); + cm.setCursor(4, 10); + helpers.doKeys(']', ')'); + helpers.assertCursorAt(5,11); + helpers.doKeys('2', ']', ')'); + helpers.assertCursorAt(8,0); + helpers.doKeys('[', '('); + helpers.assertCursorAt(0,0); + helpers.doKeys(']', ')'); + helpers.assertCursorAt(8,0); +}, { value: squareBracketMotionSandbox}); +testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) { + forEach(['*', '/'], function(key){ + cm.setCursor(7, 0); + helpers.doKeys('2', '[', key); + helpers.assertCursorAt(2,2); + helpers.doKeys('2', ']', key); + helpers.assertCursorAt(7,5); + }); +}, { value: squareBracketMotionSandbox}); +testVim('[#, ]#', function(cm, vim, helpers) { + cm.setCursor(10, 3); + helpers.doKeys('2', '[', '#'); + helpers.assertCursorAt(4,0); + helpers.doKeys('5', ']', '#'); + helpers.assertCursorAt(17,0); + cm.setCursor(10, 3); + helpers.doKeys(']', '#'); + helpers.assertCursorAt(14,0); +}, { value: squareBracketMotionSandbox}); +testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) { + cm.setCursor(11, 0); + helpers.doKeys('[', 'm'); + helpers.assertCursorAt(10,7); + helpers.doKeys('4', '[', 'm'); + helpers.assertCursorAt(1,3); + helpers.doKeys('5', ']', 'm'); + helpers.assertCursorAt(11,0); + helpers.doKeys('[', 'M'); + helpers.assertCursorAt(9,1); + helpers.doKeys('3', ']', 'M'); + helpers.assertCursorAt(15,0); + helpers.doKeys('5', '[', 'M'); + helpers.assertCursorAt(7,3); +}, { value: squareBracketMotionSandbox}); + +// Ex mode tests +testVim('ex_go_to_line', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doEx('4'); + helpers.assertCursorAt(3, 0); +}, { value: 'a\nb\nc\nd\ne\n'}); +testVim('ex_write', function(cm, vim, helpers) { + var tmp = CodeMirror.commands.save; + var written; + var actualCm; + CodeMirror.commands.save = function(cm) { + written = true; + actualCm = cm; + }; + // Test that w, wr, wri ... write all trigger :write. + var command = 'write'; + for (var i = 1; i < command.length; i++) { + written = false; + actualCm = null; + helpers.doEx(command.substring(0, i)); + eq(written, true); + eq(actualCm, cm); + } + CodeMirror.commands.save = tmp; +}); +testVim('ex_sort', function(cm, vim, helpers) { + helpers.doEx('sort'); + eq('Z\na\nb\nc\nd', cm.getValue()); +}, { value: 'b\nZ\nd\nc\na'}); +testVim('ex_sort_reverse', function(cm, vim, helpers) { + helpers.doEx('sort!'); + eq('d\nc\nb\na', cm.getValue()); +}, { value: 'b\nd\nc\na'}); +testVim('ex_sort_range', function(cm, vim, helpers) { + helpers.doEx('2,3sort'); + eq('b\nc\nd\na', cm.getValue()); +}, { value: 'b\nd\nc\na'}); +testVim('ex_sort_oneline', function(cm, vim, helpers) { + helpers.doEx('2sort'); + // Expect no change. + eq('b\nd\nc\na', cm.getValue()); +}, { value: 'b\nd\nc\na'}); +testVim('ex_sort_ignoreCase', function(cm, vim, helpers) { + helpers.doEx('sort i'); + eq('a\nb\nc\nd\nZ', cm.getValue()); +}, { value: 'b\nZ\nd\nc\na'}); +testVim('ex_sort_unique', function(cm, vim, helpers) { + helpers.doEx('sort u'); + eq('Z\na\nb\nc\nd', cm.getValue()); +}, { value: 'b\nZ\na\na\nd\na\nc\na'}); +testVim('ex_sort_decimal', function(cm, vim, helpers) { + helpers.doEx('sort d'); + eq('d3\n s5\n6\n.9', cm.getValue()); +}, { value: '6\nd3\n s5\n.9'}); +testVim('ex_sort_decimal_negative', function(cm, vim, helpers) { + helpers.doEx('sort d'); + eq('z-9\nd3\n s5\n6\n.9', cm.getValue()); +}, { value: '6\nd3\n s5\n.9\nz-9'}); +testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) { + helpers.doEx('sort! d'); + eq('.9\n6\n s5\nd3', cm.getValue()); +}, { value: '6\nd3\n s5\n.9'}); +testVim('ex_sort_hex', function(cm, vim, helpers) { + helpers.doEx('sort x'); + eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue()); +}, { value: '6\nd3\n s5\n&0xB\n.9'}); +testVim('ex_sort_octal', function(cm, vim, helpers) { + helpers.doEx('sort o'); + eq('.8\n.9\nd3\n s5\n6', cm.getValue()); +}, { value: '6\nd3\n s5\n.9\n.8'}); +testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) { + helpers.doEx('sort d'); + eq('y\nz\nc1\nb2\na3', cm.getValue()); +}, { value: 'a3\nz\nc1\ny\nb2'}); +testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) { + helpers.doEx('sort! d'); + eq('a3\nb2\nc1\nz\ny', cm.getValue()); +}, { value: 'a3\nz\nc1\ny\nb2'}); +// test for :global command +testVim('ex_global', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doEx('g/one/s//two'); + eq('two two\n two two\n two two', cm.getValue()); + helpers.doEx('1,2g/two/s//one'); + eq('one one\n one one\n two two', cm.getValue()); +}, {value: 'one one\n one one\n one one'}); +testVim('ex_global_confirm', function(cm, vim, helpers) { + cm.setCursor(0, 0); + var onKeyDown; + var openDialogSave = cm.openDialog; + var KEYCODES = { + a: 65, + n: 78, + q: 81, + y: 89 + }; + // Intercept the ex command, 'global' + cm.openDialog = function(template, callback, options) { + // Intercept the prompt for the embedded ex command, 'substitute' + cm.openDialog = function(template, callback, options) { + onKeyDown = options.onKeyDown; + }; + callback('g/one/s//two/gc'); + }; + helpers.doKeys(':'); + var close = function() {}; + onKeyDown({keyCode: KEYCODES.n}, '', close); + onKeyDown({keyCode: KEYCODES.y}, '', close); + onKeyDown({keyCode: KEYCODES.a}, '', close); + onKeyDown({keyCode: KEYCODES.q}, '', close); + onKeyDown({keyCode: KEYCODES.y}, '', close); + eq('one two\n two two\n one one\n two one\n one one', cm.getValue()); +}, {value: 'one one\n one one\n one one\n one one\n one one'}); +// Basic substitute tests. +testVim('ex_substitute_same_line', function(cm, vim, helpers) { + cm.setCursor(1, 0); + helpers.doEx('s/one/two/g'); + eq('one one\n two two', cm.getValue()); +}, { value: 'one one\n one one'}); +testVim('ex_substitute_full_file', function(cm, vim, helpers) { + cm.setCursor(1, 0); + helpers.doEx('%s/one/two/g'); + eq('two two\n two two', cm.getValue()); +}, { value: 'one one\n one one'}); +testVim('ex_substitute_input_range', function(cm, vim, helpers) { + cm.setCursor(1, 0); + helpers.doEx('1,3s/\\d/0/g'); + eq('0\n0\n0\n4', cm.getValue()); +}, { value: '1\n2\n3\n4' }); +testVim('ex_substitute_visual_range', function(cm, vim, helpers) { + cm.setCursor(1, 0); + // Set last visual mode selection marks '< and '> at lines 2 and 4 + helpers.doKeys('V', '2', 'j', 'v'); + helpers.doEx('\'<,\'>s/\\d/0/g'); + eq('1\n0\n0\n0\n5', cm.getValue()); +}, { value: '1\n2\n3\n4\n5' }); +testVim('ex_substitute_empty_query', function(cm, vim, helpers) { + // If the query is empty, use last query. + cm.setCursor(1, 0); + cm.openDialog = helpers.fakeOpenDialog('1'); + helpers.doKeys('/'); + helpers.doEx('s//b/g'); + eq('abb ab2 ab3', cm.getValue()); +}, { value: 'a11 a12 a13' }); +testVim('ex_substitute_javascript', function(cm, vim, helpers) { + CodeMirror.Vim.setOption('pcre', false); + cm.setCursor(1, 0); + // Throw all the things that javascript likes to treat as special values + // into the replace part. All should be literal (this is VIM). + helpers.doEx('s/\\(\\d+\\)/$$ $\' $` $& \\1/g') + eq('a $$ $\' $` $& 0 b', cm.getValue()); +}, { value: 'a 0 b' }); +testVim('ex_substitute_empty_arguments', function(cm,vim,helpers) { + cm.setCursor(0, 0); + helpers.doEx('s/a/b/g'); + cm.setCursor(1, 0); + helpers.doEx('s'); + eq('b b\nb a', cm.getValue()); +}, {value: 'a a\na a'}); + +// More complex substitute tests that test both pcre and nopcre options. +function testSubstitute(name, options) { + testVim(name + '_pcre', function(cm, vim, helpers) { + cm.setCursor(1, 0); + CodeMirror.Vim.setOption('pcre', true); + helpers.doEx(options.expr); + eq(options.expectedValue, cm.getValue()); + }, options); + // If no noPcreExpr is defined, assume that it's the same as the expr. + var noPcreExpr = options.noPcreExpr ? options.noPcreExpr : options.expr; + testVim(name + '_nopcre', function(cm, vim, helpers) { + cm.setCursor(1, 0); + CodeMirror.Vim.setOption('pcre', false); + helpers.doEx(noPcreExpr); + eq(options.expectedValue, cm.getValue()); + }, options); +} +testSubstitute('ex_substitute_capture', { + value: 'a11 a12 a13', + expectedValue: 'a1111 a1212 a1313', + // $n is a backreference + expr: 's/(\\d+)/$1$1/g', + // \n is a backreference. + noPcreExpr: 's/\\(\\d+\\)/\\1\\1/g'}); +testSubstitute('ex_substitute_capture2', { + value: 'a 0 b', + expectedValue: 'a $00 b', + expr: 's/(\\d+)/$$$1$1/g', + noPcreExpr: 's/\\(\\d+\\)/$\\1\\1/g'}); +testSubstitute('ex_substitute_nocapture', { + value: 'a11 a12 a13', + expectedValue: 'a$1$1 a$1$1 a$1$1', + expr: 's/(\\d+)/$$1$$1/g', + noPcreExpr: 's/\\(\\d+\\)/$1$1/g'}); +testSubstitute('ex_substitute_nocapture2', { + value: 'a 0 b', + expectedValue: 'a $10 b', + expr: 's/(\\d+)/$$1$1/g', + noPcreExpr: 's/\\(\\d+\\)/\\$1\\1/g'}); +testSubstitute('ex_substitute_nocapture', { + value: 'a b c', + expectedValue: 'a $ c', + expr: 's/b/$$/', + noPcreExpr: 's/b/$/'}); +testSubstitute('ex_substitute_slash_regex', { + value: 'one/two \n three/four', + expectedValue: 'one|two \n three|four', + expr: '%s/\\//|'}); +testSubstitute('ex_substitute_pipe_regex', { + value: 'one|two \n three|four', + expectedValue: 'one,two \n three,four', + expr: '%s/\\|/,/', + noPcreExpr: '%s/|/,/'}); +testSubstitute('ex_substitute_or_regex', { + value: 'one|two \n three|four', + expectedValue: 'ana|twa \n thraa|faar', + expr: '%s/o|e|u/a/g', + noPcreExpr: '%s/o\\|e\\|u/a/g'}); +testSubstitute('ex_substitute_or_word_regex', { + value: 'one|two \n three|four', + expectedValue: 'five|five \n three|four', + expr: '%s/(one|two)/five/g', + noPcreExpr: '%s/\\(one\\|two\\)/five/g'}); +testSubstitute('ex_substitute_backslashslash_regex', { + value: 'one\\two \n three\\four', + expectedValue: 'one,two \n three,four', + expr: '%s/\\\\/,'}); +testSubstitute('ex_substitute_slash_replacement', { + value: 'one,two \n three,four', + expectedValue: 'one/two \n three/four', + expr: '%s/,/\\/'}); +testSubstitute('ex_substitute_backslash_replacement', { + value: 'one,two \n three,four', + expectedValue: 'one\\two \n three\\four', + expr: '%s/,/\\\\/g'}); +testSubstitute('ex_substitute_multibackslash_replacement', { + value: 'one,two \n three,four', + expectedValue: 'one\\\\\\\\two \n three\\\\\\\\four', // 2*8 backslashes. + expr: '%s/,/\\\\\\\\\\\\\\\\/g'}); // 16 backslashes. +testSubstitute('ex_substitute_braces_word', { + value: 'ababab abb ab{2}', + expectedValue: 'ab abb ab{2}', + expr: '%s/(ab){2}//g', + noPcreExpr: '%s/\\(ab\\)\\{2\\}//g'}); +testSubstitute('ex_substitute_braces_range', { + value: 'a aa aaa aaaa', + expectedValue: 'a a', + expr: '%s/a{2,3}//g', + noPcreExpr: '%s/a\\{2,3\\}//g'}); +testSubstitute('ex_substitute_braces_literal', { + value: 'ababab abb ab{2}', + expectedValue: 'ababab abb ', + expr: '%s/ab\\{2\\}//g', + noPcreExpr: '%s/ab{2}//g'}); +testSubstitute('ex_substitute_braces_char', { + value: 'ababab abb ab{2}', + expectedValue: 'ababab ab{2}', + expr: '%s/ab{2}//g', + noPcreExpr: '%s/ab\\{2\\}//g'}); +testSubstitute('ex_substitute_braces_no_escape', { + value: 'ababab abb ab{2}', + expectedValue: 'ababab ab{2}', + expr: '%s/ab{2}//g', + noPcreExpr: '%s/ab\\{2}//g'}); +testSubstitute('ex_substitute_count', { + value: '1\n2\n3\n4', + expectedValue: '1\n0\n0\n4', + expr: 's/\\d/0/i 2'}); +testSubstitute('ex_substitute_count_with_range', { + value: '1\n2\n3\n4', + expectedValue: '1\n2\n0\n0', + expr: '1,3s/\\d/0/ 3'}); +testSubstitute('ex_substitute_not_global', { + value: 'aaa\nbaa\ncaa', + expectedValue: 'xaa\nbxa\ncxa', + expr: '%s/a/x/'}); +function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) { + testVim(name, function(cm, vim, helpers) { + var savedOpenDialog = cm.openDialog; + var savedKeyName = CodeMirror.keyName; + var onKeyDown; + var recordedCallback; + var closed = true; // Start out closed, set false on second openDialog. + function close() { + closed = true; } - sendKeys("ctrl-r", "ctrl-r"); - assertContent(text.substring(2)); - text = "A very intelligent turtle"; - sendKeys("ddi", text, "Esc"); - sendKeys("0wxxxxxwwxxxxxx"); - assertContent("A intelligent "); -/* "U" fails - sendKeys("U"); - assertContent(text); - sendKeys("u"); - assertContent("A intelligent "); -*/ + // First openDialog should save callback. + cm.openDialog = function(template, callback, options) { + recordedCallback = callback; + } + // Do first openDialog. + helpers.doKeys(':'); + // Second openDialog should save keyDown handler. + cm.openDialog = function(template, callback, options) { + onKeyDown = options.onKeyDown; + closed = false; + }; + // Return the command to Vim and trigger second openDialog. + recordedCallback(command); + // The event should really use keyCode, but here just mock it out and use + // key and replace keyName to just return key. + CodeMirror.keyName = function (e) { return e.key; } + keys = keys.toUpperCase(); + for (var i = 0; i < keys.length; i++) { + is(!closed); + onKeyDown({ key: keys.charAt(i) }, '', close); + } + try { + eq(expectedValue, cm.getValue()); + helpers.assertCursorAt(finalPos); + is(closed); + } catch(e) { + throw e + } finally { + // Restore overriden functions. + CodeMirror.keyName = savedKeyName; + cm.openDialog = savedOpenDialog; + } + }, { value: initialValue }); +}; +testSubstituteConfirm('ex_substitute_confirm_emptydoc', + '%s/x/b/c', '', '', '', makeCursor(0, 0)); +testSubstituteConfirm('ex_substitute_confirm_nomatch', + '%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0)); +testSubstituteConfirm('ex_substitute_confirm_accept', + '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1)); +testSubstituteConfirm('ex_substitute_confirm_random_keys', + '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1)); +testSubstituteConfirm('ex_substitute_confirm_some', + '%s/a/b/cg', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1)); +testSubstituteConfirm('ex_substitute_confirm_all', + '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1)); +testSubstituteConfirm('ex_substitute_confirm_accept_then_all', + '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1)); +testSubstituteConfirm('ex_substitute_confirm_quit', + '%s/a/b/cg', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3)); +testSubstituteConfirm('ex_substitute_confirm_last', + '%s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); +testSubstituteConfirm('ex_substitute_confirm_oneline', + '1s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); +testSubstituteConfirm('ex_substitute_confirm_range_accept', + '1,2s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0)); +testSubstituteConfirm('ex_substitute_confirm_range_some', + '1,3s/a/b/cg', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0)); +testSubstituteConfirm('ex_substitute_confirm_range_all', + '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0)); +testSubstituteConfirm('ex_substitute_confirm_range_last', + '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0)); +//:noh should clear highlighting of search-results but allow to resume search through n +testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) { + cm.openDialog = helpers.fakeOpenDialog('match'); + helpers.doKeys('?'); + helpers.doEx('noh'); + eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared'); + helpers.doKeys('n'); + helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting'); +}, { value: 'match nope match \n nope Match' }); +testVim('set_boolean', function(cm, vim, helpers) { + CodeMirror.Vim.defineOption('testoption', true, 'boolean'); + // Test default value is set. + is(CodeMirror.Vim.getOption('testoption')); + try { + // Test fail to set to non-boolean + CodeMirror.Vim.setOption('testoption', '5'); + fail(); + } catch (expected) {}; + // Test setOption + CodeMirror.Vim.setOption('testoption', false); + is(!CodeMirror.Vim.getOption('testoption')); +}); +testVim('ex_set_boolean', function(cm, vim, helpers) { + CodeMirror.Vim.defineOption('testoption', true, 'boolean'); + // Test default value is set. + is(CodeMirror.Vim.getOption('testoption')); + try { + // Test fail to set to non-boolean + helpers.doEx('set testoption=22'); + fail(); + } catch (expected) {}; + // Test setOption + helpers.doEx('set notestoption'); + is(!CodeMirror.Vim.getOption('testoption')); +}); +testVim('set_string', function(cm, vim, helpers) { + CodeMirror.Vim.defineOption('testoption', 'a', 'string'); + // Test default value is set. + eq('a', CodeMirror.Vim.getOption('testoption')); + try { + // Test fail to set non-string. + CodeMirror.Vim.setOption('testoption', true); + fail(); + } catch (expected) {}; + try { + // Test fail to set 'notestoption' + CodeMirror.Vim.setOption('notestoption', 'b'); + fail(); + } catch (expected) {}; + // Test setOption + CodeMirror.Vim.setOption('testoption', 'c'); + eq('c', CodeMirror.Vim.getOption('testoption')); +}); +testVim('ex_set_string', function(cm, vim, helpers) { + CodeMirror.Vim.defineOption('testoption', 'a', 'string'); + // Test default value is set. + eq('a', CodeMirror.Vim.getOption('testoption')); + try { + // Test fail to set 'notestoption' + helpers.doEx('set notestoption=b'); + fail(); + } catch (expected) {}; + // Test setOption + helpers.doEx('set testoption=c') + eq('c', CodeMirror.Vim.getOption('testoption')); +}); +// TODO: Reset key maps after each test. +testVim('ex_map_key2key', function(cm, vim, helpers) { + helpers.doEx('map a x'); + helpers.doKeys('a'); + helpers.assertCursorAt(0, 0); + eq('bc', cm.getValue()); +}, { value: 'abc' }); +testVim('ex_unmap_key2key', function(cm, vim, helpers) { + helpers.doEx('unmap a'); + helpers.doKeys('a'); + eq('vim-insert', cm.getOption('keyMap')); +}, { value: 'abc' }); +testVim('ex_unmap_key2key_does_not_remove_default', function(cm, vim, helpers) { + try { + helpers.doEx('unmap a'); + fail(); + } catch (expected) {} + helpers.doKeys('a'); + eq('vim-insert', cm.getOption('keyMap')); +}, { value: 'abc' }); +testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) { + helpers.doEx('map ; :'); + var dialogOpened = false; + cm.openDialog = function() { + dialogOpened = true; + } + helpers.doKeys(';'); + eq(dialogOpened, true); +}); +testVim('ex_map_ex2key:', function(cm, vim, helpers) { + helpers.doEx('map :del x'); + helpers.doEx('del'); + helpers.assertCursorAt(0, 0); + eq('bc', cm.getValue()); +}, { value: 'abc' }); +testVim('ex_map_ex2ex', function(cm, vim, helpers) { + helpers.doEx('map :del :w'); + var tmp = CodeMirror.commands.save; + var written = false; + var actualCm; + CodeMirror.commands.save = function(cm) { + written = true; + actualCm = cm; + }; + helpers.doEx('del'); + CodeMirror.commands.save = tmp; + eq(written, true); + eq(actualCm, cm); +}); +testVim('ex_map_key2ex', function(cm, vim, helpers) { + helpers.doEx('map a :w'); + var tmp = CodeMirror.commands.save; + var written = false; + var actualCm; + CodeMirror.commands.save = function(cm) { + written = true; + actualCm = cm; + }; + helpers.doKeys('a'); + CodeMirror.commands.save = tmp; + eq(written, true); + eq(actualCm, cm); +}); +testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) { + CodeMirror.Vim.map('b', ':w', 'visual'); + var tmp = CodeMirror.commands.save; + var written = false; + var actualCm; + CodeMirror.commands.save = function(cm) { + written = true; + actualCm = cm; + }; + // Mapping should not work in normal mode. + helpers.doKeys('b'); + eq(written, false); + // Mapping should work in visual mode. + helpers.doKeys('v', 'b'); + eq(written, true); + eq(actualCm, cm); + + CodeMirror.commands.save = tmp; +}); +testVim('ex_imap', function(cm, vim, helpers) { + CodeMirror.Vim.map('jk', '', 'insert'); + helpers.doKeys('i'); + is(vim.insertMode); + helpers.doKeys('j', 'k'); + is(!vim.insertMode); +}) + +// Testing registration of functions as ex-commands and mapping to -keys +testVim('ex_api_test', function(cm, vim, helpers) { + var res=false; + var val='from'; + CodeMirror.Vim.defineEx('extest','ext',function(cm,params){ + if(params.args)val=params.args[0]; + else res=true; + }); + helpers.doEx(':ext to'); + eq(val,'to','Defining ex-command failed'); + CodeMirror.Vim.map('',':ext'); + helpers.doKeys('',''); + is(res,'Mapping to key failed'); +}); +// For now, this test needs to be last because it messes up : for future tests. +testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) { + helpers.doEx('map : x'); + helpers.doKeys(':'); + helpers.assertCursorAt(0, 0); + eq('bc', cm.getValue()); +}, { value: 'abc' }); + +// Test event handlers +testVim('beforeSelectionChange', function(cm, vim, helpers) { + cm.setCursor(0, 100); + eqPos(cm.getCursor('head'), cm.getCursor('anchor')); +}, { value: 'abc' }); + + }); -addTest("Other editing commands [PARTIAL]", "02", "6", function() { - var text = "and that's not saying much for the turtle."; - initEditor(text); - sendKeys("$xa!!!", "Esc"); - assertContent(text.slice(0, -1) + "!!!"); - var text1 = "A very intelligent turtle"; - var text2 = "Found programming UNIX a hurdle"; - sendKeys("ddi", text1 + "\n" + text2, "Esc"); - var text3 = "That liked using Vim"; - sendKeys("ko", text3, "Esc"); - assertContent([text1, text3, text2].join("\n")); - sendKeys("O", "Esc"); - assertContent([text1, "", text3, text2].join("\n")); -/* "3a!" fails - sendKeys("3a!", "Esc"); -*/ - sendKeys("a!!!", "Esc"); - assertContent([text1, "!!!", text3, text2].join("\n")); - sendKeys("hhh3x"); - assertContent([text1, "", text3, text2].join("\n")); -}); - -addTest("Getting out [PARTIAL]", "02", "7", function() { - initEditor(""); - sendKeys("ZZ"); - /* - sendKeys("aSome text", "Esc"); - sendKeys(":q", "Return"); - sendKeys(":q!", "Return"); - - sendKeys(":e!", "Return"); - */ -}); - -addTest("Finding help [PARTIAL]", "02", "8", function() { - initEditor(""); - sendKeys(":help", "Return"); - sendKeys("F1"); -}); - -addTest("Word movement [PARTIAL]", "03", "1", function() { - var text = "This is a line with example text"; - initEditor(text); - sendKeys("www3w"); - assertPosition(0, 28); - sendKeys("b2b"); - assertPosition(0, 10); - sendKeys("3le"); - assertPosition(0, 18); -/* "ge" fails - sendKeys("2ge"); - assertPosition(0, 8); - TODO: What iskeyword behavior is assumed for Ace? - Need to test "b,w,ge,e,gE, B, W, E" behaviors - sendKeys("ddaThis is-a line, with special/separated/words (and some more).", "Esc"); - sendKeys("$4b"); - assertPosition(0, 21); -*/ -}); - -addTest("Moving to the start or end of a line", "03", "2", function() { - var text = " This is a line with example text"; - var textLength = text.length; - initEditor(text); - sendKeys("$"); - assertPosition(0, 36); - sendKeys("0"); - assertPosition(0, 0); - sendKeys("End"); - assertPosition(0, 36); - sendKeys("Home"); - assertPosition(0, 0); - sendKeys("^"); - assertPosition(0, 5); - sendKeys("$^"); - assertPosition(0, 5); - sendKeys("ddaA young intelligent turtle\nFound programming UNIX a hurdle", "Esc", "k0"); - assertPosition(0, 0); - sendKeys("2$"); - assertPosition(1, 30); -}); - -addTest("Moving to a character [PARTIAL]", "03", "3", function() { - var text = "To err is human. To really foul up you need a computer."; - initEditor(repeat(text, 2)); - sendKeys("fh"); - assertPosition(0, 10); - sendKeys("3fl"); - assertPosition(0, 31); - sendKeys("Fh"); - assertPosition(0, 10); - sendKeys("Fh"); - assertPosition(0, 10); - sendKeys("2tn"); - assertPosition(0, 39); - sendKeys("Th"); - assertPosition(0, 11); - sendKeys("tn"); - assertPosition(0, 13); - sendKeys(";"); - assertPosition(0, 39); -/* Problem with mockrenderer? - sendKeys(";"); - assertPosition(0, 39); -*/ - sendKeys(","); - assertPosition(0, 15); - sendKeys("0f", "Esc", "w"); - assertPosition(0, 3); -}); - -addTest("Matching a parenthesis", "03", "4", function() { - var text = "if (a == (b * c) / d)\nif [a == [b * c] / d]\nif {a == {b * c} / d}"; - initEditor(text); - sendKeys("%"); - assertPosition(0, 20); - sendKeys("%"); - assertPosition(0, 3); - sendKeys("0j%"); - assertPosition(1, 20); - sendKeys("%"); - assertPosition(1, 3); - sendKeys("0j%"); - assertPosition(2, 20); - sendKeys("%"); - assertPosition(2, 3); -}); - -addTest("Moving to a specific line [PARTIAL]", "03", "5", function() { - var text = "first line of a file\n" + repeat("text text text text\n", 8) + "last line of a file"; - initEditor(text); - sendKeys("7G"); - assertPosition(6, 0); - sendKeys("gg"); - assertPosition(0, 0); - sendKeys("G"); - assertPosition(9, 0); -/* % motion fails - sendKeys("50%"); - assertPosition(4, 0); - sendKeys("90%"); - assertPosition(8, 0); -"H, M, L" motion supported, but mockrenderer.js has no 'getScrollBottomRow', etc. - sendKeys("L"); - assertPosition(9, 0); - sendKeys("M"); - assertPosition(4, 0); - sendKeys("H"); - assertPosition(0, 0); -*/ -}); - -addTest("Telling where you are [PARTIAL]", "03", "6", function() { - // Ctrl-G, :set commands not implemented? -}); - -addTest("Scrolling around [PARTIAL]", "03", "7", function() { - /* Ctrl-D, Ctrl-U, Ctrl-E, Ctrl-Y, zz, zt, zb cannot be tested with mockrenderer - var text = repeat("some text\n", 4) + "\n123456\n7890\n" + repeat("\nexample", 4); - initEditor(text); - sendKeys("Ctrl-D"); - */ -}); - -addTest("Simple searches [PARTIAL]", "03", "8", function() { - var text = repeat("To find the word #include\n", 10); - initEditor(text); -/* Search fails, (is a command line really necessary for this to work? - sendKeys("/include", "Return"); - assertPosition(0, 18); - sendKeys("/#include", "Return"); - assertPosition(1, 17); - sendKeys("nnn"); - assertPosition(4, 17); - sendKeys("3n"); - assertPosition(7, 17); - sendKeys("?word", "Return"); - assertPosition(7, 12); - sendKeys("N"); - assertPosition(8, 12); - sendKeys("/#include", "Return"); - assertPosition(8, 17); - sendKeys("N"); - assertPosition(7, 17); - //Skipping ':set ignorecase' and ':set noignorecase' - //Skipping search history - //TODO additional search tests -*" and "#" searches fail, no getPixelPosition in mockrenderer - sendKeys("gg*"); - assertPosition(1, 5); -*/ -}); - -addTest("Simple search patterns [PARTIAL]", "03", "9", function() { -}); - -addTest("Using marks [PARTIAL]", "03", "10", function() { -/* '', ``, Ctrl-O, Ctrl-I fail - var text1 = "example text\n" - var text2 = "line 33 text\n" - var text3 = "There you are\n" - var text = repeat(text1, 32) + text2 + repeat(text1, 2) + text3 + text1; - initEditor(text); - sendKeys("G"); - sendKeys("``"); - assertPosition(0, 0); - sendKeys("``"); - assertPosition(37, 0); - sendKeys("10k``"); - assertPosition(0, 0); - sendKeys("33G"); - assertPosition(33, 0); - sendKeys("/^The"); - assertPosition((36, 0); - sendKeys("Ctrl-O"); - assertPosition(33, 0); - sendKeys("Ctrl-O"); - assertPosition(0, 0); - sendKeys("Ctrl-I"); - assertPosition(33, 0); - sendKeys("Ctrl-I"); - assertPosition(36, 0); - sendKeys(":0$msG$me's"); - assertPosition(0, 0); - sendKeys("`s"); - assertPosition(0, 11); - sendKeys("'e"); - assertPosition(36, 0); - sendKeys("`e"): - assertPosition(36, 11); -*/ -}); - -addTest("Operators and motions [PARTIAL]", "04", "1", function() { - initEditor("To err is human. To really foul up you need a computer."); - sendKeys("5wd4w"); - assertContent("To err is human. you need a computer."); -/* "de" fails - sendKeys("d2e"); - assertContent("To err is human. a computer."); - - sendKeys("2hd$"); - assertContent("To err is human"); -*/ -}); - -addTest("Changing text [PARTIAL]", "04", "2", function() { - initEditor("To err is human"); -/* -// "cw" fails -// sendKeys("wc2wbe", "Esc"); -// assertContent("To be human"); - sendKeys("uccabc def", "Esc"); - assertContent("abc def"); - sendKeys("0c$123", "Esc"); - assertContent("123"); - sendKeys("hx"); - assertContent("13"); - sendKeys("X"); - assertContent("3"); - sendKeys("a 2 1", "Esc", "0wD"); - assertContent("3 "); - sendKeys("a2 1", "Esc", "0wC4 5", "Esc"); - assertContent("3 4 5"); - sendKeys("0ws6", "Esc"); - assertContent("3 6 5"); - sendKeys("S1 3 2", "Esc"); - assertContent("1 3 2"); - sendKeys("$a4 6 5", "Esc", "03d2w"); - assertContent(""); - sendKeys("athere is somerhing grong here", "Esc", "0rTww4lrtwrw"); - assertContent("There is something wrong here"); - sendKeys("03w5rx"); - assertContent("There is something xxxxx here"); -// "r" fails - also replaces trailing space - sendKeys("r", "Return"); - assertContent("There is something xxxx\n here"); - //TODO - 4r -*/ -}); - -addTest("Repeating a change [PARTIAL]", "04", "3", function() { -/* - initEditor("To generate a table of contents"); - sendKeys("ff<.f<."); //strangeness after this - assertContent("To generate a table of contents");; - sendKeys("dd"); - assertContent(""); -sendKeys("Esc", "Esc"); - sendKeys("afind"); - var text = "find the first \"four\"\n" + - "change the word to \"five\"\n" + - "find the next \"four\"\n" + - "repeat the change to \"five\"\n" + - "find the next \"four\"\n" + - "repeat the change\n" + - "etc."; - sendKeys(text); -assertContent(text); - sendKeys("Esc"); - sendKeys("0"); -// search doesn't work with mockrenderer - sendKeys("/four", "", "cwfive", "Esc", "n.n."); - text.replace(/four/g, "five"); - assertContent(text); -*/ -}); - -addTest("Visual mode [PARTIAL]", "04", "4", function() { -}); - -addTest("Moving text [PARTIAL]", "04", "5", function() { -}); - -addTest("Copying text [PARTIAL]", "04", "6", function() { -}); - -addTest("Using the clipboard [PARTIAL]", "04", "7", function() { -}); - -addTest("Text objects [PARTIAL]", "04", "8", function() { -}); - -addTest("Replace mode [PARTIAL]", "04", "9", function() { -}); - -tests.name = "vim_test.js"; - -module.exports = tests; - -}); if (typeof module !== "undefined" && module === require.main) { require("asyncjs").test.testcase(module.exports).exec(); diff --git a/tool/update_deps.js b/tool/update_deps.js index d230fde6..09ea8766 100644 --- a/tool/update_deps.js +++ b/tool/update_deps.js @@ -122,7 +122,7 @@ var deps = { vim: { fetch: function(){ var rootHref = "https://raw.githubusercontent.com/codemirror/CodeMirror/master/" - var fileMap = {"keymap/vim.js": "keyboard/vim2.js", "test/vim_test.js": "keyboard/vim2_test.js"}; + var fileMap = {"keymap/vim.js": "keyboard/vim.js", "test/vim_test.js": "keyboard/vim_test.js"}; async.forEach(Object.keys(fileMap), function(x, next) { download(rootHref + x, function(e, d) { d = d.replace(/^\(function.*{[^{}]+^}[^{}]+{/m, "define(function(require, exports, module) {"); From b4d2cf810d414bf7803f03bfddd03bd3df314938 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 11 Nov 2014 18:02:43 +0400 Subject: [PATCH 069/315] fix failing test --- lib/ace/mode/behaviour/behaviour_test.js | 3 --- lib/ace/multi_select.js | 3 ++- lib/ace/test/all_browser.js | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/ace/mode/behaviour/behaviour_test.js b/lib/ace/mode/behaviour/behaviour_test.js index 33a09c83..ded22ccb 100644 --- a/lib/ace/mode/behaviour/behaviour_test.js +++ b/lib/ace/mode/behaviour/behaviour_test.js @@ -53,9 +53,6 @@ var testRanges = function(str) { }; module.exports = { - - name: "ACE multi_select.js", - "test: cstyle": function() { function testValue(line) { assert.equal(editor.getValue(), Array(4).join(line + "\n")); diff --git a/lib/ace/multi_select.js b/lib/ace/multi_select.js index 04d644ce..729d5253 100644 --- a/lib/ace/multi_select.js +++ b/lib/ace/multi_select.js @@ -552,7 +552,8 @@ var Editor = require("./editor").Editor; var pos = anchor == this.multiSelect.anchor ? range.cursor == range.start ? range.end : range.start : range.cursor; - if (!isSamePoint(this.session.$clipPositionToDocument(pos.row, pos.column), anchor)) + if (pos.row != anchor.row + || this.session.$clipPositionToDocument(pos.row, pos.column).column != anchor.column) this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange()); } }; diff --git a/lib/ace/test/all_browser.js b/lib/ace/test/all_browser.js index f05148e9..9b5742dd 100644 --- a/lib/ace/test/all_browser.js +++ b/lib/ace/test/all_browser.js @@ -25,7 +25,6 @@ var testNames = [ "ace/keyboard/emacs_test", "ace/keyboard/keybinding_test", "ace/keyboard/vim_test", - "ace/keyboard/vim2_test", "ace/layer/text_test", "ace/lib/event_emitter_test", "ace/mode/coffee/parser_test", From a40060c1ae180bb96bda4c158238b6ce5a41e790 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 11 Nov 2014 18:45:23 +0400 Subject: [PATCH 070/315] increase timeout for intermittently failing placeholder_test.js --- lib/ace/edit_session.js | 6 ++---- lib/ace/placeholder_test.js | 3 ++- lib/ace/test/all_browser.js | 1 + 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 3ef0d64c..932a9e3d 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -969,10 +969,8 @@ var EditSession = function(text, mode) { try { this.$worker = this.$mode.createWorker(this); } catch (e) { - if (typeof console == "object") { - console.log("Could not load worker"); - console.log(e); - } + if (typeof console == "object" && console.error) + console.log("Could not load worker", e); this.$worker = null; } }; diff --git a/lib/ace/placeholder_test.js b/lib/ace/placeholder_test.js index 97e561fd..f674ccff 100644 --- a/lib/ace/placeholder_test.js +++ b/lib/ace/placeholder_test.js @@ -43,6 +43,7 @@ var assert = require("./test/assertions"); var JavaScriptMode = require("./mode/javascript").Mode; var PlaceHolder = require("./placeholder").PlaceHolder; var UndoManager = require("./undomanager").UndoManager; +require("./multi_select") module.exports = { @@ -89,7 +90,7 @@ module.exports = { editor.insert('v'); assert.equal(session.doc.getValue(), "var v$a = 10;\nconsole.log(v$a, v$a);"); next(); - }, 10); + }, 20); }, "test: detaching placeholder" : function() { diff --git a/lib/ace/test/all_browser.js b/lib/ace/test/all_browser.js index 9b5742dd..1ffbb01a 100644 --- a/lib/ace/test/all_browser.js +++ b/lib/ace/test/all_browser.js @@ -47,6 +47,7 @@ var testNames = [ "ace/multi_select_test", "ace/mouse/mouse_handler_test", "ace/occur_test", + "ace/placeholder_test", "ace/range_test", "ace/range_list_test", "ace/search_test", From 2f32304c2ef890ad85cb6b21cbc4dedd841c30a6 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 20 Nov 2014 20:22:27 +0400 Subject: [PATCH 071/315] update vim.js --- kitchen-sink.html | 5 +- lib/ace/editor.js | 2 - lib/ace/keyboard/vim.js | 1112 +++++++++++++++++----------------- lib/ace/keyboard/vim_test.js | 112 +++- 4 files changed, 651 insertions(+), 580 deletions(-) diff --git a/kitchen-sink.html b/kitchen-sink.html index b2ab3577..65fe2a2a 100644 --- a/kitchen-sink.html +++ b/kitchen-sink.html @@ -12,8 +12,8 @@ --> - + + @@ -96,7 +96,6 @@ diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 13aa2f60..59b136b1 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -2476,7 +2476,6 @@ var Editor = function(renderer, session) { **/ this.undo = function() { this.$blockScrolling++; - this.session.$syncInformUndoManager(); this.session.getUndoManager().undo(); this.$blockScrolling--; this.renderer.scrollCursorIntoView(null, 0.5); @@ -2488,7 +2487,6 @@ var Editor = function(renderer, session) { **/ this.redo = function() { this.$blockScrolling++; - this.session.$syncInformUndoManager(); this.session.getUndoManager().redo(); this.$blockScrolling--; this.renderer.scrollCursorIntoView(null, 0.5); diff --git a/lib/ace/keyboard/vim.js b/lib/ace/keyboard/vim.js index 0e860db1..cbf3dda3 100644 --- a/lib/ace/keyboard/vim.js +++ b/lib/ace/keyboard/vim.js @@ -62,7 +62,7 @@ define(function(require, exports, module) { 'use strict'; - /* function log() { + function log() { var d = ""; function format(p) { if (typeof p != "object") @@ -83,7 +83,7 @@ define(function(require, exports, module) { d+= f+" " } console.log(d) - } */ + } var Range = require("../range").Range; var EventEmitter = require("../lib/event_emitter").EventEmitter; var dom = require("../lib/dom"); @@ -297,8 +297,10 @@ define(function(require, exports, module) { ranges.push(ranges.splice(primIndex, 1)[0]); } sel.toSingleRange(ranges[0].clone()); + var session = this.ace.session; for (var i = 0; i < ranges.length; i++) { - sel.addRange(ranges[i]); + var range = session.$clipRangeToDocument(ranges[i]); // todo why ace doesn't do this? + sel.addRange(range); } }; this.setSelection = function(a, h, options) { @@ -951,10 +953,14 @@ dom.importCssString(".normal-mode .ace_cursor{\ // Operator-Motion dual commands { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }}, { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }}, - { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, operatorMotionArgs: { visualLine: true }}, - { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, operatorMotionArgs: { visualLine: true }}, - { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, operatorMotionArgs: { visualLine: true }}, - { keys: '~', type: 'operatorMotion', operator: 'changeCase', operatorArgs: { shouldMoveCursor: true }, motion: 'moveByCharacters', motionArgs: { forward: true }}, + { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: '~', type: 'operatorMotion', operator: 'changeCase', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: 'normal'}, + { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual'}, { keys: '', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' }, // Actions { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }}, @@ -965,7 +971,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' }, - { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank' }}, + { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank'}, context: 'normal' }, + { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'startOfSelectedArea' }, context: 'visual' }, { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' }, { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, { keys: 'v', type: 'action', action: 'toggleVisualMode' }, @@ -1069,7 +1076,6 @@ dom.importCssString(".normal-mode .ace_cursor{\ CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); cm.on('keypress', handleKeyPress); cm.on('keydown', handleKeyDown); - CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); } function leaveVimMode(cm) { @@ -1350,7 +1356,9 @@ dom.importCssString(".normal-mode .ace_cursor{\ visualLine: false, visualBlock: false, lastSelection: null, - lastPastedText: null + lastPastedText: null, + sel: { + } }; } return cm.state.vim; @@ -1406,6 +1414,10 @@ dom.importCssString(".normal-mode .ace_cursor{\ // Add user defined key bindings. exCommandDispatcher.map(lhs, rhs, ctx); }, + unmap: function(lhs, ctx) { + // remove user defined key bindings. + exCommandDispatcher.unmap(lhs, ctx); + }, setOption: setOption, getOption: getOption, defineOption: defineOption, @@ -1529,6 +1541,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ } catch (e) { // clear VIM state in case it's in a bad state. cm.state.vim = undefined; + maybeInitVimState(cm); throw e; } }); @@ -2032,13 +2045,13 @@ dom.importCssString(".normal-mode .ace_cursor{\ var operator = inputState.operator; var operatorArgs = inputState.operatorArgs || {}; var registerName = inputState.registerName; - var selectionEnd = copyCursor(cm.getCursor('head')); - var selectionStart = copyCursor(cm.getCursor('anchor')); - // The difference between cur and selection cursors are that cur is - // being operated on and ignores that there is a selection. - var curStart = copyCursor(selectionEnd); - var curOriginal = copyCursor(curStart); - var curEnd; + var sel = vim.sel; + // TODO: Make sure cm and vim selections are identical outside visual mode. + var origHead = copyCursor(vim.visualMode ? sel.head: cm.getCursor('head')); + var origAnchor = copyCursor(vim.visualMode ? sel.anchor : cm.getCursor('anchor')); + var oldHead = copyCursor(origHead); + var oldAnchor = copyCursor(origAnchor); + var newHead, newAnchor; var repeat; if (operator) { this.recordLastEdit(vim, inputState); @@ -2065,7 +2078,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ motionArgs.repeat = repeat; clearInputState(cm); if (motion) { - var motionResult = motions[motion](cm, motionArgs, vim); + var motionResult = motions[motion](cm, origHead, motionArgs, vim); vim.lastMotion = motions[motion]; if (!motionResult) { return; @@ -2078,159 +2091,139 @@ dom.importCssString(".normal-mode .ace_cursor{\ recordJumpPosition(cm, cachedCursor, motionResult); delete jumpList.cachedCursor; } else { - recordJumpPosition(cm, curOriginal, motionResult); + recordJumpPosition(cm, origHead, motionResult); } } if (motionResult instanceof Array) { - curStart = motionResult[0]; - curEnd = motionResult[1]; + newAnchor = motionResult[0]; + newHead = motionResult[1]; } else { - curEnd = motionResult; + newHead = motionResult; } // TODO: Handle null returns from motion commands better. - if (!curEnd) { - curEnd = Pos(curStart.line, curStart.ch); + if (!newHead) { + newHead = copyCursor(origHead); } if (vim.visualMode) { - // Check if the selection crossed over itself. Will need to shift - // the start point if that happened. - // offset is set to -1 or 1 to shift the curEnd - // left or right - var offset = 0; - if (cursorIsBefore(selectionStart, selectionEnd) && - (cursorEqual(selectionStart, curEnd) || - cursorIsBefore(curEnd, selectionStart))) { - // The end of the selection has moved from after the start to - // before the start. We will shift the start right by 1. - selectionStart.ch += 1; - offset = -1; - } else if (cursorIsBefore(selectionEnd, selectionStart) && - (cursorEqual(selectionStart, curEnd) || - cursorIsBefore(selectionStart, curEnd))) { - // The opposite happened. We will shift the start left by 1. - selectionStart.ch -= 1; - offset = 1; - } - // in case of visual Block selectionStart and curEnd - // may not be on the same line, - // Also, In case of v_o this should not happen. - if (!vim.visualBlock && !(motionResult instanceof Array)) { - curEnd.ch += offset; - } - if (vim.lastHPos != Infinity) { - vim.lastHPos = curEnd.ch; - } - selectionEnd = curEnd; - selectionStart = (motionResult instanceof Array) ? curStart : selectionStart; - if (vim.visualLine) { - if (cursorIsBefore(selectionStart, selectionEnd)) { - selectionStart.ch = 0; - - var lastLine = cm.lastLine(); - if (selectionEnd.line > lastLine) { - selectionEnd.line = lastLine; - } - selectionEnd.ch = lineLength(cm, selectionEnd.line); - } else { - selectionEnd.ch = 0; - selectionStart.ch = lineLength(cm, selectionStart.line); - } - } else if (vim.visualBlock) { - // Select a block and - // return the diagonally opposite end. - selectionStart = selectBlock(cm, selectionEnd); - } - if (!vim.visualBlock) { - cm.setSelection(selectionStart, selectionEnd); + newHead = clipCursorToContent(cm, newHead, true); + if (newAnchor) { + newAnchor = clipCursorToContent(cm, newAnchor, true); } + newAnchor = newAnchor || oldAnchor; + sel.anchor = newAnchor; + sel.head = newHead; + updateCmSelection(cm); updateMark(cm, vim, '<', - cursorIsBefore(selectionStart, selectionEnd) ? selectionStart - : selectionEnd); + cursorIsBefore(newAnchor, newHead) ? newAnchor + : newHead); updateMark(cm, vim, '>', - cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd - : selectionStart); + cursorIsBefore(newAnchor, newHead) ? newHead + : newAnchor); } else if (!operator) { - curEnd = clipCursorToContent(cm, curEnd); - cm.setCursor(curEnd.line, curEnd.ch); + newHead = clipCursorToContent(cm, newHead); + cm.setCursor(newHead.line, newHead.ch); } } - if (operator) { - var inverted = false; - vim.lastMotion = null; - var lastSelection = vim.lastSelection; - operatorArgs.repeat = repeat; // Indent in visual mode needs this. - if (vim.visualMode) { - curStart = selectionStart; - curEnd = selectionEnd; - motionArgs.inclusive = true; - operatorArgs.shouldMoveCursor = false; - } - // Swap start and end if motion was backward. - if (curEnd && cursorIsBefore(curEnd, curStart)) { - var tmp = curStart; - curStart = curEnd; - curEnd = tmp; - inverted = true; - } else if (!curEnd) { - curEnd = copyCursor(curStart); - } - if (motionArgs.inclusive && !vim.visualMode) { - // Move the selection end one to the right to include the last - // character. - curEnd.ch++; - } - if (operatorArgs.selOffset) { + if (operatorArgs.lastSel) { // Replaying a visual mode operation - curEnd.line = curStart.line + operatorArgs.selOffset.line; - if (operatorArgs.selOffset.line) {curEnd.ch = operatorArgs.selOffset.ch; } - else { curEnd.ch = curStart.ch + operatorArgs.selOffset.ch; } - // In case of blockwise visual - if (lastSelection && lastSelection.visualBlock) { - var block = lastSelection.visualBlock; - var width = block.width; - var height = block.height; - curEnd = Pos(curStart.line + height, curStart.ch + width); - // selectBlock creates a 'proper' rectangular block. - // We do not want that in all cases, so we manually set selections. - var selections = []; - for (var i = curStart.line; i < curEnd.line; i++) { - var anchor = Pos(i, curStart.ch); - var head = Pos(i, curEnd.ch); - var range = {anchor: anchor, head: head}; - selections.push(range); - } - cm.setSelections(selections); - var blockSelected = true; + newAnchor = oldAnchor; + var lastSel = operatorArgs.lastSel; + var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line); + var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch); + if (lastSel.visualLine) { + // Linewise Visual mode: The same number of lines. + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); + } else if (lastSel.visualBlock) { + // Blockwise Visual mode: The same number of lines and columns. + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset); + } else if (lastSel.head.line == lastSel.anchor.line) { + // Normal Visual mode within one line: The same number of characters. + newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset); + } else { + // Normal Visual mode with several lines: The same number of lines, in the + // last line the same number of characters as in the last line the last time. + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); } + vim.visualMode = true; + vim.visualLine = lastSel.visualLine; + vim.visualBlock = lastSel.visualBlock; + sel = vim.sel = { + anchor: newAnchor, + head: newHead + }; + updateCmSelection(cm); } else if (vim.visualMode) { - var selOffset = Pos(); - selOffset.line = curEnd.line - curStart.line; - if (selOffset.line) { selOffset.ch = curEnd.ch; } - else { selOffset.ch = curEnd.ch - curStart.ch; } - operatorArgs.selOffset = selOffset; + operatorArgs.lastSel = { + anchor: copyCursor(sel.anchor), + head: copyCursor(sel.head), + visualBlock: vim.visualBlock, + visualLine: vim.visualLine + }; } - var linewise = motionArgs.linewise || - (vim.visualMode && vim.visualLine) || - operatorArgs.linewise; - if (linewise) { - // Expand selection to entire line. - expandSelectionToLine(cm, curStart, curEnd); - } else if (motionArgs.forward) { - // Clip to trailing newlines only if the motion goes forward. - clipToLine(cm, curStart, curEnd); + var curStart, curEnd, linewise, mode; + var cmSel; + if (vim.visualMode) { + // Init visual op + curStart = cursorMin(sel.head, sel.anchor); + curEnd = cursorMax(sel.head, sel.anchor); + linewise = vim.visualLine || operatorArgs.linewise; + mode = vim.visualBlock ? 'block' : + linewise ? 'line' : + 'char'; + cmSel = makeCmSelection(cm, { + anchor: curStart, + head: curEnd + }, mode); + if (linewise) { + var ranges = cmSel.ranges; + if (mode == 'block') { + // Linewise operators in visual block mode extend to end of line + for (var i = 0; i < ranges.length; i++) { + ranges[i].head.ch = lineLength(cm, ranges[i].head.line); + } + } else if (mode == 'line') { + ranges[0].head = Pos(ranges[0].head.line + 1, 0); + } + } + } else { + // Init motion op + curStart = copyCursor(newAnchor || oldAnchor); + curEnd = copyCursor(newHead || oldHead); + if (cursorIsBefore(curEnd, curStart)) { + var tmp = curStart; + curStart = curEnd; + curEnd = tmp; + } + linewise = motionArgs.linewise || operatorArgs.linewise; + if (linewise) { + // Expand selection to entire line. + expandSelectionToLine(cm, curStart, curEnd); + } else if (motionArgs.forward) { + // Clip to trailing newlines only if the motion goes forward. + clipToLine(cm, curStart, curEnd); + } + mode = 'char'; + var exclusive = !motionArgs.inclusive || linewise; + cmSel = makeCmSelection(cm, { + anchor: curStart, + head: curEnd + }, mode, exclusive); } + cm.setSelections(cmSel.ranges, cmSel.primary); + vim.lastMotion = null; + operatorArgs.repeat = repeat; // For indent in visual mode. operatorArgs.registerName = registerName; // Keep track of linewise as it affects how paste and change behave. operatorArgs.linewise = linewise; - if (!vim.visualBlock && !blockSelected) { - cm.setSelection(curStart, curEnd); - } - operators[operator](cm, operatorArgs, vim, curStart, - curEnd, curOriginal); + var operatorMoveTo = operators[operator]( + cm, operatorArgs, cmSel.ranges, oldAnchor, newHead); if (vim.visualMode) { exitVisualMode(cm); } + if (operatorMoveTo) { + cm.setCursor(operatorMoveTo); + } } }, recordLastEdit: function(vim, inputState, actionCommand) { @@ -2249,7 +2242,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ */ // All of the functions below return Cursor objects. var motions = { - moveToTopLine: function(cm, motionArgs) { + moveToTopLine: function(cm, _head, motionArgs) { var line = getUserVisibleLines(cm).top + motionArgs.repeat -1; return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); }, @@ -2258,17 +2251,17 @@ dom.importCssString(".normal-mode .ace_cursor{\ var line = Math.floor((range.top + range.bottom) * 0.5); return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); }, - moveToBottomLine: function(cm, motionArgs) { + moveToBottomLine: function(cm, _head, motionArgs) { var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1; return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); }, - expandToLine: function(cm, motionArgs) { + expandToLine: function(_cm, head, motionArgs) { // Expands forward to end of line, and then to next line if repeat is // >1. Does not handle backward motion! - var cur = cm.getCursor(); + var cur = head; return Pos(cur.line + motionArgs.repeat - 1, Infinity); }, - findNext: function(cm, motionArgs) { + findNext: function(cm, _head, motionArgs) { var state = getSearchState(cm); var query = state.getQuery(); if (!query) { @@ -2280,7 +2273,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ highlightSearchMatches(cm, query); return findNext(cm, prev/** prev */, query, motionArgs.repeat); }, - goToMark: function(cm, motionArgs, vim) { + goToMark: function(cm, _head, motionArgs, vim) { var mark = vim.marks[motionArgs.selectedCharacter]; if (mark) { var pos = mark.find(); @@ -2288,22 +2281,19 @@ dom.importCssString(".normal-mode .ace_cursor{\ } return null; }, - moveToOtherHighlightedEnd: function(cm, motionArgs, vim) { - var ranges = cm.listSelections(); - var curEnd = cm.getCursor('head'); - var curStart = ranges[0].anchor; - var curIndex = cursorEqual(ranges[0].head, curEnd) ? ranges.length-1 : 0; - if (motionArgs.sameLine && vim.visualBlock) { - curStart = Pos(curEnd.line, ranges[curIndex].anchor.ch); - curEnd = Pos(ranges[curIndex].head.line, curEnd.ch); + moveToOtherHighlightedEnd: function(cm, _head, motionArgs, vim) { + if (vim.visualBlock && motionArgs.sameLine) { + var sel = vim.sel; + return [ + clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)), + clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch)) + ]; } else { - curStart = ranges[curIndex].anchor; + return ([vim.sel.head, vim.sel.anchor]); } - cm.setCursor(curEnd); - return ([curEnd, curStart]); }, - jumpToMark: function(cm, motionArgs, vim) { - var best = cm.getCursor(); + jumpToMark: function(cm, head, motionArgs, vim) { + var best = head; for (var i = 0; i < motionArgs.repeat; i++) { var cursor = best; for (var key in vim.marks) { @@ -2340,14 +2330,14 @@ dom.importCssString(".normal-mode .ace_cursor{\ } return best; }, - moveByCharacters: function(cm, motionArgs) { - var cur = cm.getCursor(); + moveByCharacters: function(_cm, head, motionArgs) { + var cur = head; var repeat = motionArgs.repeat; var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat; return Pos(cur.line, ch); }, - moveByLines: function(cm, motionArgs, vim) { - var cur = cm.getCursor(); + moveByLines: function(cm, head, motionArgs, vim) { + var cur = head; var endCh = cur.ch; // Depending what our last motion was, we may want to do different // things. If our last motion was moving vertically, we want to @@ -2382,8 +2372,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left; return Pos(line, endCh); }, - moveByDisplayLines: function(cm, motionArgs, vim) { - var cur = cm.getCursor(); + moveByDisplayLines: function(cm, head, motionArgs, vim) { + var cur = head; switch (vim.lastMotion) { case this.moveByDisplayLines: case this.moveByScroll: @@ -2410,16 +2400,16 @@ dom.importCssString(".normal-mode .ace_cursor{\ vim.lastHPos = res.ch; return res; }, - moveByPage: function(cm, motionArgs) { + moveByPage: function(cm, head, motionArgs) { // CodeMirror only exposes functions that move the cursor page down, so // doing this bad hack to move the cursor and move it back. evalInput // will move the cursor to where it should be in the end. - var curStart = cm.getCursor(); + var curStart = head; var repeat = motionArgs.repeat; return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page'); }, - moveByParagraph: function(cm, motionArgs) { - var line = cm.getCursor().line; + moveByParagraph: function(cm, head, motionArgs) { + var line = head.line; var repeat = motionArgs.repeat; var inc = motionArgs.forward ? 1 : -1; for (var i = 0; i < repeat; i++) { @@ -2434,16 +2424,16 @@ dom.importCssString(".normal-mode .ace_cursor{\ } return Pos(line, 0); }, - moveByScroll: function(cm, motionArgs, vim) { + moveByScroll: function(cm, head, motionArgs, vim) { var scrollbox = cm.getScrollInfo(); var curEnd = null; var repeat = motionArgs.repeat; if (!repeat) { repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight()); } - var orig = cm.charCoords(cm.getCursor(), 'local'); + var orig = cm.charCoords(head, 'local'); motionArgs.repeat = repeat; - var curEnd = motions.moveByDisplayLines(cm, motionArgs, vim); + var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim); if (!curEnd) { return null; } @@ -2451,11 +2441,11 @@ dom.importCssString(".normal-mode .ace_cursor{\ cm.scrollTo(null, scrollbox.top + dest.top - orig.top); return curEnd; }, - moveByWords: function(cm, motionArgs) { - return moveToWord(cm, motionArgs.repeat, !!motionArgs.forward, + moveByWords: function(cm, head, motionArgs) { + return moveToWord(cm, head, motionArgs.repeat, !!motionArgs.forward, !!motionArgs.wordEnd, !!motionArgs.bigWord); }, - moveTillCharacter: function(cm, motionArgs) { + moveTillCharacter: function(cm, _head, motionArgs) { var repeat = motionArgs.repeat; var curEnd = moveToCharacter(cm, repeat, motionArgs.forward, motionArgs.selectedCharacter); @@ -2465,26 +2455,26 @@ dom.importCssString(".normal-mode .ace_cursor{\ curEnd.ch += increment; return curEnd; }, - moveToCharacter: function(cm, motionArgs) { + moveToCharacter: function(cm, head, motionArgs) { var repeat = motionArgs.repeat; recordLastCharacterSearch(0, motionArgs); return moveToCharacter(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || cm.getCursor(); + motionArgs.selectedCharacter) || head; }, - moveToSymbol: function(cm, motionArgs) { + moveToSymbol: function(cm, head, motionArgs) { var repeat = motionArgs.repeat; return findSymbol(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || cm.getCursor(); + motionArgs.selectedCharacter) || head; }, - moveToColumn: function(cm, motionArgs, vim) { + moveToColumn: function(cm, head, motionArgs, vim) { var repeat = motionArgs.repeat; // repeat is equivalent to which column we want to move to! vim.lastHPos = repeat - 1; - vim.lastHSPos = cm.charCoords(cm.getCursor(),'div').left; + vim.lastHSPos = cm.charCoords(head,'div').left; return moveToColumn(cm, repeat); }, - moveToEol: function(cm, motionArgs, vim) { - var cur = cm.getCursor(); + moveToEol: function(cm, head, motionArgs, vim) { + var cur = head; vim.lastHPos = Infinity; var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity); var end=cm.clipPos(retval); @@ -2492,15 +2482,15 @@ dom.importCssString(".normal-mode .ace_cursor{\ vim.lastHSPos = cm.charCoords(end,'div').left; return retval; }, - moveToFirstNonWhiteSpaceCharacter: function(cm) { + moveToFirstNonWhiteSpaceCharacter: function(cm, head) { // Go to the start of the line where the text begins, or the end for // whitespace-only lines - var cursor = cm.getCursor(); + var cursor = head; return Pos(cursor.line, findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))); }, - moveToMatchedSymbol: function(cm) { - var cursor = cm.getCursor(); + moveToMatchedSymbol: function(cm, head) { + var cursor = head; var line = cursor.line; var ch = cursor.ch; var lineText = cm.getLine(line); @@ -2521,11 +2511,10 @@ dom.importCssString(".normal-mode .ace_cursor{\ return cursor; } }, - moveToStartOfLine: function(cm) { - var cursor = cm.getCursor(); - return Pos(cursor.line, 0); + moveToStartOfLine: function(_cm, head) { + return Pos(head.line, 0); }, - moveToLineOrEdgeOfDocument: function(cm, motionArgs) { + moveToLineOrEdgeOfDocument: function(cm, _head, motionArgs) { var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine(); if (motionArgs.repeatIsExplicit) { lineNum = motionArgs.repeat - cm.getOption('firstLineNumber'); @@ -2533,7 +2522,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ return Pos(lineNum, findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))); }, - textObjectManipulation: function(cm, motionArgs) { + textObjectManipulation: function(cm, head, motionArgs) { // TODO: lots of possible exceptions that can be thrown here. Try da( // outside of a () block. @@ -2562,9 +2551,9 @@ dom.importCssString(".normal-mode .ace_cursor{\ var tmp; if (mirroredPairs[character]) { - tmp = selectCompanionObject(cm, character, inclusive); + tmp = selectCompanionObject(cm, head, character, inclusive); } else if (selfPaired[character]) { - tmp = findBeginningAndEnd(cm, character, inclusive); + tmp = findBeginningAndEnd(cm, head, character, inclusive); } else if (character === 'W') { tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, true /** bigWord */); @@ -2586,7 +2575,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ } }, - repeatLastCharacterSearch: function(cm, motionArgs) { + repeatLastCharacterSearch: function(cm, head, motionArgs) { var lastSearch = vimGlobalState.lastChararacterSearch; var repeat = motionArgs.repeat; var forward = motionArgs.forward === lastSearch.forward; @@ -2596,141 +2585,107 @@ dom.importCssString(".normal-mode .ace_cursor{\ var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter); if (!curEnd) { cm.moveH(increment, 'char'); - return cm.getCursor(); + return head; } curEnd.ch += increment; return curEnd; } }; + function fillArray(val, times) { + var arr = []; + for (var i = 0; i < times; i++) { + arr.push(val); + } + return arr; + } + /** + * An operator acts on a text selection. It receives the list of selections + * as input. The corresponding CodeMirror selection is guaranteed to + * match the input selection. + */ var operators = { - change: function(cm, operatorArgs, vim) { - var selections = cm.listSelections(); - var start = selections[0], end = selections[selections.length-1]; - var curStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; - var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; - var text = cm.getSelection(); - var visualBlock = vim.visualBlock; - if (vim.lastSelection && !vim.visualMode) { - visualBlock = vim.lastSelection.visualBlock ? true : visualBlock; - } - var lastInsertModeChanges = vimGlobalState.macroModeState.lastInsertModeChanges; - lastInsertModeChanges.inVisualBlock = visualBlock; - var replacement = new Array(selections.length).join('1').split('1'); - // save the selectionEnd mark - var selectionEnd = vim.marks[">"] && vim.marks[">"].find(); - if (!selectionEnd) { - selectionEnd = cm.getCursor("head"); - } - vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'change', text, - operatorArgs.linewise); - if (operatorArgs.linewise) { - // 'C' in visual block extends the block till eol for all lines - if (visualBlock){ - var startLine = curStart.line; - while (startLine <= curEnd.line) { - var endCh = lineLength(cm, startLine); - var head = Pos(startLine, endCh); - var anchor = Pos(startLine, curStart.ch); - startLine++; - cm.replaceRange('', anchor, head); - } - } else { - // Push the next line back down, if there is a next line. - replacement = '\n'; - if (curEnd.line == curStart.line && curEnd.line == cm.lastLine()) { - replacement = ''; - } - cm.replaceRange(replacement, curStart, curEnd); - cm.indentLine(curStart.line, 'smart'); - // null ch so setCursor moves to end of line. - curStart.ch = null; - cm.setCursor(curStart); - } - } else { - // Exclude trailing whitespace if the range is not all whitespace. - var text = cm.getRange(curStart, curEnd); + change: function(cm, args, ranges) { + var finalHead, text; + var vim = cm.state.vim; + vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock; + if (!vim.visualMode) { + var anchor = ranges[0].anchor, + head = ranges[0].head; + text = cm.getRange(anchor, head); if (!isWhiteSpaceString(text)) { + // Exclude trailing whitespace if the range is not all whitespace. var match = (/\s+$/).exec(text); if (match) { - curEnd = offsetCursor(curEnd, 0, - match[0].length); + head = offsetCursor(head, 0, - match[0].length); + text = text.slice(0, - match[0].length); } } - if (visualBlock) { - cm.replaceSelections(replacement); - } else { - cm.setCursor(curStart); - cm.replaceRange('', curStart, curEnd); + var wasLastLine = head.line - 1 == cm.lastLine(); + cm.replaceRange('', anchor, head); + if (args.linewise && !wasLastLine) { + // Push the next line back down, if there is a next line. + CodeMirror.commands.newlineAndIndent(cm); + // null ch so setCursor moves to end of line. + anchor.ch = null; } + finalHead = anchor; + } else { + text = cm.getSelection(); + var replacement = fillArray('', ranges.length); + cm.replaceSelections(replacement); + finalHead = cursorMin(ranges[0].head, ranges[0].anchor); } - vim.marks['>'] = cm.setBookmark(selectionEnd); - actions.enterInsertMode(cm, {}, cm.state.vim); + vimGlobalState.registerController.pushText( + args.registerName, 'change', text, + args.linewise, ranges.length > 1); + actions.enterInsertMode(cm, {head: finalHead}, cm.state.vim); }, // delete is a javascript keyword. - 'delete': function(cm, operatorArgs, vim) { - var selections = cm.listSelections(); - var start = selections[0], end = selections[selections.length-1]; - var curStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; - var curEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; - // Save the '>' mark before cm.replaceRange clears it. - var selectionEnd, selectionStart; - var blockwise = vim.visualBlock; - if (vim.visualMode) { - selectionEnd = vim.marks['>'].find(); - selectionStart = vim.marks['<'].find(); - } else if (vim.lastSelection) { - selectionEnd = vim.lastSelection.curStartMark.find(); - selectionStart = vim.lastSelection.curEndMark.find(); - blockwise = vim.lastSelection.visualBlock; - } - var text = cm.getSelection(); - vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'delete', text, - operatorArgs.linewise, blockwise); - var replacement = new Array(selections.length).join('1').split('1'); - // If the ending line is past the last line, inclusive, instead of - // including the trailing \n, include the \n before the starting line - if (operatorArgs.linewise && - curEnd.line == cm.lastLine() && curStart.line == curEnd.line) { - if (curEnd.line == 0) { - curStart.ch = 0; + 'delete': function(cm, args, ranges) { + var finalHead, text; + var vim = cm.state.vim; + if (!vim.visualBlock) { + var anchor = ranges[0].anchor, + head = ranges[0].head; + if (args.linewise && + head.line != cm.firstLine() && + anchor.line == cm.lastLine() && + anchor.line == head.line - 1) { + // Special case for dd on last line (and first line). + if (anchor.line == cm.firstLine()) { + anchor.ch = 0; + } else { + anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1)); + } } - else { - var tmp = copyCursor(curEnd); - curStart.line--; - curStart.ch = lineLength(cm, curStart.line); - curEnd = tmp; + text = cm.getRange(anchor, head); + cm.replaceRange('', anchor, head); + finalHead = anchor; + if (args.linewise) { + finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor); } - cm.replaceRange('', curStart, curEnd); } else { + text = cm.getSelection(); + var replacement = fillArray('', ranges.length); cm.replaceSelections(replacement); + finalHead = ranges[0].anchor; } - // restore the saved bookmark - if (selectionEnd) { - var curStartMark = cm.setBookmark(selectionStart); - var curEndMark = cm.setBookmark(selectionEnd); - if (vim.visualMode) { - vim.marks['<'] = curStartMark; - vim.marks['>'] = curEndMark; - } else { - vim.lastSelection.curStartMark = curStartMark; - vim.lastSelection.curEndMark = curEndMark; - } - } - if (operatorArgs.linewise) { - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); - } else { - cm.setCursor(curStart); - } + vimGlobalState.registerController.pushText( + args.registerName, 'delete', text, + args.linewise, vim.visualBlock); + return finalHead; }, - indent: function(cm, operatorArgs, vim, curStart, curEnd) { - var startLine = curStart.line; - var endLine = curEnd.line; + indent: function(cm, args, ranges) { + var vim = cm.state.vim; + var startLine = ranges[0].anchor.line; + var endLine = vim.visualBlock ? + ranges[ranges.length - 1].anchor.line : + ranges[0].head.line; // In visual mode, n> shifts the selection right n times, instead of // shifting n lines right once. - var repeat = (vim.visualMode) ? operatorArgs.repeat : 1; - if (operatorArgs.linewise) { + var repeat = (vim.visualMode) ? args.repeat : 1; + if (args.linewise) { // The only way to delete a newline is to delete until the start of // the next line, so in linewise mode evalInput will include the next // line. We don't want this in indent, so we go back a line. @@ -2738,17 +2693,15 @@ dom.importCssString(".normal-mode .ace_cursor{\ } for (var i = startLine; i <= endLine; i++) { for (var j = 0; j < repeat; j++) { - cm.indentLine(i, operatorArgs.indentRight); + cm.indentLine(i, args.indentRight); } } - cm.setCursor(curStart); - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor); }, - changeCase: function(cm, operatorArgs, _vim, _curStart, _curEnd, _curOriginal) { + changeCase: function(cm, args, ranges, oldAnchor, newHead) { var selections = cm.getSelections(); - var ranges = cm.listSelections(); var swapped = []; - var toLower = operatorArgs.toLower; + var toLower = args.toLower; for (var j = 0; j < selections.length; j++) { var toSwap = selections[j]; var text = ''; @@ -2766,18 +2719,26 @@ dom.importCssString(".normal-mode .ace_cursor{\ swapped.push(text); } cm.replaceSelections(swapped); - var curStart = ranges[0].anchor; - var curEnd = ranges[0].head; - if (!operatorArgs.shouldMoveCursor) { - cm.setCursor(cursorIsBefore(curStart, curEnd) ? curStart : curEnd); + if (args.shouldMoveCursor){ + return newHead; + } else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) { + return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor); + } else if (args.linewise){ + return oldAnchor; + } else { + return cursorMin(ranges[0].anchor, ranges[0].head); } }, - yank: function(cm, operatorArgs, vim, _curStart, _curEnd, curOriginal) { + yank: function(cm, args, ranges, oldAnchor) { + var vim = cm.state.vim; var text = cm.getSelection(); + var endPos = vim.visualMode + ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor) + : oldAnchor; vimGlobalState.registerController.pushText( - operatorArgs.registerName, 'yank', - text, operatorArgs.linewise, vim.visualBlock); - cm.setCursor(curOriginal); + args.registerName, 'yank', + text, args.linewise, vim.visualBlock); + return endPos; } }; @@ -2869,41 +2830,40 @@ dom.importCssString(".normal-mode .ace_cursor{\ vim.insertMode = true; vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1; var insertAt = (actionArgs) ? actionArgs.insertAt : null; - if (vim.visualMode) { - var selections = getSelectedAreaRange(cm, vim); - var selectionStart = selections[0]; - var selectionEnd = selections[1]; - } + var sel = vim.sel; + var head = actionArgs.head || cm.getCursor('head'); + var height = cm.listSelections().length; if (insertAt == 'eol') { - var cursor = cm.getCursor(); - cursor = Pos(cursor.line, lineLength(cm, cursor.line)); - cm.setCursor(cursor); + head = Pos(head.line, lineLength(cm, head.line)); } else if (insertAt == 'charAfter') { - cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); + head = offsetCursor(head, 0, 1); } else if (insertAt == 'firstNonBlank') { - if (vim.visualMode && !vim.visualBlock) { - if (selectionEnd.line < selectionStart.line) { - cm.setCursor(selectionEnd); + head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head); + } else if (insertAt == 'startOfSelectedArea') { + if (!vim.visualBlock) { + if (sel.head.line < sel.anchor.line) { + head = sel.head; } else { - selectionStart = Pos(selectionStart.line, 0); - cm.setCursor(selectionStart); + head = Pos(sel.anchor.line, 0); } - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); - } else if (vim.visualBlock) { - selectionEnd = Pos(selectionEnd.line, selectionStart.ch); - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); } else { - cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm)); + head = Pos( + Math.min(sel.head.line, sel.anchor.line), + Math.min(sel.head.ch, sel.anchor.ch)); + height = Math.abs(sel.head.line - sel.anchor.line) + 1; } } else if (insertAt == 'endOfSelectedArea') { - if (vim.visualBlock) { - selectionStart = Pos(selectionStart.line, selectionEnd.ch); - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); - } else if (selectionEnd && selectionEnd.line < selectionStart.line) { - selectionEnd = Pos(selectionStart.line, 0); - cm.setCursor(selectionEnd); + if (!vim.visualBlock) { + if (sel.head.line >= sel.anchor.line) { + head = offsetCursor(sel.head, 0, 1); + } else { + head = Pos(sel.anchor.line, 0); + } + } else { + head = Pos( + Math.min(sel.head.line, sel.anchor.line), + Math.max(sel.head.ch + 1, sel.anchor.ch)); + height = Math.abs(sel.head.line - sel.anchor.line) + 1; } } else if (insertAt == 'inplace') { if (vim.visualMode){ @@ -2929,128 +2889,68 @@ dom.importCssString(".normal-mode .ace_cursor{\ if (vim.visualMode) { exitVisualMode(cm); } + selectForInsert(cm, head, height); }, toggleVisualMode: function(cm, actionArgs, vim) { var repeat = actionArgs.repeat; - var curStart = cm.getCursor(); - var curEnd; - var selections = cm.listSelections(); + var anchor = cm.getCursor(); + var head; // TODO: The repeat should actually select number of characters/lines // equal to the repeat times the size of the previous visual // operation. if (!vim.visualMode) { + // Entering visual mode vim.visualMode = true; vim.visualLine = !!actionArgs.linewise; vim.visualBlock = !!actionArgs.blockwise; - if (vim.visualLine) { - curStart.ch = 0; - curEnd = clipCursorToContent( - cm, Pos(curStart.line + repeat - 1, lineLength(cm, curStart.line)), + head = clipCursorToContent( + cm, Pos(anchor.line, anchor.ch + repeat - 1), true /** includeLineBreak */); - } else { - curEnd = clipCursorToContent( - cm, Pos(curStart.line, curStart.ch + repeat), - true /** includeLineBreak */); - } - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""}); + vim.sel = { + anchor: anchor, + head: head + }; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); + updateCmSelection(cm); + updateMark(cm, vim, '<', cursorMin(anchor, head)); + updateMark(cm, vim, '>', cursorMax(anchor, head)); + } else if (vim.visualLine ^ actionArgs.linewise || + vim.visualBlock ^ actionArgs.blockwise) { + // Toggling between modes + vim.visualLine = !!actionArgs.linewise; + vim.visualBlock = !!actionArgs.blockwise; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); + updateCmSelection(cm); } else { - curStart = cm.getCursor('anchor'); - curEnd = cm.getCursor('head'); - if (vim.visualLine) { - if (actionArgs.blockwise) { - // This means Ctrl-V pressed in linewise visual - vim.visualBlock = true; - selectBlock(cm, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'blockwise'}); - } else if (!actionArgs.linewise) { - // v pressed in linewise, switch to characterwise visual mode - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual'}); - } else { - exitVisualMode(cm); - } - vim.visualLine = false; - } else if (vim.visualBlock) { - if (actionArgs.linewise) { - // Shift-V pressed in blockwise visual mode - vim.visualLine = true; - curStart = Pos(selections[0].anchor.line, 0); - curEnd = Pos(selections[selections.length-1].anchor.line, lineLength(cm, selections[selections.length-1].anchor.line)); - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'linewise'}); - } else if (!actionArgs.blockwise) { - // v pressed in blockwise mode, Switch to characterwise - if (curEnd != selections[0].head) { - curStart = selections[0].anchor; - } else { - curStart = selections[selections.length-1].anchor; - } - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual'}); - } else { - exitVisualMode(cm); - } - vim.visualBlock = false; - } else if (actionArgs.linewise) { - // Shift-V pressed in characterwise visual mode. Switch to linewise - // visual mode instead of exiting visual mode. - vim.visualLine = true; - curStart.ch = cursorIsBefore(curStart, curEnd) ? 0 : - lineLength(cm, curStart.line); - curEnd.ch = cursorIsBefore(curStart, curEnd) ? - lineLength(cm, curEnd.line) : 0; - cm.setSelection(curStart, curEnd); - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: "linewise"}); - } else if (actionArgs.blockwise) { - vim.visualBlock = true; - selectBlock(cm, curEnd); - CodeMirror.signal(cm, 'vim-mode-change', {mode: 'visual', subMode: 'blockwise'}); - } else { - exitVisualMode(cm); - } + exitVisualMode(cm); } - updateMark(cm, vim, '<', cursorIsBefore(curStart, curEnd) ? curStart - : curEnd); - updateMark(cm, vim, '>', cursorIsBefore(curStart, curEnd) ? curEnd - : curStart); }, reselectLastSelection: function(cm, _actionArgs, vim) { - var curStart = vim.marks['<'].find(); - var curEnd = vim.marks['>'].find(); var lastSelection = vim.lastSelection; + if (vim.visualMode) { + updateLastSelection(cm, vim); + } if (lastSelection) { - // Set the selections as per last selection - var selectionStart = lastSelection.curStartMark.find(); - var selectionEnd = lastSelection.curEndMark.find(); - var blockwise = lastSelection.visualBlock; - // update last selection - updateLastSelection(cm, vim, curStart, curEnd); - if (blockwise) { - cm.setCursor(selectionStart); - selectionStart = selectBlock(cm, selectionEnd); - } else { - cm.setSelection(selectionStart, selectionEnd); - selectionStart = cm.getCursor('anchor'); - selectionEnd = cm.getCursor('head'); + var anchor = lastSelection.anchorMark.find(); + var head = lastSelection.headMark.find(); + if (!anchor || !head) { + // If the marks have been destroyed due to edits, do nothing. + return; } - if (vim.visualMode) { - updateMark(cm, vim, '<', cursorIsBefore(selectionStart, selectionEnd) ? selectionStart - : selectionEnd); - updateMark(cm, vim, '>', cursorIsBefore(selectionStart, selectionEnd) ? selectionEnd - : selectionStart); - } - // Last selection is updated now + vim.sel = { + anchor: anchor, + head: head + }; vim.visualMode = true; - if (lastSelection.visualLine) { - vim.visualLine = true; - vim.visualBlock = false; - } else if (lastSelection.visualBlock) { - vim.visualLine = false; - vim.visualBlock = true; - } else { - vim.visualBlock = vim.visualLine = false; - } - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""}); + vim.visualLine = lastSelection.visualLine; + vim.visualBlock = lastSelection.visualBlock; + updateCmSelection(cm); + updateMark(cm, vim, '<', cursorMin(anchor, head)); + updateMark(cm, vim, '>', cursorMax(anchor, head)); + CodeMirror.signal(cm, 'vim-mode-change', { + mode: 'visual', + subMode: vim.visualLine ? 'linewise' : + vim.visualBlock ? 'blockwise' : ''}); } }, joinLines: function(cm, actionArgs, vim) { @@ -3067,18 +2967,19 @@ dom.importCssString(".normal-mode .ace_cursor{\ Infinity)); } var finalCh = 0; - cm.operation(function() { - for (var i = curStart.line; i < curEnd.line; i++) { - finalCh = lineLength(cm, curStart.line); - var tmp = Pos(curStart.line + 1, - lineLength(cm, curStart.line + 1)); - var text = cm.getRange(curStart, tmp); - text = text.replace(/\n\s*/g, ' '); - cm.replaceRange(text, curStart, tmp); - } - var curFinalPos = Pos(curStart.line, finalCh); - cm.setCursor(curFinalPos); - }); + for (var i = curStart.line; i < curEnd.line; i++) { + finalCh = lineLength(cm, curStart.line); + var tmp = Pos(curStart.line + 1, + lineLength(cm, curStart.line + 1)); + var text = cm.getRange(curStart, tmp); + text = text.replace(/\n\s*/g, ' '); + cm.replaceRange(text, curStart, tmp); + } + var curFinalPos = Pos(curStart.line, finalCh); + cm.setCursor(curFinalPos); + if (vim.visualMode) { + exitVisualMode(cm); + } }, newLineAndEnterInsertMode: function(cm, actionArgs, vim) { vim.insertMode = true; @@ -3174,7 +3075,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ var emptyStrings = new Array(selections.length).join('1').split('1'); // save the curEnd marker before it get cleared due to cm.replaceRange. if (vim.lastSelection) { - lastSelectionCurEnd = vim.lastSelection.curEndMark.find(); + lastSelectionCurEnd = vim.lastSelection.headMark.find(); } // push the previously selected text to unnamed register vimGlobalState.registerController.unnamedRegister.setText(selectedText); @@ -3198,7 +3099,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ } // restore the the curEnd marker if(lastSelectionCurEnd) { - vim.lastSelection.curEndMark = cm.setBookmark(lastSelectionCurEnd); + vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd); } if (linewise) { curPosFinal.ch=0; @@ -3240,10 +3141,10 @@ dom.importCssString(".normal-mode .ace_cursor{\ } } } - cm.setCursor(curPosFinal); if (vim.visualMode) { exitVisualMode(cm); } + cm.setCursor(curPosFinal); }, undo: function(cm, actionArgs) { cm.operation(function() { @@ -3372,8 +3273,18 @@ dom.importCssString(".normal-mode .ace_cursor{\ return ret; } function offsetCursor(cur, offsetLine, offsetCh) { + if (typeof offsetLine === 'object') { + offsetCh = offsetLine.ch; + offsetLine = offsetLine.line; + } return Pos(cur.line + offsetLine, cur.ch + offsetCh); } + function getOffset(anchor, head) { + return { + line: head.line - anchor.line, + ch: head.line - anchor.line + }; + } function commandMatches(keys, keyMap, context, inputState) { // Partial matches are not applied. They inform the key handler // that the current key sequence is a subsequence of a valid key @@ -3446,9 +3357,15 @@ dom.importCssString(".normal-mode .ace_cursor{\ return false; } function cursorMin(cur1, cur2) { + if (arguments.length > 2) { + cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1)); + } return cursorIsBefore(cur1, cur2) ? cur1 : cur2; } function cursorMax(cur1, cur2) { + if (arguments.length > 2) { + cur2 = cursorMax.apply(undefined, Array.prototype.slice.call(arguments, 1)); + } return cursorIsBefore(cur1, cur2) ? cur2 : cur1; } function cursorIsBetween(cur1, cur2, cur3) { @@ -3516,11 +3433,19 @@ dom.importCssString(".normal-mode .ace_cursor{\ selections.push(range); } primIndex = head.line == lastLine ? selections.length - 1 : 0; - cm.setSelections(selections, primIndex); + cm.setSelections(selections); selectionEnd.ch = headCh; base.ch = baseCh; return base; } + function selectForInsert(cm, head, height) { + var sel = []; + for (var i = 0; i < height; i++) { + var lineHead = offsetCursor(head, i, 0); + sel.push({anchor: lineHead, head: lineHead}); + } + cm.setSelections(sel, 0); + } // getIndex returns the index of the cursor in the selections. function getIndex(ranges, cursor, end) { for (var i = 0; i < ranges.length; i++) { @@ -3561,8 +3486,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ } cm.setSelections(selections); } else { - var start = lastSelection.curStartMark.find(); - var end = lastSelection.curEndMark.find(); + var start = lastSelection.anchorMark.find(); + var end = lastSelection.headMark.find(); var line = end.line - start.line; var ch = end.ch - start.ch; selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch}; @@ -3581,36 +3506,28 @@ dom.importCssString(".normal-mode .ace_cursor{\ return getCurrentSelectedAreaRange(); } } - function updateLastSelection(cm, vim, selectionStart, selectionEnd) { - if (!selectionStart || !selectionEnd) { - selectionStart = vim.marks['<'].find() || cm.getCursor('anchor'); - selectionEnd = vim.marks['>'].find() || cm.getCursor('head'); - } + // Updates the previous selection with the current selection's values. This + // should only be called in visual mode. + function updateLastSelection(cm, vim) { + var anchor = vim.sel.anchor; + var head = vim.sel.head; // To accommodate the effect of lastPastedText in the last selection if (vim.lastPastedText) { - selectionEnd = cm.posFromIndex(cm.indexFromPos(selectionStart) + vim.lastPastedText.length); + head = cm.posFromIndex(cm.indexFromPos(anchor) + vim.lastPastedText.length); vim.lastPastedText = null; } - var ranges = cm.listSelections(); - // This check ensures to set the cursor - // position where we left off in previous selection - var swap = getIndex(ranges, selectionStart, 'head') > -1; - if (vim.visualBlock) { - var height = Math.abs(selectionStart.line - selectionEnd.line)+1; - var width = Math.abs(selectionStart.ch - selectionEnd.ch); - var block = {height: height, width: width}; - } - // can't use selection state here because yank has already reset its cursor - // Also, Bookmarks make the visual selections robust to edit operations - vim.lastSelection = {'curStartMark': cm.setBookmark(swap ? selectionEnd : selectionStart), - 'curEndMark': cm.setBookmark(swap ? selectionStart : selectionEnd), + vim.lastSelection = {'anchorMark': cm.setBookmark(anchor), + 'headMark': cm.setBookmark(head), + 'anchor': copyCursor(anchor), + 'head': copyCursor(head), 'visualMode': vim.visualMode, 'visualLine': vim.visualLine, - 'visualBlock': block}; + 'visualBlock': vim.visualBlock}; } function expandSelection(cm, start, end) { - var head = cm.getCursor('head'); - var anchor = cm.getCursor('anchor'); + var sel = cm.state.vim.sel; + var head = sel.head; + var anchor = sel.anchor; var tmp; if (cursorIsBefore(end, start)) { tmp = end; @@ -3623,9 +3540,75 @@ dom.importCssString(".normal-mode .ace_cursor{\ } else { anchor = cursorMin(start, anchor); head = cursorMax(head, end); + head = offsetCursor(head, 0, -1); + if (head.ch == -1 && head.line != cm.firstLine()) { + head = Pos(head.line - 1, lineLength(cm, head.line - 1)); + } } return [anchor, head]; } + /** + * Updates the CodeMirror selection to match the provided vim selection. + * If no arguments are given, it uses the current vim selection state. + */ + function updateCmSelection(cm, sel, mode) { + var vim = cm.state.vim; + sel = sel || vim.sel; + var mode = mode || + vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char'; + var cmSel = makeCmSelection(cm, sel, mode); + cm.setSelections(cmSel.ranges, cmSel.primary); + updateFakeCursor(cm); + } + function makeCmSelection(cm, sel, mode, exclusive) { + var head = copyCursor(sel.head); + var anchor = copyCursor(sel.anchor); + if (mode == 'char') { + var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; + var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; + head = offsetCursor(sel.head, 0, headOffset); + anchor = offsetCursor(sel.anchor, 0, anchorOffset); + return { + ranges: [{anchor: anchor, head: head}], + primary: 0 + }; + } else if (mode == 'line') { + if (!cursorIsBefore(sel.head, sel.anchor)) { + anchor.ch = 0; + + var lastLine = cm.lastLine(); + if (head.line > lastLine) { + head.line = lastLine; + } + head.ch = lineLength(cm, head.line); + } else { + head.ch = 0; + anchor.ch = lineLength(cm, anchor.line); + } + return { + ranges: [{anchor: anchor, head: head}], + primary: 0 + }; + } else if (mode == 'block') { + var top = Math.min(anchor.line, head.line), + left = Math.min(anchor.ch, head.ch), + bottom = Math.max(anchor.line, head.line), + right = Math.max(anchor.ch, head.ch) + 1; + var height = bottom - top + 1; + var primary = head.line == top ? 0 : height - 1; + var ranges = []; + for (var i = 0; i < height; i++) { + ranges.push({ + anchor: Pos(top + i, left), + head: Pos(top + i, right) + }); + } + return { + ranges: ranges, + primary: primary + }; + } + } function getHead(cm) { var cur = cm.getCursor('head'); if (cm.getSelection().length == 1) { @@ -3636,22 +3619,20 @@ dom.importCssString(".normal-mode .ace_cursor{\ return cur; } - function exitVisualMode(cm) { + /** + * If moveHead is set to false, the CodeMirror selection will not be + * touched. The caller assumes the responsibility of putting the cursor + * in the right place. + */ + function exitVisualMode(cm, moveHead) { var vim = cm.state.vim; - var selectionStart = cm.getCursor('anchor'); - var selectionEnd = cm.getCursor('head'); - // hack to place the cursor at the right place - // in case of visual block - if (vim.visualBlock && (cursorIsBefore(selectionStart, selectionEnd))) { - selectionEnd.ch--; + if (moveHead !== false) { + cm.setCursor(clipCursorToContent(cm, vim.sel.head)); } updateLastSelection(cm, vim); vim.visualMode = false; vim.visualLine = false; vim.visualBlock = false; - if (!cursorEqual(selectionStart, selectionEnd)) { - cm.setCursor(clipCursorToContent(cm, selectionEnd)); - } CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); if (vim.fakeCursor) { vim.fakeCursor.clear(); @@ -3981,6 +3962,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ /** * @param {CodeMirror} cm CodeMirror object. + * @param {Pos} cur The position to start from. * @param {int} repeat Number of words to move past. * @param {boolean} forward True to search forward. False to search * backward. @@ -3990,8 +3972,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ * False if only alphabet characters count as part of the word. * @return {Cursor} The position the cursor should move to. */ - function moveToWord(cm, repeat, forward, wordEnd, bigWord) { - var cur = cm.getCursor(); + function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) { var curStart = copyCursor(cur); var words = []; if (forward && !wordEnd || !forward && wordEnd) { @@ -4091,8 +4072,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ // TODO: perhaps this finagling of start and end positions belonds // in codmirror/replaceRange? - function selectCompanionObject(cm, symb, inclusive) { - var cur = getHead(cm), start, end; + function selectCompanionObject(cm, head, symb, inclusive) { + var cur = head, start, end; var bracketRegexp = ({ '(': /[()]/, ')': /[()]/, @@ -4136,8 +4117,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ // Takes in a symbol and a cursor and tries to simulate text objects that // have identical opening and closing symbols // TODO support across multiple lines - function findBeginningAndEnd(cm, symb, inclusive) { - var cur = copyCursor(getHead(cm)); + function findBeginningAndEnd(cm, head, symb, inclusive) { + var cur = copyCursor(head); var line = cm.getLine(cur.line); var chars = line.split(''); var start, end, i, len; @@ -4560,13 +4541,6 @@ dom.importCssString(".normal-mode .ace_cursor{\ top: renderer.getFirstFullyVisibleRow(), bottom: renderer.getLastFullyVisibleRow() } - var scrollInfo = cm.getScrollInfo(); - var occludeToleranceTop = 6; - var occludeToleranceBottom = 10; - var from = cm.coordsChar({left:0, top: occludeToleranceTop + scrollInfo.top}, 'local'); - var bottomY = scrollInfo.clientHeight - occludeToleranceBottom + scrollInfo.top; - var to = cm.coordsChar({left:0, top: bottomY}, 'local'); - return {top: from.line, bottom: to.line}; } // Ex command handling @@ -5483,45 +5457,49 @@ dom.importCssString(".normal-mode .ace_cursor{\ // Cursor moved outside the context of an edit. Reset the change. lastChange.changes = []; } - } else { + } else if (!cm.curOp.isVimOp) { handleExternalSelection(cm, vim); } if (vim.visualMode) { - var from, head; - from = head = cm.getCursor('head'); - var anchor = cm.getCursor('anchor'); - var to = Pos(head.line, from.ch + (cursorIsBefore(anchor, head) ? -1 : 1)); - if (cursorIsBefore(to, from)) { - var temp = from; - from = to; - to = temp; - } - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } - vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); + updateFakeCursor(cm); } } - + function updateFakeCursor(cm) { + var vim = cm.state.vim; + var from = copyCursor(vim.sel.head); + var to = offsetCursor(from, 0, 1); + if (vim.fakeCursor) { + vim.fakeCursor.clear(); + } + vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); + } function handleExternalSelection(cm, vim) { var anchor = cm.getCursor('anchor'); var head = cm.getCursor('head'); // Enter or exit visual mode to match mouse selection. if (vim.visualMode && cursorEqual(head, anchor) && lineLength(cm, head.line) > head.ch) { - exitVisualMode(cm); - } else if (!cm.curOp.isVimOp && !vim.visualMode && !vim.insertMode && cm.somethingSelected()) { + exitVisualMode(cm, false); + } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) { vim.visualMode = true; vim.visualLine = false; CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); } - if (!cm.curOp.isVimOp) { - if (vim.visualMode) { - updateMark(cm, vim, '<', cursorMin(head, anchor)); - updateMark(cm, vim, '>', cursorMax(head, anchor)); - } else if (!vim.insertMode) { - // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse. - vim.lastHPos = cm.getCursor().ch; - } + if (vim.visualMode) { + // Bind CodeMirror selection model to vim selection model. + // Mouse selections are considered visual characterwise. + var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0; + var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0; + head = offsetCursor(head, 0, headOffset); + anchor = offsetCursor(anchor, 0, anchorOffset); + vim.sel = { + anchor: anchor, + head: head + }; + updateMark(cm, vim, '<', cursorMin(head, anchor)); + updateMark(cm, vim, '>', cursorMax(head, anchor)); + } else if (!vim.insertMode) { + // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse. + vim.lastHPos = cm.getCursor().ch; } } @@ -5613,19 +5591,21 @@ dom.importCssString(".normal-mode .ace_cursor{\ } return true; } - var curStart = cm.getCursor(); + var head = cm.getCursor('head'); var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; if (inVisualBlock) { // Set up block selection again for repeating the changes. var vim = cm.state.vim; - var block = vim.lastSelection.visualBlock; - var curEnd = Pos(curStart.line + block.height-1, curStart.ch); - cm.setCursor(curStart); - selectBlock(cm, curEnd); + var lastSel = vim.lastSelection; + var offset = getOffset(lastSel.anchor, lastSel.head); + selectForInsert(cm, head, offset.line + 1); repeat = cm.listSelections().length; - cm.setCursor(curStart); + cm.setCursor(head); } for (var i = 0; i < repeat; i++) { + if (inVisualBlock) { + cm.setCursor(offsetCursor(head, i, 0)); + } for (var j = 0; j < changes.length; j++) { var change = changes[j]; if (change instanceof InsertModeKey) { @@ -5635,10 +5615,9 @@ dom.importCssString(".normal-mode .ace_cursor{\ cm.replaceRange(change, cur, cur); } } - if (inVisualBlock) { - curStart.line++; - cm.setCursor(curStart); - } + } + if (inVisualBlock) { + cm.setCursor(offsetCursor(head, 0, 1)); } } @@ -5683,6 +5662,12 @@ dom.importCssString(".normal-mode .ace_cursor{\ o = cloneVimState(o); n[key] = o; }); + if (state.sel) { + n.sel = { + head: state.sel.head && copyCursor(state.sel.head), + anchor: state.sel.anchor && copyCursor(state.sel.anchor) + }; + } return n; } function multiSelectHandleKey(cm, key, origin) { @@ -5705,6 +5690,15 @@ dom.importCssString(".normal-mode .ace_cursor{\ cm.ace.forEachSelection(function() { var sel = cm.ace.selection; cm.state.vim.lastHPos = sel.$desiredColumn == null ? sel.lead.column : sel.$desiredColumn; + var head = cm.getCursor("head"); + var anchor = cm.getCursor("anchor"); + var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0; + var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0; + head = offsetCursor(head, 0, headOffset); + anchor = offsetCursor(anchor, 0, anchorOffset); + cm.state.vim.sel.head = head; + cm.state.vim.sel.anchor = anchor; + isHandled = handleKey(cm, key, origin); sel.$desiredColumn = cm.state.vim.lastHPos == -1 ? null : cm.state.vim.lastHPos; if (cm.virtualSelectionMode()) { @@ -5860,7 +5854,9 @@ dom.importCssString(".normal-mode .ace_cursor{\ // on mac, with some keyboard layouts (e.g swedish) ^ starts composition, we don't need it in normal mode updateMacCompositionHandlers: function(editor, enable) { var onCompositionUpdateOverride = function(text) { - if (util.currentMode !== "insert") { + var cm = editor.state.cm; + var vim = getVim(cm); + if (!vim.insertMode) { var el = this.textInput.getElement(); el.blur(); el.focus(); @@ -5870,7 +5866,9 @@ dom.importCssString(".normal-mode .ace_cursor{\ } }; var onCompositionStartOverride = function(text) { - if (util.currentMode === "insert") { + var cm = editor.state.cm; + var vim = getVim(cm); + if (!vim.insertMode) { this.onCompositionStartOrig(text); } }; @@ -5947,7 +5945,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ ace.off("beforeEndOperation", delayedExecAceCommand); var cmd = ace.state.cm.vimCmd; if (cmd) { - ace.execCommand(cmd.name, cmd.args); + ace.execCommand(cmd.exec ? cmd : cmd.name, cmd.args); } ace.curOp = ace.prevOp; } @@ -5956,5 +5954,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ ][(actionArgs.all ? 2 : 0) + (actionArgs.open ? 1 : 0)]); }, + exports.handler.defaultKeymap = defaultKeymap; + Vim.map("Y", "yy"); }); diff --git a/lib/ace/keyboard/vim_test.js b/lib/ace/keyboard/vim_test.js index 1fd8c320..8c9eeb65 100644 --- a/lib/ace/keyboard/vim_test.js +++ b/lib/ace/keyboard/vim_test.js @@ -72,6 +72,9 @@ function test(name, fn) { exports["test " + name] = fn; } +vim.CodeMirror.Vim.unmap("Y"); + + // cm.setBookmark({ch: 5, line: 0}) // cm.setBookmark({ch: 4, line: 0}) @@ -985,32 +988,36 @@ testVim('cc_multiply_repeat', function(cm, vim, helpers) { is(register.linewise); eq('vim-insert', cm.getOption('keyMap')); }); -testVim('cc_append', function(cm, vim, helpers) { +testVim('cc_should_not_append_to_document', function(cm, vim, helpers) { var expectedLineCount = cm.lineCount(); cm.setCursor(cm.lastLine(), 0); helpers.doKeys('c', 'c'); eq(expectedLineCount, cm.lineCount()); }); +function fillArray(val, times) { + var arr = []; + for (var i = 0; i < times; i++) { + arr.push(val); + } + return arr; +} testVim('c_visual_block', function(cm, vim, helpers) { cm.setCursor(0, 1); helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'c'); - var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); - replacement.pop(); + var replacement = fillArray('hello', 3); cm.replaceSelections(replacement); eq('1hello\n5hello\nahellofg', cm.getValue()); helpers.doKeys(''); cm.setCursor(2, 3); helpers.doKeys('', '2', 'k', 'h', 'C'); - replacement = new Array(cm.listSelections().length+1).join('world ').split(' '); - replacement.pop(); + replacement = fillArray('world', 3); cm.replaceSelections(replacement); eq('1hworld\n5hworld\nahworld', cm.getValue()); }, {value: '1234\n5678\nabcdefg'}); testVim('c_visual_block_replay', function(cm, vim, helpers) { cm.setCursor(0, 1); helpers.doKeys('', '2', 'j', 'l', 'c'); - var replacement = new Array(cm.listSelections().length+1).join('fo ').split(' '); - replacement.pop(); + var replacement = fillArray('fo', 3); cm.replaceSelections(replacement); eq('1fo4\n5fo8\nafodefg', cm.getValue()); helpers.doKeys(''); @@ -1019,6 +1026,17 @@ testVim('c_visual_block_replay', function(cm, vim, helpers) { eq('foo4\nfoo8\nfoodefg', cm.getValue()); }, {value: '1234\n5678\nabcdefg'}); +testVim('d_visual_block', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'd'); + eq('1\n5\nafg', cm.getValue()); +}, {value: '1234\n5678\nabcdefg'}); +testVim('D_visual_block', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('', '2', 'j', 'l', 'D'); + eq('1\n5\na', cm.getValue()); +}, {value: '1234\n5678\nabcdefg'}); + // Swapcase commands edit in place and do not modify registers. testVim('g~w_repeat', function(cm, vim, helpers) { // Assert that dw does delete newline if it should go to the next line, and @@ -1042,7 +1060,7 @@ testVim('g~g~', function(cm, vim, helpers) { var register = helpers.getRegisterController().getRegister(); eq('', register.toString()); is(!register.linewise); - eqPos({line: curStart.line, ch:0}, cm.getCursor()); + eqPos(curStart, cm.getCursor()); }, { value: ' word1\nword2\nword3\nword4\nword5\nword6' }); testVim('gu_and_gU', function(cm, vim, helpers) { var curStart = makeCursor(0, 7); @@ -1350,7 +1368,7 @@ testVim('a_eol', function(cm, vim, helpers) { helpers.assertCursorAt(0, lines[0].length); eq('vim-insert', cm.getOption('keyMap')); }); -testVim('a_endOfSelectedArea', function(cm, vim, helpers) { +testVim('A_endOfSelectedArea', function(cm, vim, helpers) { cm.setCursor(0, 0); helpers.doKeys('v', 'j', 'l'); helpers.doKeys('A'); @@ -1813,6 +1831,49 @@ testVim('visual', function(cm, vim, helpers) { helpers.doKeys('d'); eq('15', cm.getValue()); }, { value: '12345' }); +testVim('visual_yank', function(cm, vim, helpers) { + helpers.doKeys('v', '3', 'l', 'y'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('p'); + eq('aa te test for yank', cm.getValue()); +}, { value: 'a test for yank' }) +testVim('visual_w', function(cm, vim, helpers) { + helpers.doKeys('v', 'w'); + eq(cm.getSelection(), 'motion t'); +}, { value: 'motion test'}); +testVim('visual_initial_selection', function(cm, vim, helpers) { + cm.setCursor(0, 1); + helpers.doKeys('v'); + cm.getSelection('n'); +}, { value: 'init'}); +testVim('visual_crossover_left', function(cm, vim, helpers) { + cm.setCursor(0, 2); + helpers.doKeys('v', 'l', 'h', 'h'); + cm.getSelection('ro'); +}, { value: 'cross'}); +testVim('visual_crossover_left', function(cm, vim, helpers) { + cm.setCursor(0, 2); + helpers.doKeys('v', 'h', 'l', 'l'); + cm.getSelection('os'); +}, { value: 'cross'}); +testVim('visual_crossover_up', function(cm, vim, helpers) { + cm.setCursor(3, 2); + helpers.doKeys('v', 'j', 'k', 'k'); + eqPos(Pos(2, 2), cm.getCursor('head')); + eqPos(Pos(3, 3), cm.getCursor('anchor')); + helpers.doKeys('k'); + eqPos(Pos(1, 2), cm.getCursor('head')); + eqPos(Pos(3, 3), cm.getCursor('anchor')); +}, { value: 'cross\ncross\ncross\ncross\ncross\n'}); +testVim('visual_crossover_down', function(cm, vim, helpers) { + cm.setCursor(1, 2); + helpers.doKeys('v', 'k', 'j', 'j'); + eqPos(Pos(2, 3), cm.getCursor('head')); + eqPos(Pos(1, 2), cm.getCursor('anchor')); + helpers.doKeys('j'); + eqPos(Pos(3, 3), cm.getCursor('head')); + eqPos(Pos(1, 2), cm.getCursor('anchor')); +}, { value: 'cross\ncross\ncross\ncross\ncross\n'}); testVim('visual_exit', function(cm, vim, helpers) { helpers.doKeys('', 'l', 'j', 'j', ''); eqPos(cm.getCursor('anchor'), cm.getCursor('head')); @@ -1822,20 +1883,23 @@ testVim('visual_line', function(cm, vim, helpers) { helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd'); eq(' 4\n 5', cm.getValue()); }, { value: ' 1\n 2\n 3\n 4\n 5' }); -testVim('visual_block', function(cm, vim, helpers) { +testVim('visual_block_different_line_lengths', function(cm, vim, helpers) { // test the block selection with lines of different length // i.e. extending the selection // till the end of the longest line. helpers.doKeys('', 'l', 'j', 'j', '6', 'l', 'd'); helpers.doKeys('d', 'd', 'd', 'd'); eq('', cm.getValue()); +}, {value: '1234\n5678\nabcdefg'}); +testVim('visual_block_truncate_on_short_line', function(cm, vim, helpers) { // check for left side selection in case // of moving up to a shorter line. - cm.replaceRange('hello world\n{\nthis is\nsparta!', cm.getCursor()); + cm.replaceRange('', cm.getCursor()); cm.setCursor(3, 4); helpers.doKeys('', 'l', 'k', 'k', 'd'); eq('hello world\n{\ntis\nsa!', cm.getValue()); - cm.replaceRange('12345\n67891\nabcde', {line: 0, ch: 0}, {line: cm.lastLine(), ch: 6}); +}, {value: 'hello world\n{\nthis is\nsparta!'}); +testVim('visual_block_corners', function(cm, vim, helpers) { cm.setCursor(1, 2); helpers.doKeys('', '2', 'l', 'k'); // circle around the anchor @@ -1851,6 +1915,8 @@ testVim('visual_block', function(cm, vim, helpers) { helpers.doKeys('4', 'l'); selections = cm.getSelections(); eq('891cde', selections.join('')); +}, {value: '12345\n67891\nabcde'}); +testVim('visual_block_mode_switch', function(cm, vim, helpers) { // switch between visual modes cm.setCursor(1, 1); // blockwise to characterwise visual @@ -1865,7 +1931,7 @@ testVim('visual_block', function(cm, vim, helpers) { helpers.doKeys('V'); selections = cm.getSelections(); eq('67891\nabcde', selections.join('')); -}, {value: '1234\n5678\nabcdefg'}); +}, {value: '12345\n67891\nabcde'}); testVim('visual_block_crossing_short_line', function(cm, vim, helpers) { // visual block with long and short lines cm.setCursor(0, 3); @@ -1945,12 +2011,15 @@ testVim('reselect_visual_block', function(cm, vim, helpers) { helpers.doKeys('', 'k', 'h', ''); cm.setCursor(2, 1); helpers.doKeys('v', 'l', 'g', 'v'); - helpers.assertCursorAt(0, 1); + eqPos(Pos(1, 2), vim.sel.anchor); + eqPos(Pos(0, 1), vim.sel.head); // Ensure selection is done with visual block mode rather than one // continuous range. eq(cm.getSelections().join(''), '23oo') helpers.doKeys('g', 'v'); - helpers.assertCursorAt(2, 3); + eqPos(Pos(2, 1), vim.sel.anchor); + eqPos(Pos(2, 2), vim.sel.head); + helpers.doKeys(''); // Ensure selection of deleted range cm.setCursor(1, 1); helpers.doKeys('v', '', 'j', 'd', 'g', 'v'); @@ -1984,11 +2053,14 @@ testVim('o_visual', function(cm, vim, helpers) { testVim('o_visual_block', function(cm, vim, helpers) { cm.setCursor(0, 1); helpers.doKeys('','3','j','l','l', 'o'); - helpers.assertCursorAt(0, 1); + eqPos(Pos(3, 3), vim.sel.anchor); + eqPos(Pos(0, 1), vim.sel.head); helpers.doKeys('O'); - helpers.assertCursorAt(0, 4); + eqPos(Pos(3, 1), vim.sel.anchor); + eqPos(Pos(0, 3), vim.sel.head); helpers.doKeys('o'); - helpers.assertCursorAt(3, 1); + eqPos(Pos(0, 3), vim.sel.anchor); + eqPos(Pos(3, 1), vim.sel.head); }, { value: 'abcd\nefgh\nijkl\nmnop'}); testVim('changeCase_visual', function(cm, vim, helpers) { cm.setCursor(0, 0); @@ -2023,7 +2095,9 @@ testVim('changeCase_visual_block', function(cm, vim, helpers) { }, { value: 'abcdef\nghijkl\nmnopq\nfoo'}); testVim('visual_paste', function(cm, vim, helpers) { cm.setCursor(0, 0); - helpers.doKeys('v', 'l', 'l', 'y', 'j', 'v', 'l', 'p'); + helpers.doKeys('v', 'l', 'l', 'y'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('3', 'l', 'j', 'v', 'l', 'p'); helpers.assertCursorAt(1, 5); eq('this is a\nunithitest for visual paste', cm.getValue()); cm.setCursor(0, 0); From 332472ecc64918793346010c51a5a518355bcacd Mon Sep 17 00:00:00 2001 From: William Candillon Date: Sat, 22 Nov 2014 19:27:52 -0800 Subject: [PATCH 072/315] Remove references to built-in modules --- lib/ace/mode/xquery/modules.js | 4 ---- lib/ace/mode/xquery_worker.js | 1 - 2 files changed, 5 deletions(-) delete mode 100644 lib/ace/mode/xquery/modules.js diff --git a/lib/ace/mode/xquery/modules.js b/lib/ace/mode/xquery/modules.js deleted file mode 100644 index 9f341b49..00000000 --- a/lib/ace/mode/xquery/modules.js +++ /dev/null @@ -1,4 +0,0 @@ -define(function(require, exports, module) { - exports.Modules = -{ "http://xbrl.io/modules/bizql/components" : { "ns" : "http://xbrl.io/modules/bizql/components", "description" : "

    This module provides functionality for retrieving components.

    \n

    Components help organizing the facts contained in archives\n in smaller parts that \"make sense\" together. A component is identified\n with a CID (component ID).

    \n

    A component is made of networks (see the networks module) and hypercubes\n (see the hypercubes module).

    \n

    With this module, you can retrieve all components, all components belonging\n to one or several archives. You can retrieve the CID of a component or retrieve\n the components associated with a couple of CIDs.

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/archives", "prefix" : "archives" }, { "uri" : "http://xbrl.io/modules/bizql/components", "prefix" : "components" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://xbrl.io/modules/bizql/facts", "prefix" : "facts" }, { "uri" : "http://www.28msec.com/modules/mongodb", "prefix" : "mongo" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "cid", "qname" : "components:cid", "signature" : "($component-or-id as item()) as atomic", "description" : "

    Converts the input to a normalized component id (CID). The input\n can be either an CID, or an component object which contains an _id.

    \n", "summary" : "

    Converts the input to a normalized component id (CID).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "component-or-id", "type" : "item()", "occurrence" : null, "description" : "
    an component object or an CID.
    " } ], "returns" : { "type" : "atomic", "description" : "the normalized CID." }, "errors" : [ "components:INVALID_PARAMETER if the CID or component is not valid." ] }, { "isDocumented" : true, "arity" : 1, "name" : "components-for-archives", "qname" : "components:components-for-archives", "signature" : "($archive-or-ids as item()*) as object()*", "description" : "

    Retrieves all components that belong to the supplied archives.

    \n", "summary" : "

    Retrieves all components that belong to the supplied archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive-or-ids", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "all components in the archive with this AID." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "components", "qname" : "components:components", "signature" : "() as object()*", "description" : "

    Retrieves all components.

    \n", "summary" : "

    Retrieves all components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()*", "description" : "all components." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "components", "qname" : "components:components", "signature" : "($component-or-ids as item()*) as object()*", "description" : "

    Retrieves the components with the given CIDs.

    \n", "summary" : "

    Retrieves the components with the given CIDs.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "component-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    the CIDs or the components themselves.
    " } ], "returns" : { "type" : "object()*", "description" : "the components whose _id field matches one of these CIDs." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-abstract-primary-items-in-hypercubes", "qname" : "components:num-abstract-primary-items-in-hypercubes", "signature" : "($components-or-ids) as integer*", "description" : " Return the number of (distinct) abstract primary items being\n in a hypercube for each of the given components.\n", "summary" : "

    Return the number of (distinct) abstract primary items being\n in a hypercube for each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "components-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of primary items" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-concrete-primary-items-in-hypercubes", "qname" : "components:num-concrete-primary-items-in-hypercubes", "signature" : "($components-or-ids) as integer*", "description" : " Return the number of (distinct) concrete primary items being\n in a hypercube for each of the given components.\n", "summary" : "

    Return the number of (distinct) concrete primary items being\n in a hypercube for each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "components-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of primary items" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-concrete-primary-items-not-in-hypercubes", "qname" : "components:num-concrete-primary-items-not-in-hypercubes", "signature" : "($components-or-ids) as integer*", "description" : " Return the number of (distinct) concrete primary items not being\n in a hypercube for each of the given components.\n", "summary" : "

    Return the number of (distinct) concrete primary items not being\n in a hypercube for each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "components-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of primary items" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-distinct-abstract-primary-items-not-in-hypercubes", "qname" : "components:num-distinct-abstract-primary-items-not-in-hypercubes", "signature" : "($components-or-ids) as integer*", "description" : " Return the number of (distinct) abstract primary items not being\n in a hypercube for each of the given components.\n", "summary" : "

    Return the number of (distinct) abstract primary items not being\n in a hypercube for each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "components-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of primary items" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-domains", "qname" : "components:num-domains", "signature" : "($components-or-ids) as integer*", "description" : " Return the number of (distinct) domains in each of the given components.\n", "summary" : "

    Return the number of (distinct) domains in each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "components-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of domains" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-explicit-dimensions", "qname" : "components:num-explicit-dimensions", "signature" : "($components-or-ids) as integer*", "description" : " Return the number of (distinct) explicit dimensions in each of the given components.\n", "summary" : "

    Return the number of (distinct) explicit dimensions in each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "components-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of dimensions" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-hypercubes", "qname" : "components:num-hypercubes", "signature" : "($components-or-ids as item()*) as integer*", "description" : " Return the number of hypercubes in each of the given components.\n", "summary" : "

    Return the number of hypercubes in each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "components-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of hypercubes" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-members", "qname" : "components:num-members", "signature" : "($components-or-ids) as integer*", "description" : " Return the number of (distinct) members in each of the given components.\n", "summary" : "

    Return the number of (distinct) members in each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "components-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of members" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-networks", "qname" : "components:num-networks", "signature" : "($components-or-ids) as integer*", "description" : " Return the number of networks in each of the given components.\n", "summary" : "

    Return the number of networks in each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "components-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of networks" }, "errors" : [ ] } ], "variables" : [ { "name" : "components:col", "type" : "xs:string", "description" : " Name of the collection the components are stored in.\n" }, { "name" : "components:ARCHIVE", "type" : "xs:string", "description" : " Name of the field pointing to the archive.\n" } ] }, "http://jsound.io/modules/validate" : { "ns" : "http://jsound.io/modules/validate", "description" : " JSound simple validator.\n This is a JSONiq implemenation of the JSound (the schema for JSON) validator.\n", "sees" : [ ], "authors" : [ "Cezar Andrei" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://zorba.io/modules/fetch", "prefix" : "fetch" }, { "uri" : "http://jsoniq.org/functions", "prefix" : "jn" }, { "uri" : "http://jsound.io/modules/validate", "prefix" : "jsv" }, { "uri" : "http://jsound.io/modules/validate/map", "prefix" : "map" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 3, "name" : "jsd-valid", "qname" : "jsv:jsd-valid", "signature" : "($ns as string, $name as string, $instance as json-item()) as boolean", "description" : " Validates the $instance JSON item against the JSound type with name $name\n and namespace $ns, from the JSound schema definition $jsd.\n", "summary" : "

    Validates the $instance JSON item against the JSound type with name $name\n and namespace $ns, from the JSound schema definition $jsd.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "ns", "type" : "string", "occurrence" : null, "description" : "
    the namespace of the expected type
    " }, { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the expected type
    " }, { "name" : "instance", "type" : "json-item()", "occurrence" : null, "description" : "
    the instance to be validated
    " } ], "returns" : { "type" : "boolean", "description" : "true if the instance is valid, otherwise throws an error." }, "errors" : [ "jsv:BadJSoundFormat If the schema is not a valid JSound schema", "jsv:Invalid If the instance does not conform to the JSound schema", "zerr:ZXQP0025 If the schema namespace URI cannot be resolved.", "jn:JNDY0021 If the loaded schema is syntactically incorrect" ] }, { "isDocumented" : true, "arity" : 4, "name" : "jsd-valid", "qname" : "jsv:jsd-valid", "signature" : "($jsd as object(), $name as string, $ns as string, $instance as item()) as boolean", "description" : " Validates the $instance JSON item against the JSound type with name $name\n and namespace $ns, from the JSound schema definition $jsd.\n", "summary" : "

    Validates the $instance JSON item against the JSound type with name $name\n and namespace $ns, from the JSound schema definition $jsd.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "jsd", "type" : "object()", "occurrence" : null, "description" : "
    the JSound schema as a JSON object to be validated against
    " }, { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the expected type
    " }, { "name" : "ns", "type" : "string", "occurrence" : null, "description" : "
    the namespace of the expected type
    " }, { "name" : "instance", "type" : "item()", "occurrence" : null, "description" : "
    the instance to be validated
    " } ], "returns" : { "type" : "boolean", "description" : "true if the instance is valid, otherwise throws an error." }, "errors" : [ "jsv:BadJSoundFormat If the schema is not a valid JSound schema", "jsv:Invalid If the instance does not conform to the JSound schema" ] } ], "variables" : [ ] }, "http://xbrl.io/modules/bizql/archives" : { "ns" : "http://xbrl.io/modules/bizql/archives", "description" : "

    This module provides functions for retrieving metadata about archives.

    \n

    Archives represent the granularity of \"report shipping\", i.e., an entity\n reports one archive at a time. An archive is identified with an AID (archive ID).

    \n

    Archives are made of reported facts (see facts module),\n which are structured and organized in components (see components module).

    \n

    With this module, you can retrieve all archives, or a certain number of archives\n with their AIDs, or obtain the AID of archives you already have. You can also retrieve\n all archives submitted by one or several entities.

    \n

    Archive information is stored in a MongoDB datasource called xbrl.

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/archives", "prefix" : "archives" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://xbrl.io/modules/bizql/entities", "prefix" : "entities" }, { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://www.28msec.com/modules/mongodb", "prefix" : "mongo" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "aid", "qname" : "archives:aid", "signature" : "($archives-or-ids as item()*) as atomic*", "description" : "

    Converts the input to a normalized archive identifier (AID). The input\n can be either a pure AID, or an archive object which contains an AID.

    \n", "summary" : "

    Converts the input to a normalized archive identifier (AID).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archive objects or identifiers (AID).
    " } ], "returns" : { "type" : "atomic*", "description" : "the normalized AIDs." }, "errors" : [ "archives:INVALID_PARAMETER if the AID or archive is not valid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "archives-for-entities", "qname" : "archives:archives-for-entities", "signature" : "($entities-or-ids as item()*) as object()*", "description" : "

    Return all archives created by the supplied entities.

    \n", "summary" : "

    Return all archives created by the supplied entities.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "entities-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    arbitrary number of entity objects or EIDs.
    " } ], "returns" : { "type" : "object()*", "description" : "all archives created by these entities." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "archives", "qname" : "archives:archives", "signature" : "() as object()*", "description" : "

    Retrieves all archives.

    \n", "summary" : "

    Retrieves all archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()*", "description" : "all archives." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "archives", "qname" : "archives:archives", "signature" : "($archive-or-ids as item()*) as object()*", "description" : "

    Retrieves the archives with the given AIDs.

    \n", "summary" : "

    Retrieves the archives with the given AIDs.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive-or-ids", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "the archives with the given AIDs the empty sequence if no archive was found or if the input is an empty sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "entities", "qname" : "archives:entities", "signature" : "($archives-or-ids as item()*) as object()*", "description" : "

    Returns the entities that submitted the supplied archives.

    \n", "summary" : "

    Returns the entities that submitted the supplied archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their identifiers (AID).
    " } ], "returns" : { "type" : "object()*", "description" : "the submitting entities." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-abstract-primary-items-in-hypercubes", "qname" : "archives:num-abstract-primary-items-in-hypercubes", "signature" : "($archives-or-ids) as integer*", "description" : " Return the number of (distinct) abstract primary items being\n in a hypercube for each of the given archives.\n", "summary" : "

    Return the number of (distinct) abstract primary items being\n in a hypercube for each of the given archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of primary items" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-components", "qname" : "archives:num-components", "signature" : "($archives-or-ids) as integer*", "description" : " Return the number of components of each of the given archives.\n", "summary" : "

    Return the number of components of each of the given archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of components" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-concrete-primary-items-in-hypercubes", "qname" : "archives:num-concrete-primary-items-in-hypercubes", "signature" : "($archives-or-ids) as integer*", "description" : " Return the number of (distinct) concrete primary items being\n in a hypercube for each of the given archives.\n", "summary" : "

    Return the number of (distinct) concrete primary items being\n in a hypercube for each of the given archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of primary items" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-concrete-primary-items-not-in-hypercubes", "qname" : "archives:num-concrete-primary-items-not-in-hypercubes", "signature" : "($archives-or-ids) as integer*", "description" : " Return the number of (distinct) concrete primary items not being\n in a hypercube for each of the given archives.\n", "summary" : "

    Return the number of (distinct) concrete primary items not being\n in a hypercube for each of the given archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of primary items" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-distinct-abstract-primary-items-not-in-hypercubes", "qname" : "archives:num-distinct-abstract-primary-items-not-in-hypercubes", "signature" : "($archives-or-ids) as integer*", "description" : " Return the number of (distinct) abstract primary items not being\n in a hypercube for each of the given archives.\n", "summary" : "

    Return the number of (distinct) abstract primary items not being\n in a hypercube for each of the given archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of primary items" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-domains", "qname" : "archives:num-domains", "signature" : "($archives-or-ids) as integer*", "description" : " Return the number of (distinct) domains in each of the given archives.\n", "summary" : "

    Return the number of (distinct) domains in each of the given archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of domains" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-explicit-dimensions", "qname" : "archives:num-explicit-dimensions", "signature" : "($archives-or-ids) as integer*", "description" : " Return the number of (distinct) explicit dimensions in each of the given archives.\n", "summary" : "

    Return the number of (distinct) explicit dimensions in each of the given archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of dimensions" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-facts", "qname" : "archives:num-facts", "signature" : "($archives-or-ids) as integer*", "description" : " Return the number of facts of each of the given archives.\n", "summary" : "

    Return the number of facts of each of the given archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of facts" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-footnotes", "qname" : "archives:num-footnotes", "signature" : "($archives-or-ids) as integer*", "description" : " Return the number of XBRL footnotes of each of the given archives.\n", "summary" : "

    Return the number of XBRL footnotes of each of the given archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of footnotes" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-hypercubes", "qname" : "archives:num-hypercubes", "signature" : "($archives-or-ids as item()*) as integer*", "description" : " Return the number of hypercubes in each of the given archives.\n", "summary" : "

    Return the number of hypercubes in each of the given archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of hypercubes" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-members", "qname" : "archives:num-members", "signature" : "($archives-or-ids) as integer*", "description" : " Return the number of (distinct) members in each of the given archives.\n", "summary" : "

    Return the number of (distinct) members in each of the given archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of members" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-networks", "qname" : "archives:num-networks", "signature" : "($archives-or-ids) as integer*", "description" : " Return the number of networks in each of the given archives.\n", "summary" : "

    Return the number of networks in each of the given archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of archives or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of networks" }, "errors" : [ ] } ], "variables" : [ { "name" : "archives:col", "type" : "string", "description" : " Name of the collection the archives are stored in.\n" }, { "name" : "archives:ENTITY", "type" : "string", "description" : " Name of the field which points to the reporting entity.\n" } ] }, "http://www.28msec.com/modules/xmlrpc" : { "ns" : "http://www.28msec.com/modules/xmlrpc", "description" : " XML RPC Client Module\n This module provides the functions necessary to execute remote call\n procedures using\n XML-RPC.\n The application/mashup creator does not need to know the\n specifics of XML-RPC to use this module.\n Usage:\n
    xmlrpc:invoke(\"http://www.advogato.org/XMLRPC\", \"test.sumprod\", (5, 7))
    \n
    xmlrpc:invoke(\"http://www.advogato.org/XMLRPC\", \"test.capitalize\", \"HelloWorld\")
    \n
    xmlrpc:invoice(\"http://www.example.com/XMLRPC\", \"test.foo\", (\"some-parameter\",\n                      <struct>\n                        <member>\n                          <name>Foo</name>\n                          <value><string>Bar</string></value>\n                        </member>\n                      </struct>))
    \n", "sees" : [ "XML-RPC Specification", "XML-RPC Wikipedia article" ], "authors" : [ "William Candillon {william.candillon@28msec.com}" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "ann" }, { "uri" : "http://expath.org/ns/http-client", "prefix" : "http" }, { "uri" : "http://expath.org/ns/http-client", "prefix" : "http-client" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://www.28msec.com/modules/xmlrpc", "prefix" : "xmlrpc" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "invoke", "qname" : "xmlrpc:invoke", "signature" : "($endpoint-url as xs:string, $method as xs:string) as item()*", "description" : " Invoke a remote method without parameters.\n Calling this function is equivalent to xmlrpc:invoke($url, $method, ())\n", "summary" : "

    Invoke a remote method without parameters.

    ", "annotation_str" : " %ann:sequential", "annotations" : [ { "prefix" : "ann", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    URL of the XML-RPC server.
    " }, { "name" : "method", "type" : "xs:string", "occurrence" : null, "description" : "
    Name of the method to invoke.
    " } ], "returns" : { "type" : "item()*", "description" : "Result of the method invocation." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "invoke", "qname" : "xmlrpc:invoke", "signature" : "($endpoint-url as xs:string, $method as xs:string, $parameters as item()*) as item()*", "description" : " Invoke a remote method with parameters.\n", "summary" : "

    Invoke a remote method with parameters.

    ", "annotation_str" : " %ann:sequential", "annotations" : [ { "prefix" : "ann", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    URL of the XML-RPC server.
    " }, { "name" : "method", "type" : "xs:string", "occurrence" : null, "description" : "
    Name of the method to invoke.
    " }, { "name" : "parameters", "type" : "item()", "occurrence" : "*", "description" : "
    Method parameters. Struct and Arrays need to follow XML-RPC format. Atomic types will be automatically convert to the proper XML-RPC data format.
    " } ], "returns" : { "type" : "item()*", "description" : "Result of the method invocation." }, "errors" : [ ] } ], "variables" : [ { "name" : "xmlrpc:ERR_001", "type" : "xs:QName", "description" : " XML-RPC serialization error.\n" } ] }, "http://zorba.io/modules/unordered-maps" : { "ns" : "http://zorba.io/modules/unordered-maps", "description" : " This module defines a set of functions for working with maps. A map\n is identified by a string and can be created using the map:create function\n and dropped using the map:drop function.\n

    \n It is possible to create persistent and transient maps. The lifetime of a\n transient map is limited by the execution of the current query.\n A persistent map lives until it is explicitly dropped.\n Accordingly, it is also available to other requests.\n

    \n For example,\n

    map:create(\"my-map\", [\"string\", \"integer\"], { \"persistent\" : false })
    \n will create a transient map named my-map having two keys.\n The types of the keys are string and integer.\n

    \n The key of a particular entry in the map can consist of a tuple of\n atomic values (called key attributes). The actual type of each attribute\n is determined when the map is created. The value of each entry is a\n sequence of items. If an item in this sequence is a object or array,\n this item needs to belong to a collection, otherwise, an error is raised.\n", "sees" : [ ], "authors" : [ "Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://zorba.io/modules/unordered-maps", "prefix" : "map" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "available-maps", "qname" : "map:available-maps", "signature" : "() as string* external", "description" : " The function returns a sequence of names of the maps that are\n available (persistent and non-persistent). The sequence will be\n empty if there are no maps.\n

    \n", "summary" : "

    The function returns a sequence of names of the maps that are\n available (persistent and non-persistent).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "string*", "description" : "A sequence of string, one for each available map, or an empty sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "create", "qname" : "map:create", "signature" : "($name as string, $key-types as item()) as empty-sequence() external", "description" : " Create a persistent map with a given name and type identifiers for the key\n attributes.\n

    \n If the map has only one key attribute, a single type identifier is given,\n for more than one key attribute an array of type identifiers is given.\n Calling this function is equivalent to calling create with the options\n { \"persistent\" : true }\n Note that the function is sequential and immediately creates the map.\n

    \n Each key-type should be specified as string (e.g. \"integer\",\n \"string\", \"boolean\", \"double\", or \"datetime\").\n

    \n For example,\n

    map:create(\"my-map\", \"string\")
    or\n
    map:create(\"my-map\", [\"string\", \"integer\"])
    .\n", "summary" : "

    Create a persistent map with a given name and type identifiers for the key\n attributes.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map (the restrictions on collection names apply)
    " }, { "name" : "key-types", "type" : "item()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and immediately creates the corresponding map. It returns the empty-sequence." }, "errors" : [ "err:XPTY0004 if any of the key attribute types is not a subtype of anyAtomicType.", "zerr:ZSTR0001 if a map with the given name already exists.", "zerr:ZDDY1000 if the given name is not a legal collection name", "zerr:ZDDY0043 if any of the given options has an invalid type" ] }, { "isDocumented" : true, "arity" : 3, "name" : "create", "qname" : "map:create", "signature" : "($name as string, $key-types as item(), $options as object()) as empty-sequence() external", "description" : " Create a map with a given name, type identifiers for the key attributes, and\n options.\n

    \n If the map has only one key attribute, a single type identifier is given,\n for more than one key attribute an array of type identifiers is given.\n Currently only one option is supported: To create a transient map the object\n { \"persistent\" : false }\n has to be passed to the $options parameter.\n Note that the function is sequential and immediately creates the map in the\n store.\n

    \n Note that a map cannot be created if it already exists in a parent context.\n For example, a map that was created in an outer query cannot be\n created again in an inner query executed using the\n reflection:eval-s function.\n", "summary" : "

    Create a map with a given name, type identifiers for the key attributes, and\n options.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map (the restrictions on collection names apply)
    " }, { "name" : "key-types", "type" : "item()", "occurrence" : null, "description" : "" }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    an object describing options for the map
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and immediately creates the corresponding map but returns the empty-sequence." }, "errors" : [ "err:XPTY0004 if any of the attribute types is not a subtype of anyAtomicType.", "zerr:ZSTR0001 if a map with the given name already exists.", "zerr:ZDDY1000 if the given name is not a legal collection name", "zerr:ZDDY0043 if any of the given options has an invalid type" ] }, { "isDocumented" : true, "arity" : 2, "name" : "delete", "qname" : "map:delete", "signature" : "($name as string, $key as item()) as empty-sequence() external", "description" : " Removes an entry identified by the given key from the map.\n

    \n If the map has only one key attribute, a single key value is given, for\n more than one key attribute an array of key values is given.\n

    \n Note that it is possible to insert entries with empty key attributes.\n However as the removing the entries is based on the \"eq\" comparison and\n as \"eq\" with an empty sequence always return false, it is not possible\n to delete these entries.\n", "summary" : "

    Removes an entry identified by the given key from the map.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map
    " }, { "name" : "key", "type" : "item()", "occurrence" : null, "description" : "
    either a single attribute key or an array of keys
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and immediately deletes the entry into the map but returns the empty-sequence." }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist.", "zerr:ZDDY0025 if the given number of key attributes does not match the number of key attributes specified when creating the map (see the map:create function).", "zerr:ZXQD0005 if any of the given key attributes can not be cast (or is not a subtype) of the corresponding key attribute specified when creating the map." ] }, { "isDocumented" : true, "arity" : 1, "name" : "drop", "qname" : "map:drop", "signature" : "($name as string) as empty-sequence() external", "description" : " Deletes the map with the given name.\n

    \n Note that a map can only be dropped in the context it was created.\n For example, a map that was created in an outer query cannot be\n dropped in an inner query executed using the\n reflection:eval-s function.\n", "summary" : "

    Deletes the map with the given name.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map to drop
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and immediately drops the map. It returns the empty-sequence." }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist." ] }, { "isDocumented" : true, "arity" : 2, "name" : "get", "qname" : "map:get", "signature" : "($name as string, $key as item()) as item()* external", "description" : " Returns the value of the entry with the given key from the map.\n

    \n If the map has only one key attribute, a single key value is given, for\n more than one key attribute an array of key values is given.\n

    \n Note that it is possible to insert entries with empty key attributes.\n However as the getting the entries is based on the \"eq\" comparison and\n as \"eq\" with an empty sequence always return false, it is not possible\n to retrieve these entries.\n

    \n For example,\n

    map:get(\"my-map\", \"key\")
    or\n
    map:get(\"my-map\", [ \"key1\", \"key2\" ])
    .\n", "summary" : "

    Returns the value of the entry with the given key from the map.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map
    " }, { "name" : "key", "type" : "item()", "occurrence" : null, "description" : "
    either a single attribute key or an array of keys
    " } ], "returns" : { "type" : "item()*", "description" : "the value of the entry in the map identified by the given key. The empty-sequence will be returned if no entry with the given key is contained in the map." }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist.", "zerr:ZDDY0025 if the given number of key attributes does not match the number of key attributes specified when creating the map (see the map:create function).", "zerr:ZXQD0005 if any of the given key attributes can not be cast (or is not a subtype) of the corresponding key attribute specified when creating the map." ] }, { "isDocumented" : true, "arity" : 3, "name" : "insert", "qname" : "map:insert", "signature" : "($name as string, $key as item(), $value as item()*) as empty-sequence() external", "description" : " Inserts a new entry into the map with the given name.\n

    \n If the map has only one key attribute, a single key value is given, for\n more than one key attribute an array of key values is given.\n If an entry with the given key already exists in the map, the value\n sequences of the existing entry and the sequence passed using $value\n argument are concatenated.\n

    \n If an item in the value sequence is an object or array, this\n item needs to belong to a collection, otherwise, an an error\n is raised.\n

    \n Note that it is possible to insert entries with empty key attributes\n or key attributes having the value null. However, as\n the comparison with an empty sequence or null always returns false,\n it is not possible to retrieve these entries.\n

    \n For example,\n

    map:insert(\"my-map\", \"key\", \"value\")
    or\n
    map:insert(\"my-map\", [ \"key1\", \"key2\" ] , (42, \"value\"))
    .\n", "summary" : "

    Inserts a new entry into the map with the given name.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map
    " }, { "name" : "key", "type" : "item()", "occurrence" : null, "description" : "
    either a single attribute key or an array of keys
    " }, { "name" : "value", "type" : "item()", "occurrence" : "*", "description" : "
    the value of the entry to insert
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and immediately inserts the entry into the map. It returns the empty-sequence." }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist.", "zerr:ZDDY0025 if the given number of key attributes does not match the number of key attributes specified when creating the map (see the map:create function).", "zerr:ZXQD0005 if any of the given key attributes can not be cast (or is not a subtype) of the corresponding key attribute specified when creating the map.", "zerr:ZDDY1003 if the value to insert is an object or array it must belong to a collection." ] }, { "isDocumented" : true, "arity" : 1, "name" : "keys", "qname" : "map:keys", "signature" : "($name as string) as array()* external", "description" : " Returns the keys of all entries of a map. The keys\n are returned as sequence of arrays.\n

    \n The following condition always holds:\n map:size($name) eq count(map:keys($name))\n", "summary" : "

    Returns the keys of all entries of a map.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map
    " } ], "returns" : { "type" : "array()*", "description" : "an sequence of arrays each array containing the values of all attributes of one key." }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist." ] }, { "isDocumented" : true, "arity" : 1, "name" : "options", "qname" : "map:options", "signature" : "($name as string) as object() external", "description" : " The function returns the options that were passed during creation or the\n default options if no options were passed.\n", "summary" : "

    The function returns the options that were passed during creation or the\n default options if no options were passed.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map
    " } ], "returns" : { "type" : "object()", "description" : "an options object" }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist." ] }, { "isDocumented" : true, "arity" : 1, "name" : "size", "qname" : "map:size", "signature" : "($name as string) as integer external", "description" : " Returns the number of entries in a map.\n

    \n The following condition always holds:\n map:size($name) eq count(map:keys($name))\n", "summary" : "

    Returns the number of entries in a map.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map
    " } ], "returns" : { "type" : "integer", "description" : "the number of entries in the map." }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist." ] } ], "variables" : [ { "name" : "map:PERSISTENT", "type" : "string", "description" : " Constant containing the field name of the options object\n indiciating whether a map is persistent or transient.\n" } ] }, "http://www.28msec.com/modules/assertion" : { "ns" : "http://www.28msec.com/modules/assertion", "description" : "

    \n This module provides a set of assertion functions.\n

    \n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/assertion", "prefix" : "assertion" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "equals-deep", "qname" : "assertion:equals-deep", "signature" : "($expected as item()*, $actual as item()*) as item()*", "description" : " Asserts that two objects are deep-equal.\n If they are not, an error containing the diff is raised.\n", "summary" : "

    Asserts that two objects are deep-equal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "expected", "type" : "item()", "occurrence" : "*", "description" : "
    expected value
    " }, { "name" : "actual", "type" : "item()", "occurrence" : "*", "description" : "
    actual value
    " } ], "returns" : { "type" : "item()*", "description" : "actual value" }, "errors" : [ "assertion:A003 expected and actual value are not deep-equal" ] }, { "isDocumented" : true, "arity" : 2, "name" : "equals-general", "qname" : "assertion:equals-general", "signature" : "($expected as item()*, $actual as item()*) as item()*", "description" : " Asserts that two objects are equal (by general comarison).\n If they are not, an error containing the diff is raised.\n", "summary" : "

    Asserts that two objects are equal (by general comarison).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "expected", "type" : "item()", "occurrence" : "*", "description" : "
    expected value
    " }, { "name" : "actual", "type" : "item()", "occurrence" : "*", "description" : "
    actual value
    " } ], "returns" : { "type" : "item()*", "description" : "actual value" }, "errors" : [ "assertion:A002 expected and actual value are not equal" ] }, { "isDocumented" : true, "arity" : 2, "name" : "equals-value", "qname" : "assertion:equals-value", "signature" : "($expected as item()?, $actual as item()?) as item()?", "description" : " Asserts that two objects are equal (by value comparison).\n If they are not, an error containing the diff is raised.\n", "summary" : "

    Asserts that two objects are equal (by value comparison).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "expected", "type" : "item()", "occurrence" : "?", "description" : "
    expected value
    " }, { "name" : "actual", "type" : "item()", "occurrence" : "?", "description" : "
    actual value
    " } ], "returns" : { "type" : "item()?", "description" : "actual value" }, "errors" : [ "assertion:A001 expected and actual value are not equal" ] } ], "variables" : [ { "name" : "assertion:A001", "type" : "xs:QName", "description" : " xs:QName with namespace URI=\"http://www.28msec.com/modules/assertion\" and\n local name 'A001'. 'equals-value' assertion failed.\n" }, { "name" : "assertion:A002", "type" : "xs:QName", "description" : " xs:QName with namespace URI=\"http://www.28msec.com/modules/assertion\" and\n local name 'A002'. 'equals-general' assertion failed.\n" }, { "name" : "assertion:A003", "type" : "xs:QName", "description" : " xs:QName with namespace URI=\"http://www.28msec.com/modules/assertion\" and\n local name 'A003'. 'equals-general' assertion failed.\n" } ] }, "http://www.zorba-xquery.com/modules/image/basic" : { "ns" : "http://www.zorba-xquery.com/modules/image/basic", "description" : " This module provides function to do the following basic image operations:\n
      \n
    • create empty images
    • \n
    • compare images
    • \n
    • compress image
    • \n
    • convert an image one format to another
    • \n
    • retrieve with, height, format, and exif information from an image
    • \n
    \n The following image formats are supported:\n
      \n
    • GIF
    • \n
    • JPEG
    • \n
    • PNG
    • \n
    • TIFF
    • \n
    • BMP
    • \n
    \n

    The errors raised by functions of this module have the namespace\n http://www.zorba-xquery.com/modules/image/error (associated with prefix ierr).

    \n", "sees" : [ ], "authors" : [ "Daniel Thomas" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.zorba-xquery.com/modules/image/basic", "prefix" : "basic" }, { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://www.zorba-xquery.com/modules/image/error", "prefix" : "ierr" }, { "uri" : "http://www.zorba-xquery.com/modules/image/image", "prefix" : "image" }, { "uri" : "http://www.w3.org/2000/svg", "prefix" : "svg" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "compress", "qname" : "basic:compress", "signature" : "($image as xs:base64Binary, $quality as xs:unsignedInt) as xs:base64Binary external", "description" : " Compresses the passed image.\n Compressing means lowering the quality and reducing the size.\n", "summary" : "

    Compresses the passed image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the image
    " }, { "name" : "quality", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    compression level, 0 to 100
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the compressed image" }, "errors" : [ "ierr:IM001 the passed image is invalid." ] }, { "isDocumented" : true, "arity" : 2, "name" : "convert-svg-string", "qname" : "basic:convert-svg-string", "signature" : "($svg as xs:string, $format as xs:string) as xs:base64Binary", "description" : " Converts an SVG image to a supported image format.\n", "summary" : "

    Converts an SVG image to a supported image format.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "svg", "type" : "xs:string", "occurrence" : null, "description" : "
    the image to convert as string
    " }, { "name" : "format", "type" : "xs:string", "occurrence" : null, "description" : "
    target format
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the resulting image" }, "errors" : [ "ierr:IM001 the passed SVG is invalid." ] }, { "isDocumented" : true, "arity" : 2, "name" : "convert-svg", "qname" : "basic:convert-svg", "signature" : "($svg as element(svg:svg), $format as xs:string) as xs:base64Binary", "description" : " Converts an SVG image to a supported image format.\n", "summary" : "

    Converts an SVG image to a supported image format.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "svg", "type" : "element(svg:svg)", "occurrence" : null, "description" : "
    the image to convert
    " }, { "name" : "format", "type" : "xs:string", "occurrence" : null, "description" : "
    target format
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the resulting image" }, "errors" : [ "ierr:IM001 the passed SVG is invalid." ] }, { "isDocumented" : true, "arity" : 2, "name" : "convert", "qname" : "basic:convert", "signature" : "($image as xs:base64Binary, $format as xs:string) as xs:base64Binary", "description" : " Converts an image to another format.\n", "summary" : "

    Converts an image to another format.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "format", "type" : "xs:string", "occurrence" : null, "description" : "
    the format (see supported formats above) of the resulting image.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A new image with the same content as the passed image but with the specified file format." }, "errors" : [ "ierr:IM001 the passed image is invalid.", "err:FORG0001 unsupported image format" ] }, { "isDocumented" : true, "arity" : 3, "name" : "create", "qname" : "basic:create", "signature" : "($width as xs:unsignedInt, $height as xs:unsignedInt, $format as xs:string) as xs:base64Binary", "description" : " Creates an empty image with background color white.\n", "summary" : "

    Creates an empty image with background color white.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "width", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    the width of the new image
    " }, { "name" : "height", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    the height of the new image
    " }, { "name" : "format", "type" : "xs:string", "occurrence" : null, "description" : "
    the format of the new image
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "newly created image" }, "errors" : [ "err:FORG0001 unsupported image format" ] }, { "isDocumented" : true, "arity" : 2, "name" : "equals", "qname" : "basic:equals", "signature" : "($image1 as xs:base64Binary, $image2 as xs:base64Binary) as xs:boolean external", "description" : " Compares two images.\n", "summary" : "

    Compares two images.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image1", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    first image
    " }, { "name" : "image2", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    second image
    " } ], "returns" : { "type" : "xs:boolean", "description" : "True if the images are equal." }, "errors" : [ "ierr:IM001 one of the passed images is invalid." ] }, { "isDocumented" : true, "arity" : 2, "name" : "exif", "qname" : "basic:exif", "signature" : "($image as xs:base64Binary, $tag as xs:string) as xs:string? external", "description" : " Reads exif information from an image.\n This function works for JPEG and TIFF images only.\n It returns empty sequence if no exif information matching the passed tag is found.\n", "summary" : "

    Reads exif information from an image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the image
    " }, { "name" : "tag", "type" : "xs:string", "occurrence" : null, "description" : "
    the field name we want read (e.g. DateTime).
    " } ], "returns" : { "type" : "xs:string?", "description" : "exif field content" }, "errors" : [ "ierr:IM001 the passed image is invalid." ] }, { "isDocumented" : true, "arity" : 1, "name" : "format", "qname" : "basic:format", "signature" : "($image as xs:base64Binary) as xs:string external", "description" : " Returns the format of the passed image.\n", "summary" : "

    Returns the format of the passed image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the image
    " } ], "returns" : { "type" : "xs:string", "description" : "the format" }, "errors" : [ "ierr:IM001 the passed image is invalid." ] }, { "isDocumented" : true, "arity" : 1, "name" : "height", "qname" : "basic:height", "signature" : "($image as xs:base64Binary) as xs:unsignedInt external", "description" : " Returns the height of the passed image.\n", "summary" : "

    Returns the height of the passed image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the image
    " } ], "returns" : { "type" : "xs:unsignedInt", "description" : "the height in pixels" }, "errors" : [ "ierr:IM001 the passed image is invalid." ] }, { "isDocumented" : true, "arity" : 1, "name" : "width", "qname" : "basic:width", "signature" : "($image as xs:base64Binary) as xs:unsignedInt external", "description" : " Returns the width of the passed image.\n", "summary" : "

    Returns the width of the passed image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the image
    " } ], "returns" : { "type" : "xs:unsignedInt", "description" : "the width in pixels" }, "errors" : [ "ierr:IM001 the passed image is invalid." ] } ], "variables" : [ ] }, "http://api.28.io/indices" : { "ns" : "http://api.28.io/indices", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://api.28.io/indices", "prefix" : "in" }, { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "req" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "resp" }, { "uri" : "http://api.28.io/util", "prefix" : "util" }, { "uri" : "http://api.28.io/validation", "prefix" : "validate" } ], "functions" : [ { "isDocumented" : false, "arity" : 1, "name" : "create-index", "qname" : "in:create-index", "signature" : "($new-index as object()) as empty-sequence()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "new-index", "type" : "object()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "delete-index", "qname" : "in:delete-index", "signature" : "($name) as empty-sequence()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "dispatch", "qname" : "in:dispatch", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "get-index", "qname" : "in:get-index", "signature" : "($name as xs:string) as object()?", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "object()?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "list-indices", "qname" : "in:list-indices", "signature" : "() as array()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "array()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "metadata", "qname" : "in:metadata", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "put-index", "qname" : "in:put-index", "signature" : "($name as xs:string, $new-index-obj as object()) as empty-sequence()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "new-index-obj", "type" : "object()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "refresh-index", "qname" : "in:refresh-index", "signature" : "($index as xs:string) as empty-sequence()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "index", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "validate-index", "qname" : "in:validate-index", "signature" : "($index as object()) as empty-sequence()", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "index", "type" : "object()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://api.28.io/xdmview" : { "ns" : "http://api.28.io/xdmview", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://api.28.io/model", "prefix" : "model" }, { "uri" : "http://zorba.io/modules/reference", "prefix" : "ref" }, { "uri" : "http://www.zorba-xquery.com/schemas/xdm", "prefix" : "xdm" }, { "uri" : "http://api.28.io/xdmview", "prefix" : "xdmview" } ], "functions" : [ { "isDocumented" : false, "arity" : 1, "name" : "show-namespaces", "qname" : "xdmview:show-namespaces", "signature" : "($namespaces)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "show-node", "qname" : "xdmview:show-node", "signature" : "($node, $namespaces, $include-noderef as xs:boolean)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "node", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "include-noderef", "type" : "xs:boolean", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "show-nodes", "qname" : "xdmview:show-nodes", "signature" : "($nodes, $include-noderef as xs:boolean)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "include-noderef", "type" : "xs:boolean", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/xqdoc/json" : { "ns" : "http://www.zorba-xquery.com/modules/xqdoc/json", "description" : " Convert an XQDoc document into an HTML document.\n This module contains a single convert() function\n that transform an XQDoc document into an HTML document.\n Usage:\n
    \n let $xqdoc := xqdoc:xqdoc(\"http://expath.org/ns/file\")\n return html:convert($xqdoc)\n 
    \n", "sees" : [ ], "authors" : [ "William Candillon wcandillon at gmail dot com" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.zorba-xquery.com/modules/xqdoc/json", "prefix" : "html" }, { "uri" : "http://www.w3.org/2010/xslt-xquery-serialization", "prefix" : "o" }, { "uri" : "http://www.xqdoc.org/1.0", "prefix" : "xq" } ], "functions" : [ { "isDocumented" : false, "arity" : 1, "name" : "convert", "qname" : "html:convert", "signature" : "($xqdoc as element(xq:xqdoc)) as object()", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "xqdoc", "type" : "element(xq:xqdoc)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "object()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "normalize-anchors", "qname" : "html:normalize-anchors", "signature" : "($node)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/math" : { "ns" : "http://zorba.io/modules/math", "description" : " Extensive math library.

    \n", "sees" : [ ], "authors" : [ "Daniel Turcanu, Dan Muresan" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xpath-functions/math", "prefix" : "W3Cmath" }, { "uri" : "http://zorba.io/modules/math", "prefix" : "math" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "acosh", "qname" : "math:acosh", "signature" : "($arg as double) as double external", "description" : " Inverse hyperbolic cosine.\n", "summary" : "

    Inverse hyperbolic cosine.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : null, "description" : "
    the arg
    " } ], "returns" : { "type" : "double", "description" : "the result of acosh(arg)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "asinh", "qname" : "math:asinh", "signature" : "($arg as double) as double external", "description" : " Calculate the inverse hyperbolic sine.\n", "summary" : "

    Calculate the inverse hyperbolic sine.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : null, "description" : "
    the arg
    " } ], "returns" : { "type" : "double", "description" : "the result of asinh(arg)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "atanh", "qname" : "math:atanh", "signature" : "($arg as double) as double external", "description" : " Calculate the hyperbolic tangent.\n", "summary" : "

    Calculate the hyperbolic tangent.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : null, "description" : "
    must be in range -1 ... +1 (exclusive)
    " } ], "returns" : { "type" : "double", "description" : "the result of atanh(arg)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "avedev", "qname" : "math:avedev", "signature" : "($numbers as double+) as double", "description" : " Returns the average of the absolute deviations of data points from their mean.

    \n The formula is sum(abs(x - average_x))/n, where n is the count of x in the sequence.

    \n Borrowed from excel module.\n", "summary" : "

    Returns the average of the absolute deviations of data points from their mean.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "+", "description" : "
    the sequence of numbers. Sequence can be of any length from 1 up.
    " } ], "returns" : { "type" : "double", "description" : "The formula result" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "cast-as-numeric", "qname" : "math:cast-as-numeric", "signature" : "($number as anyAtomicType) as anyAtomicType", "description" : " Cast the anyAtomicType to a numeric type.

    \n If the value is already of a numeric type then nothing is changed.\n Otherwise the value is casted to the numeric type that is most appropriate.\n

    \n Borrowed from excel module.\n", "summary" : "

    Cast the anyAtomicType to a numeric type.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "anyAtomicType", "occurrence" : null, "description" : "
    The parameter can be a number, string, boolean value.
    " } ], "returns" : { "type" : "anyAtomicType", "description" : "The casted value." }, "errors" : [ "math:VALUE_NOT_NUMERIC if the value cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 2, "name" : "ceiling", "qname" : "math:ceiling", "signature" : "($number as double, $significance as double) as double", "description" : " Returns number rounded up, away from zero, to the nearest multiple of significance.

    \n Significance must have the same sign as number.\n Number and significance must be of a numeric type or castable to numeric.\n Significance must not be zero.

    \n Borrowed from excel module.\n", "summary" : "

    Returns number rounded up, away from zero, to the nearest multiple of significance.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "double", "occurrence" : null, "description" : "
    The value you want to round.
    " }, { "name" : "significance", "type" : "double", "occurrence" : null, "description" : "
    The multiple to which you want to round.
    " } ], "returns" : { "type" : "double", "description" : "The rounded value." }, "errors" : [ "math:INVALID_ARGUMENT if significance is zero or it doesn't have the same sign as number." ] }, { "isDocumented" : true, "arity" : 1, "name" : "cosh", "qname" : "math:cosh", "signature" : "($arg as double) as double external", "description" : " Returns the hyperbolic cosine of x.

    \n If the result it too large, INF is returned.\n", "summary" : "

    Returns the hyperbolic cosine of x.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : null, "description" : "
    must be smaller than 7.104760e+002
    " } ], "returns" : { "type" : "double", "description" : "cosh(arg)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "deg-to-rad", "qname" : "math:deg-to-rad", "signature" : "($deg as double) as double", "description" : " Convert angle from degrees to radians.

    \n The parameter is first converted to value range of (-360, 360).\n", "summary" : "

    Convert angle from degrees to radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "deg", "type" : "double", "occurrence" : null, "description" : "
    angle in degrees
    " } ], "returns" : { "type" : "double", "description" : "value in radians (-2PI, 2PI)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "even", "qname" : "math:even", "signature" : "($number as double) as integer", "description" : " Returns number rounded up to the nearest even integer.

    \n Regardless of the sign of number, a value is rounded up when adjusted away from zero.

    \n Borrowed from excel module.\n", "summary" : "

    Returns number rounded up to the nearest even integer.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "double", "occurrence" : null, "description" : "
    The value to round.
    " } ], "returns" : { "type" : "integer", "description" : "The rounded value casted as numeric type." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "fact", "qname" : "math:fact", "signature" : "($number as integer) as integer", "description" : " Returns the factorial of a number.

    \n Borrowed from excel module.\n", "summary" : "

    Returns the factorial of a number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "integer", "occurrence" : null, "description" : "
    The non-negative number you want the factorial of.
    " } ], "returns" : { "type" : "integer", "description" : "Returns the factorial of a number. The factorial of a number is equal to 1*2*3*...* number." }, "errors" : [ "math:INVALID_ARGUMENT if the number is smaller than zero" ] }, { "isDocumented" : true, "arity" : 1, "name" : "factdouble", "qname" : "math:factdouble", "signature" : "($number as integer) as integer", "description" : " Returns the double factorial of a number.

    \n Computes the double factorial of n as n(n-2)(n-4)...

    \n Borrowed from excel module.\n", "summary" : "

    Returns the double factorial of a number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "integer", "occurrence" : null, "description" : "
    The positive integer value.
    " } ], "returns" : { "type" : "integer", "description" : "The result as integer." }, "errors" : [ "math:INVALID_ARGUMENT if the number is negative." ] }, { "isDocumented" : true, "arity" : 2, "name" : "floor", "qname" : "math:floor", "signature" : "($number as double, $significance as double) as double", "description" : " Rounds number down, toward zero, to the nearest multiple of significance.

    \n Significance must have the same sign as number.\n Borrowed from excel module.\n", "summary" : "

    Rounds number down, toward zero, to the nearest multiple of significance.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "double", "occurrence" : null, "description" : "
    The value you want to round.
    " }, { "name" : "significance", "type" : "double", "occurrence" : null, "description" : "
    The multiple to which you want to round.
    " } ], "returns" : { "type" : "double", "description" : "The rounded value as numeric type." }, "errors" : [ "math:INVALID_ARGUMENT if significance is zero or it doesn't have the same sign as number." ] }, { "isDocumented" : true, "arity" : 2, "name" : "fmod", "qname" : "math:fmod", "signature" : "($x as double, $y as double) as double external", "description" : " Function performing the modulo operation between the two arguments.\n", "summary" : "

    Function performing the modulo operation between the two arguments.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x", "type" : "double", "occurrence" : null, "description" : "
    the x
    " }, { "name" : "y", "type" : "double", "occurrence" : null, "description" : "
    the y
    " } ], "returns" : { "type" : "double", "description" : "The remainder of x/y." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "frexp", "qname" : "math:frexp", "signature" : "($arg as double) as double+ external", "description" : " Returns the argument split as mantissa and exponent.

    \n The recombining formula is (mantissa * 2^exponent).\n", "summary" : "

    Returns the argument split as mantissa and exponent.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : null, "description" : "
    the double to be split.
    " } ], "returns" : { "type" : "double+", "description" : "A sequence of two doubles (mantissa, exponent)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "gcd", "qname" : "math:gcd", "signature" : "($numbers as integer+) as integer", "description" : " Returns the greatest common divisor GCD of a sequence of integers.

    \n The sequence can have one or more positive integers.

    \n Borrowed from excel module.\n", "summary" : "

    Returns the greatest common divisor GCD of a sequence of integers.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "integer", "occurrence" : "+", "description" : "
    The sequence of positive integers.
    " } ], "returns" : { "type" : "integer", "description" : "The GCD as integer." }, "errors" : [ "math:INVALID_ARGUMENT if any number is smaller than zero." ] }, { "isDocumented" : true, "arity" : 1, "name" : "int", "qname" : "math:int", "signature" : "($number as double) as integer", "description" : " Rounds a number down to the nearest integer.

    \n Positive numbers are rounded toward zero, negative numbers are rounded away from zero.

    \n Borrowed from excel module.\n", "summary" : "

    Rounds a number down to the nearest integer.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "double", "occurrence" : null, "description" : "
    The value to be rounded.
    " } ], "returns" : { "type" : "integer", "description" : "The rounded integer." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-a-number", "qname" : "math:is-a-number", "signature" : "($value as anyAtomicType) as boolean", "description" : " Checks if the anyAtomicType argument is actually a numeric type\n or can be converted to numeric.

    \n Borrowed from excel module.\n", "summary" : "

    Checks if the anyAtomicType argument is actually a numeric type\n or can be converted to numeric.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "anyAtomicType", "occurrence" : null, "description" : "
    Parameter to be checked.
    " } ], "returns" : { "type" : "boolean", "description" : "true if the value can be casted to numeric." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is_inf", "qname" : "math:is_inf", "signature" : "($arg as double) as boolean external", "description" : " Checks if the double value is positive or negative infinite.\n", "summary" : "

    Checks if the double value is positive or negative infinite.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : null, "description" : "
    the double to be checked
    " } ], "returns" : { "type" : "boolean", "description" : "boolean true if argument is pos INF or neg INF" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is_nan", "qname" : "math:is_nan", "signature" : "($arg as double) as boolean external", "description" : " Checks if the double value is Not a Number (NaN).\n", "summary" : "

    Checks if the double value is Not a Number (NaN).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : null, "description" : "
    the arg
    " } ], "returns" : { "type" : "boolean", "description" : "boolean true if the double is NaN" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "large", "qname" : "math:large", "signature" : "($numbers as double+, $k as integer) as double", "description" : " Returns the k-th largest value in a data set.

    \n If n is the number of data points in a range,\n then LARGE(array,1) returns the largest value,\n and LARGE(array,n) returns the smallest value.

    \n Borrowed from excel module.
    \n", "summary" : "

    Returns the k-th largest value in a data set.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "+", "description" : "
    the sequence of numbers The sequence can be of any length, from 1 up.
    " }, { "name" : "k", "type" : "integer", "occurrence" : null, "description" : "
    the position of largest value, with value from 1 to count of values
    " } ], "returns" : { "type" : "double", "description" : "The k-th largest value as numeric type" }, "errors" : [ "math:INVALID_ARGUMENT if the sequence is empty or k is not a value between 1 and the size of the sequence" ] }, { "isDocumented" : true, "arity" : 1, "name" : "lcm", "qname" : "math:lcm", "signature" : "($numbers as integer+) as integer", "description" : " Returns the least common multiple of integers.

    \n LCM for two numbers is computed by multiplying them and dividing with GCD.\n The function is applied recursively replacing the first two numbers in the sequence with their LCM.

    \n Borrowed from excel module.\n", "summary" : "

    Returns the least common multiple of integers.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "integer", "occurrence" : "+", "description" : "
    The sequence of one or more positive integers.
    " } ], "returns" : { "type" : "integer", "description" : "The LCM as integer." }, "errors" : [ "math:INVALID_ARGUMENT if any number is smaller than zero." ] }, { "isDocumented" : true, "arity" : 2, "name" : "ldexp", "qname" : "math:ldexp", "signature" : "($x as double, $i as integer) as double external", "description" : " Computes a real number from the mantissa and exponent.

    \n The formula is (x * 2^i).\n", "summary" : "

    Computes a real number from the mantissa and exponent.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x", "type" : "double", "occurrence" : null, "description" : "
    the mantissa
    " }, { "name" : "i", "type" : "integer", "occurrence" : null, "description" : "
    the exponent
    " } ], "returns" : { "type" : "double", "description" : "the computed real number" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "median", "qname" : "math:median", "signature" : "($numbers as double*) as double", "description" : " Returns the median of the given numbers.

    \n The median is the number in the middle of a set of numbers.\n Half the numbers have values that are greater than the median,\n and half the numbers have values that are less than the median.

    \n Borrowed from excel module.\n", "summary" : "

    Returns the median of the given numbers.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "*", "description" : "
    the sequence of numbers, of any length
    " } ], "returns" : { "type" : "double", "description" : "for odd count of numbers return the number in the middle of the sorted sequence. For even count of numbers return the average of the two numbers in the middle." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "mod", "qname" : "math:mod", "signature" : "($number as double, $divisor as double) as double", "description" : " Returns the remainder after number is divided by divisor.

    \n The result has the same sign as divisor.

    \n Borrowed from excel module.\n", "summary" : "

    Returns the remainder after number is divided by divisor.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "double", "occurrence" : null, "description" : "
    The number for which you want to find the remainder.
    " }, { "name" : "divisor", "type" : "double", "occurrence" : null, "description" : "
    The number by which you want to divide number. This cannot be zero.
    " } ], "returns" : { "type" : "double", "description" : "The remainder from division as numeric type." }, "errors" : [ "math:DIVIDE_BY_0 if divisor is zero after casting to numeric." ] }, { "isDocumented" : true, "arity" : 1, "name" : "mode", "qname" : "math:mode", "signature" : "($numbers as double*) as double", "description" : " Returns the most frequently occurring, or repetitive, value in a sequence.

    \n Borrowed from excel module.\n", "summary" : "

    Returns the most frequently occurring, or repetitive, value in a sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "*", "description" : "
    the sequence of numbers, of any length
    " } ], "returns" : { "type" : "double", "description" : "The most occuring number" }, "errors" : [ "math:INVALID_INPUT if there are no duplicate numbers" ] }, { "isDocumented" : true, "arity" : 1, "name" : "modf", "qname" : "math:modf", "signature" : "($arg as double) as double+ external", "description" : " Splits a floating-point value into fractional and integer parts.

    \n Both the fraction and integer keep the original sign of the value.\n", "summary" : "

    Splits a floating-point value into fractional and integer parts.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : null, "description" : "
    the double to be split.
    " } ], "returns" : { "type" : "double+", "description" : "A sequence of two doubles (fraction, integer)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "mround", "qname" : "math:mround", "signature" : "($number as decimal, $multiple as double) as double", "description" : " Returns a number rounded to the desired multiple.

    \n MROUND rounds up, away from zero, if the remainder of dividing number by multiple\n is greater than or equal to half the value of multiple.\n MROUND is computed through math:floor function.

    \n Borrowed from excel module.\n", "summary" : "

    Returns a number rounded to the desired multiple.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "decimal", "occurrence" : null, "description" : "
    The value to round,
    " }, { "name" : "multiple", "type" : "double", "occurrence" : null, "description" : "
    The multiple to which you want to round number.
    " } ], "returns" : { "type" : "double", "description" : "The rounded number up to the desired multiple." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "odd", "qname" : "math:odd", "signature" : "($number as double) as integer", "description" : " Returns number rounded up to the nearest odd integer, away from zero.

    \n Borrowed from excel module.\n", "summary" : "

    Returns number rounded up to the nearest odd integer, away from zero.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "double", "occurrence" : null, "description" : "
    The value to round.
    " } ], "returns" : { "type" : "integer", "description" : "The odd integer." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "percentile", "qname" : "math:percentile", "signature" : "($numbers as double*, $k_at as double) as double", "description" : " Returns the k-th percentile of values in a sequence.

    \n If k is not a multiple of 1/(n - 1),\n PERCENTILE interpolates to determine the value at the k-th percentile.\n The function is computed by (max-min)*k + min

    \n Borrowed from excel module.\n", "summary" : "

    Returns the k-th percentile of values in a sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "*", "description" : "
    the sequence of numbers, of any length
    " }, { "name" : "k_at", "type" : "double", "occurrence" : null, "description" : "
    the percentile, with value between 0 .. 1 inclusive
    " } ], "returns" : { "type" : "double", "description" : "The computed percentile" }, "errors" : [ "math:INVALID_ARGUMENT if percentile is not between 0 .. 1" ] }, { "isDocumented" : true, "arity" : 2, "name" : "percentrank", "qname" : "math:percentrank", "signature" : "($numbers as double*, $x as double) as double", "description" : " Returns the rank of a value in a data set as a percentage of the data set.

    \n If x does not match one of the values in array,\n PERCENTRANK interpolates to return the correct percentage rank.
    \n The formula is uses: (RANK - 1) / (size - 1) .

    \n Borrowed from excel module.\n", "summary" : "

    Returns the rank of a value in a data set as a percentage of the data set.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "*", "description" : "
    the sequence of numbers. The sequence can be of any length, from 1 up.
    " }, { "name" : "x", "type" : "double", "occurrence" : null, "description" : "
    is the value for which you want to know the rank
    " } ], "returns" : { "type" : "double", "description" : "The percentage of rank." }, "errors" : [ "math:INVALID_ARGUMENT if the sequence is zero length" ] }, { "isDocumented" : true, "arity" : 3, "name" : "prob", "qname" : "math:prob", "signature" : "($x_range as double+, $prob_range as double+, $range_lower_limit as double) as double", "description" : " This is the same as math:prob#4, only that upper_limit is not specified.

    \n The probability is computed only for range_lower_limit.

    \n Borrowed from excel module.\n", "summary" : "

    This is the same as math:prob#4, only that upper_limit is not specified.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x_range", "type" : "double", "occurrence" : "+", "description" : "
    is the range of numeric values of x with which there are associated probabilities. This does not need to be ordered.
    " }, { "name" : "prob_range", "type" : "double", "occurrence" : "+", "description" : "
    is a set of probabilities associated with values in x_range.
    " }, { "name" : "range_lower_limit", "type" : "double", "occurrence" : null, "description" : "
    is the value for which you want a probability.
    " } ], "returns" : { "type" : "double", "description" : "The probability of the range_lower_limit value" }, "errors" : [ "math:INVALID_ARGUMENT if any probability is not between 0 and 1", "math:INVALID_ARGUMENT if the sum of probabilities is not equal to 1", "math:INVALID_ARGUMENT if x_range and prob_range do not have the same number of values" ] }, { "isDocumented" : true, "arity" : 4, "name" : "prob", "qname" : "math:prob", "signature" : "($x_range as double+, $prob_range as double+, $range_lower_limit as double, $upper_limit as double) as double", "description" : " Returns the probability that values in a range are between two limits.

    \n Borrowed from excel module.\n", "summary" : "

    Returns the probability that values in a range are between two limits.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x_range", "type" : "double", "occurrence" : "+", "description" : "
    is the range of numeric values of x with which there are associated probabilities. This does not need to be ordered.
    " }, { "name" : "prob_range", "type" : "double", "occurrence" : "+", "description" : "
    is a set of probabilities associated with values in x_range.
    " }, { "name" : "range_lower_limit", "type" : "double", "occurrence" : null, "description" : "
    is the lower bound on the value for which you want a probability.
    " }, { "name" : "upper_limit", "type" : "double", "occurrence" : null, "description" : "
    is the upper bound on the value for which you want a probability.
    " } ], "returns" : { "type" : "double", "description" : "The probability of the entire range" }, "errors" : [ "math:INVALID_ARGUMENT if any probability is not between 0 and 1", "math:INVALID_ARGUMENT if the sum of probabilities is not equal to 1", "math:INVALID_ARGUMENT if x_range and prob_range do not have the same number of values" ] }, { "isDocumented" : true, "arity" : 1, "name" : "product", "qname" : "math:product", "signature" : "($numbers as double*) as double", "description" : " Multiplies all the numbers given as arguments and returns the product.

    \n Borrowed from excel module.\n", "summary" : "

    Multiplies all the numbers given as arguments and returns the product.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "*", "description" : "
    The sequence of arguments convertible to numeric types. The sequence can be of any length.
    " } ], "returns" : { "type" : "double", "description" : "The multiplication result as numeric type." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "quartile", "qname" : "math:quartile", "signature" : "($numbers as double*, $quart as integer) as double", "description" : " Returns the quartile of a data set.

    \n Borrowed from excel module.\n", "summary" : "

    Returns the quartile of a data set.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "*", "description" : "
    sequence of numbers. The sequence can be of any length, from 1 up.
    " }, { "name" : "quart", "type" : "integer", "occurrence" : null, "description" : "
    one of the values 0, 1, 2, 3, 4 with meaning:
    0
    compute minimum value
    1
    compute first quartile (25th percentile)
    2
    compute median value (50th percentile)
    3
    compute third quartile (75th percentile)
    4
    compute maximum value
    " } ], "returns" : { "type" : "double", "description" : "the computed quartile, as numeric type" }, "errors" : [ "math:INVALID_ARGUMENT if the sequence is zero length or $quart is not one of the values 0,1,3,4" ] }, { "isDocumented" : true, "arity" : 2, "name" : "quotient", "qname" : "math:quotient", "signature" : "($numerator as double, $denominator as double) as integer", "description" : " Returns the integer portion of a division.

    \n Borrowed from excel module.\n", "summary" : "

    Returns the integer portion of a division.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numerator", "type" : "double", "occurrence" : null, "description" : "
    The divider.
    " }, { "name" : "denominator", "type" : "double", "occurrence" : null, "description" : "
    The divisor. It cannot be zero.
    " } ], "returns" : { "type" : "integer", "description" : "The result value as numeric type." }, "errors" : [ "math:DIVIDE_BY_0 if denominator casted as numeric type has value zero." ] }, { "isDocumented" : true, "arity" : 1, "name" : "rad-to-deg", "qname" : "math:rad-to-deg", "signature" : "($rad as double) as double", "description" : " Convert angle from radians to degrees.

    \n", "summary" : "

    Convert angle from radians to degrees.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "rad", "type" : "double", "occurrence" : null, "description" : "
    value in radians
    " } ], "returns" : { "type" : "double", "description" : "value in degrees (-360, 360)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "rank", "qname" : "math:rank", "signature" : "($x as double, $numbers as double*) as double", "description" : " This RANK function is same as the above, only that $order_ascending is set by default to false.

    \n Borrowed from excel module.\n", "summary" : "

    This RANK function is same as the above, only that $order_ascending is set by default to false.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x", "type" : "double", "occurrence" : null, "description" : "
    The number whose rank you want to find.
    " }, { "name" : "numbers", "type" : "double", "occurrence" : "*", "description" : "
    the sequence of numbers. The sequence can be of any length.
    " } ], "returns" : { "type" : "double", "description" : "The rank of $x." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "rank", "qname" : "math:rank", "signature" : "($x as double, $numbers as double*, $order_ascending as boolean) as double", "description" : " Returns the rank of a number in a list of numbers.

    \n The rank of a number is its size relative to other values in a list.\n (If you were to sort the list, the rank of the number would be its position.)\n RANK gives duplicate numbers the same rank.

    \n Borrowed from excel module.\n", "summary" : "

    Returns the rank of a number in a list of numbers.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x", "type" : "double", "occurrence" : null, "description" : "
    The number whose rank you want to find.
    " }, { "name" : "numbers", "type" : "double", "occurrence" : "*", "description" : "
    The sequence of numbers. The sequence can be of any length.
    " }, { "name" : "order_ascending", "type" : "boolean", "occurrence" : null, "description" : "
    A boolean having the meaning:
    false
    then rank the number as if the sequence was sorted in descending order.
    true
    then rank the number as if the sequence was sorted in ascending order.
    " } ], "returns" : { "type" : "double", "description" : "The rank of $x." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "roman", "qname" : "math:roman", "signature" : "($number as integer) as string", "description" : " Converts an Arabic numeral to roman, as text.

    \n Only the classic format is supported (out of all formats Excel requires).\n M is the largest digit, it represents 1000.\n Numbers bigger than 2000 will be represented by a sequence of \"M\".\n D = 500, C = 100, L = 50, X = 10, V = 5, I = 1.

    \n Borrowed from excel module.\n", "summary" : "

    Converts an Arabic numeral to roman, as text.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "integer", "occurrence" : null, "description" : "
    A positive integer.
    " } ], "returns" : { "type" : "string", "description" : "The roman string representation." }, "errors" : [ "math:INVALID_ARGUMENT if the input integer is negative" ] }, { "isDocumented" : true, "arity" : 2, "name" : "round", "qname" : "math:round", "signature" : "($number as double, $precision as integer) as double", "description" : " Rounds a number to a specified number of digits.

    \n If precision is greater than 0 (zero), then number is rounded\n to the specified number of decimal places.\n If num_digits is 0, then number is rounded to the nearest integer.\n If num_digits is less than 0, then number is rounded to the left of the decimal point.\n The 0.5 is rounded away from zero.

    \n Borrowed from excel module.\n", "summary" : "

    Rounds a number to a specified number of digits.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "double", "occurrence" : null, "description" : "
    The number to round.
    " }, { "name" : "precision", "type" : "integer", "occurrence" : null, "description" : "
    The number of decimal places to keep.
    " } ], "returns" : { "type" : "double", "description" : "The rounded number as numeric type." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "rounddown", "qname" : "math:rounddown", "signature" : "($number as double, $precision as integer) as double", "description" : " Rounds a number down, toward zero.

    \n If num_digits is greater than 0 (zero), then number is rounded down\n to the specified number of decimal places.\n If num_digits is 0, then number is rounded down to the nearest integer.\n If num_digits is less than 0, then number is rounded down to the left of the decimal point.

    \n Borrowed from excel module.\n", "summary" : "

    Rounds a number down, toward zero.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "double", "occurrence" : null, "description" : "
    The number to round
    " }, { "name" : "precision", "type" : "integer", "occurrence" : null, "description" : "
    The number of decimal places to keep.
    " } ], "returns" : { "type" : "double", "description" : "the truncated number toward zero, as numeric type." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "roundup", "qname" : "math:roundup", "signature" : "($number as double, $precision as integer) as double", "description" : " Rounds a number up, away from 0 (zero).

    \n If num_digits is greater than 0 (zero), then number is rounded down\n to the specified number of decimal places.\n If num_digits is 0, then number is rounded down to the nearest integer.\n If num_digits is less than 0, then number is rounded down to the left of the decimal point.

    \n Borrowed from excel module.\n", "summary" : "

    Rounds a number up, away from 0 (zero).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "double", "occurrence" : null, "description" : "
    The number to round
    " }, { "name" : "precision", "type" : "integer", "occurrence" : null, "description" : "
    The number of decimal places to keep.
    " } ], "returns" : { "type" : "double", "description" : "The truncated number away from zero, as numeric type." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sign", "qname" : "math:sign", "signature" : "($number as double) as integer", "description" : " Determines the sign of a number.

    \n Returns 1 if the number is positive, zero (0) if the number is 0,\n and -1 if the number is negative.

    \n Borrowed from excel module.\n", "summary" : "

    Determines the sign of a number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "double", "occurrence" : null, "description" : "
    The argument
    " } ], "returns" : { "type" : "integer", "description" : "The sign as (-1, 0, 1)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sinh", "qname" : "math:sinh", "signature" : "($arg as double) as double external", "description" : " Calculate the hyperbolic sine.\n", "summary" : "

    Calculate the hyperbolic sine.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : null, "description" : "
    the arg
    " } ], "returns" : { "type" : "double", "description" : "the result of sinh(arg)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "slope", "qname" : "math:slope", "signature" : "($known_y as double+, $known_x as double+) as double", "description" : " Returns the slope of the linear regression line through data points in known_y's and known_x's.

    \n The slope is the vertical distance divided by the horizontal distance between\n any two points on the line, which is the rate of change along the regression line.\n It computes the formula:

    \n sum((x - average_x)(y - average_y)) / sum((x - average_x)^2)

    \n where average_x and average_y are computed with AVERAGE function.

    \n Borrowed from excel module.\n", "summary" : "

    Returns the slope of the linear regression line through data points in known_y's and known_x's.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "known_y", "type" : "double", "occurrence" : "+", "description" : "
    the sequence of y numbers. The sequence can be of any length, from 1 up.
    " }, { "name" : "known_x", "type" : "double", "occurrence" : "+", "description" : "
    the sequence of x numbers. The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "double", "description" : "The slope value, as numeric type" }, "errors" : [ "math:INVALID_INPUT if there are different numbers of x's and y's or if the sequence is empty", "math:DIVIDE_BY_0 if all x's are equal" ] }, { "isDocumented" : true, "arity" : 2, "name" : "small", "qname" : "math:small", "signature" : "($numbers as double*, $k as integer) as double", "description" : " This function computes the k-th smallest value in a data set.

    \n Use this function to return values with a particular relative standing in a data set.\n If n is the number of data points in array, SMALL(array,1) equals the smallest value,\n and SMALL(array,n) equals the largest value.\n Borrowed from excel module.\n", "summary" : "

    This function computes the k-th smallest value in a data set.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "*", "description" : "
    A sequence of numbers. The sequence can be of any length, from 1 up.
    " }, { "name" : "k", "type" : "integer", "occurrence" : null, "description" : "
    The position (from the smallest) in the sequence of data to return. Must have value between 1 and size of sequence.
    " } ], "returns" : { "type" : "double", "description" : "The k-th smallest value of $numbers." }, "errors" : [ "math:INVALID_ARGUMENT if the sequence is zero length or $k is not a value between 1 and the size of sequence." ] }, { "isDocumented" : true, "arity" : 1, "name" : "sort-numbers", "qname" : "math:sort-numbers", "signature" : "($numbers as double*) as double*", "description" : " Sorts a sequence of numbers or arguments castable to numeric.

    \n It first casts all arguments to numeric and then sorts ascending.

    \n Helper function.
    \n Borrowed from excel module.\n", "summary" : "

    Sorts a sequence of numbers or arguments castable to numeric.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "*", "description" : "
    The sequence of arguments castable to numeric.
    " } ], "returns" : { "type" : "double*", "description" : "The sorted sequence as numeric types." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "standardize", "qname" : "math:standardize", "signature" : "($x as double, $mean as double, $standard_dev as double) as double", "description" : " Returns a normalized value from a distribution characterized by mean and standard_dev.

    \n The formula is (x - mean) / standard_dev .

    \n Borrowed from excel module.\n", "summary" : "

    Returns a normalized value from a distribution characterized by mean and standard_dev.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x", "type" : "double", "occurrence" : null, "description" : "
    is the value you want to normalize
    " }, { "name" : "mean", "type" : "double", "occurrence" : null, "description" : "
    is the arithmetic mean of the distribution.
    " }, { "name" : "standard_dev", "type" : "double", "occurrence" : null, "description" : "
    is the standard deviation of the distribution.
    " } ], "returns" : { "type" : "double", "description" : "The normalized x, as numeric type" }, "errors" : [ "math:INVALID_ARGUMENT if standard_dev is a value smaller than zero or equal" ] }, { "isDocumented" : true, "arity" : 1, "name" : "stdev", "qname" : "math:stdev", "signature" : "($numbers as double+) as double", "description" : " Estimates standard deviation based on a sample.

    \n The standard deviation is a measure of how widely values are dispersed\n from the average value (the mean).\n It is computed with formula:\n sqrt( sum((x-average_x)^2) / (n-1) ) = sqrt ( VAR(numbers) )

    \n Borrowed from excel module.\n", "summary" : "

    Estimates standard deviation based on a sample.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "+", "description" : "
    the sequence of numbers The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "double", "description" : "the standard deviation, as numeric type" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "stdeva", "qname" : "math:stdeva", "signature" : "($numbers as double+) as double", "description" : " Estimates standard deviation based on a sample.

    \n The standard deviation is a measure of how widely values are dispersed\n from the average value (the mean).\n It is computed with formula:\n sqrt( sum((x-average_x)^2) / (n-1) ) = sqrt ( VARA(numbers) )

    \n Borrowed from excel module.\n", "summary" : "

    Estimates standard deviation based on a sample.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "+", "description" : "
    the sequence of numbers. The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "double", "description" : "the standard deviation, as numeric type" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "stdevp", "qname" : "math:stdevp", "signature" : "($numbers as double+) as double", "description" : " Calculates standard deviation based on the entire population given as arguments.

    \n The standard deviation is a measure of how widely values are dispersed from\n the average value (the mean).\n It is computed with formula:\n sqrt( sum((x-average_x)^2) / n ) = sqrt ( VARP(numbers) )

    \n Borrowed from excel module.\n", "summary" : "

    Calculates standard deviation based on the entire population given as arguments.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "+", "description" : "
    the sequence of numbers or values castable to numeric The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "double", "description" : "the standard deviation, as numeric type" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "stdevpa", "qname" : "math:stdevpa", "signature" : "($numbers as double+) as double", "description" : " Calculates standard deviation based on the entire population given as arguments.

    \n The standard deviation is a measure of how widely values are dispersed from\n the average value (the mean).\n It is computed with formula:\n sqrt( sum((x-average_x)^2) / n ) = sqrt ( VARPA(numbers) )

    \n Borrowed from excel module.\n", "summary" : "

    Calculates standard deviation based on the entire population given as arguments.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "+", "description" : "
    the sequence of numbers or values castable to numeric The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "double", "description" : "the standard deviation, as numeric type" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "subtotal", "qname" : "math:subtotal", "signature" : "($function_num as integer, $numbers as double*) as double", "description" : " Returns a subtotal in a sequence of numbers.

    \n The function applied is given by $function_num.

    \n Borrowed from excel module.\n", "summary" : "

    Returns a subtotal in a sequence of numbers.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "function_num", "type" : "integer", "occurrence" : null, "description" : "
    defines the function to be applied on sequence values. The possible values are:
    1 or 101
    AVERAGE
    2 or 102
    COUNT
    3 or 103
    COUNTA
    4 or 104
    MAX
    5 or 105
    MIN
    6 or 106
    PRODUCT
    7 or 107
    STDEV
    8 or 108
    STDEVP
    9 or 109
    SUM
    10 or 110
    VAR
    11 or 111
    VARP
    In this implementation there is no difference between x and 10x.
    " }, { "name" : "numbers", "type" : "double", "occurrence" : "*", "description" : "
    the sequence of numbers. The sequence can be of any length.
    " } ], "returns" : { "type" : "double", "description" : "The function result, as numeric type" }, "errors" : [ "* depends on the function called", "math:INVALID_ARGUMENT if $function_num is not a value between 1 .. 11 or 101 .. 111" ] }, { "isDocumented" : true, "arity" : 2, "name" : "sumproduct", "qname" : "math:sumproduct", "signature" : "($array1 as double*, $array2 as double*) as double", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.

    \n Borrowed from excel module.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "double", "occurrence" : "*", "description" : "
    the sequences of numbers
    " }, { "name" : "array2", "type" : "double", "occurrence" : "*", "description" : "
    the sequences of numbers
    " } ], "returns" : { "type" : "double", "description" : "the sum of products" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sumsq", "qname" : "math:sumsq", "signature" : "($numbers as double+) as double", "description" : " Returns the sum of the squares of the arguments.

    \n It uses the sumproduct function.

    \n Borrowed from excel module.\n", "summary" : "

    Returns the sum of the squares of the arguments.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "+", "description" : "
    the sequence of one or more numbers
    " } ], "returns" : { "type" : "double", "description" : "the sum of squared values, as numeric type" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "tanh", "qname" : "math:tanh", "signature" : "($arg as double) as double external", "description" : " Calculate the hyperbolic tangent.\n", "summary" : "

    Calculate the hyperbolic tangent.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : null, "description" : "
    the arg
    " } ], "returns" : { "type" : "double", "description" : "the result of tanh(arg)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "trunc", "qname" : "math:trunc", "signature" : "($number as double) as integer", "description" : " Truncates a number to an integer by removing the fractional part of the number.

    \n Borrowed from excel module.\n", "summary" : "

    Truncates a number to an integer by removing the fractional part of the number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "double", "occurrence" : null, "description" : "
    The argument .
    " } ], "returns" : { "type" : "integer", "description" : "The integer value." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "trunc", "qname" : "math:trunc", "signature" : "($number as double, $precision as integer) as double", "description" : " Truncates a number down to precision.

    \n This behaves exactly like rounddown.

    \n Borrowed from excel module.\n", "summary" : "

    Truncates a number down to precision.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "double", "occurrence" : null, "description" : "
    The argument castable to numeric type.
    " }, { "name" : "precision", "type" : "integer", "occurrence" : null, "description" : "
    The number of decimal places to keep .
    " } ], "returns" : { "type" : "double", "description" : "The integer value." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "var", "qname" : "math:var", "signature" : "($numbers as double+) as double", "description" : " Estimates variance based on a sample.

    \n The formula is sum(x - average_x)^2 / (n - 1).\n average_x is computed with AVERAGE function.\n n is the count of numbers from the sequence, excluding empty values.

    \n Borrowed from excel module.\n", "summary" : "

    Estimates variance based on a sample.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "+", "description" : "
    the sequence of numbers. The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "double", "description" : "The variance, as numeric type" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "vara", "qname" : "math:vara", "signature" : "($numbers as double+) as double", "description" : " Estimates variance based on a sample.

    \n The formula is sum(x - average_x)^2 / (n - 1).\n average_x is computed with AVERAGE function.\n n is the size of sequence, including empty values.

    \n Borrowed from excel module.\n", "summary" : "

    Estimates variance based on a sample.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "+", "description" : "
    the sequence of numbers. The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "double", "description" : "The variance, as numeric type" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "varp", "qname" : "math:varp", "signature" : "($numbers as double+) as double", "description" : " Calculates variance based on the entire population.

    \n The formula is sum(x - average_x)^2 / n.\n average_x is computed with AVERAGE function.\n n is the count of numbers from the sequence, excluding empty values.

    \n Borrowed from excel module.
    \n", "summary" : "

    Calculates variance based on the entire population.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "+", "description" : "
    the sequence of numbers. The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "double", "description" : "The variance, as numeric type" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "varpa", "qname" : "math:varpa", "signature" : "($numbers as double+) as double", "description" : " Calculates variance based on the entire population.

    \n The formula is sum(x - average_x)^2 / n.\n average_x is computed with AVERAGE function.\n n is the size of sequence, including empty values.

    \n Borrowed from excel module.\n", "summary" : "

    Calculates variance based on the entire population.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "double", "occurrence" : "+", "description" : "
    the sequence of numbers. The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "double", "description" : "The variance, as numeric type" }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/oauth/error" : { "ns" : "http://www.zorba-xquery.com/modules/oauth/error", "description" : " Module that defines the errors raised in Oauth modules.\n", "sees" : [ ], "authors" : [ "Stephanie Russell" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.zorba-xquery.com/modules/oauth/error", "prefix" : "oerr" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ ], "variables" : [ { "name" : "oerr:errNS", "type" : "xs:string", "description" : " Errors namespace URI.\n" }, { "name" : "oerr:OC001", "type" : "xs:QName", "description" : " xs:QName with namespace URI=\"http://www.zorba-xquery.com/modules/oauth/errors\" and local name 'OC001'. This signing method is not implemented yet.\n" }, { "name" : "oerr:OC002", "type" : "xs:QName", "description" : " xs:QName with namespace URI=\"http://www.zorba-xquery.com/modules/oauth/errors\" and local name 'OC002'. This signing method is not supported.\n" }, { "name" : "oerr:OC003", "type" : "xs:QName", "description" : " xs:QName with namespace URI=\"http://www.zorba-xquery.com/modules/oauth/errors\" and local name 'OC003'. Http 401 error.\n" }, { "name" : "oerr:OC004", "type" : "xs:QName", "description" : " xs:QName with namespace URI=\"http://www.zorba-xquery.com/modules/oauth/errors\" and local name 'OC004'. Http 500 error.\n" }, { "name" : "oerr:OC005", "type" : "xs:QName", "description" : " xs:QName with namespace URI=\"http://www.zorba-xquery.com/modules/oauth/errors\" and local name 'OC004'. Http 500 error.\n" } ] }, "http://jsoniq.org/functions" : { "ns" : "http://jsoniq.org/functions", "description" : " This module contains all of the functions defined by the JSONiq\n specification (see http://jsoniq.org/).\n

    The module is always imported so you do not need to import it explicitly.\n Also, you do not need to fully qualify a function to invoke it.

    \n", "sees" : [ ], "authors" : [ "Markos Zaharioudakis, Matthias Brantner, Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://jsoniq.org/errors", "prefix" : "jerr" }, { "uri" : "http://jsoniq.org/functions", "prefix" : "jn" }, { "uri" : "http://jsoniq.org/types", "prefix" : "js" }, { "uri" : "http://zorba.io/modules/schema", "prefix" : "schema" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "decode-from-roundtrip", "qname" : "jn:decode-from-roundtrip", "signature" : "($items as item()*) as item()* external", "description" : " This function decodes non-JSON types previously encoded with\n jn:encode-for-roundtrip.\n Calling this version of the function is equivalent to calling the\n 2 argument version of the function with the second argument\n { \"prefix\" : \"Q{http://jsoniq.org/roundtrip}\" }\n", "summary" : "

    This function decodes non-JSON types previously encoded with\n jn:encode-for-roundtrip.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    the items to be decoded.
    " } ], "returns" : { "type" : "item()*", "description" : "the decoded items." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "decode-from-roundtrip", "qname" : "jn:decode-from-roundtrip", "signature" : "($items as item()*, $options as object()) as item()* external", "description" : " This function decodes non-JSON types previously encoded with\n jn:encode-for-roundtrip.\n The $options parameter contains options for the decoding process.\n Currently the only supported option is \"prefix\". It specifies the prefix\n that determines if this function decodes an item.\n Example:\n jn:decode-from-roundtrip(\n { \"nan\" : { \"pre-type\" : \"double\", \"pre-value\" : \"NaN\" } },\n { \"prefix\" : \"pre-\" }\n )\n returns the same instance that would be constructed by\n { \"nan\" : double(\"NaN\") }\n So\n let $decoded := jn:decode-from-roundtrip(\n { \"nan\" : { \"pre-type\" : \"double\", \"pre-value\" : \"NaN\" } },\n { \"prefix\" : \"pre-\" }\n )\n let $nan := $decoded(\"nan\")\n return\n ($nan instance of double, $nan)\n returns\n true NaN\n", "summary" : "

    This function decodes non-JSON types previously encoded with\n jn:encode-for-roundtrip.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    the items to be decoded.
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    the decoding options.
    " } ], "returns" : { "type" : "item()*", "description" : "the decoded items." }, "errors" : [ "jerr:JNTY0023 if $options(\"prefix\") is not a string" ] }, { "isDocumented" : true, "arity" : 1, "name" : "encode-for-roundtrip", "qname" : "jn:encode-for-roundtrip", "signature" : "($items as item()*) as item()* external", "description" : " This function recursively encodes non-JSON types in such a way that they\n can be serialized as JSON while keeping roundtrip capability.\n", "summary" : "

    This function recursively encodes non-JSON types in such a way that they\n can be serialized as JSON while keeping roundtrip capability.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    the items to be encoded.
    " } ], "returns" : { "type" : "item()*", "description" : "the encoded items." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "encode-for-roundtrip", "qname" : "jn:encode-for-roundtrip", "signature" : "($items as item()*, $options as object()) as item()* external", "description" : " This function recursively encodes non-JSON types in such a way that they\n can be serialized as JSON while keeping roundtrip capability.\n Example:\n jn:encode-for-roundtrip(\n { \"nan\" : double(\"NaN\") },\n { \"prefix\" : \"pre-\" }\n )\n returns\n { \"nan\" : { \"pre-type\" : \"double\", \"pre-value\" : \"NaN\" } }\n", "summary" : "

    This function recursively encodes non-JSON types in such a way that they\n can be serialized as JSON while keeping roundtrip capability.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    the items to be encoded.
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    the encoding options.
    " } ], "returns" : { "type" : "item()*", "description" : "the encoded items." }, "errors" : [ "jerr:JNTY0023 if $options(\"prefix\") is not a string" ] }, { "isDocumented" : true, "arity" : 1, "name" : "flatten", "qname" : "jn:flatten", "signature" : "($items as item()*) as item()* external", "description" : " For each item in the given sequence, this function returns the item itself,\n if it is not an array, or a sequence of items \"flattened-out\" from the array.\n Flattening an array means replacing the array with its members, and recursively\n flattening any arrays in the members sequence.\n Note: The function is equivalent to\n define function jn:flatten($args as item()*)\n {\n for $arg in args\n return\n if ($arg instance of array())\n then\n for $value in $arg[]\n return\n if ($value instance of array())\n then jn:flatten($value[])\n else $value\n else\n $arg\n };\n", "summary" : "

    For each item in the given sequence, this function returns the item itself,\n if it is not an array, or a sequence of items \"flattened-out\" from the array.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    A sequence of items
    " } ], "returns" : { "type" : "item()*", "description" : "The flattened-out items of the arrays in $items." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "keys", "qname" : "jn:keys", "signature" : "($o as item()*) as string* external", "description" : " Returns the set of keys belonging to the objects found inside a given\n sequence of items. The keys are returned in an implementation-defined\n order. Duplicate keys are eliminated.\n", "summary" : "

    Returns the set of keys belonging to the objects found inside a given\n sequence of items.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "o", "type" : "item()", "occurrence" : "*", "description" : "
    A sequence of items. Only object items are actually processed; items of any other kind are simply skipped.
    " } ], "returns" : { "type" : "string*", "description" : "The distinct keys of the objects in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "members", "qname" : "jn:members", "signature" : "($a as item()*) as item()* external", "description" : " Returns the items belonging to the arrays found inside a given sequence\n of items. The items are returned in an implementation-defined order.\n", "summary" : "

    Returns the items belonging to the arrays found inside a given sequence\n of items.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "a", "type" : "item()", "occurrence" : "*", "description" : "
    A sequence of items. Only array items are actually processed; items of any other kind are simply skipped.
    " } ], "returns" : { "type" : "item()*", "description" : "The members of the arrays in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "null", "qname" : "jn:null", "signature" : "() as js:null external", "description" : " Returns the JSON null.\n", "summary" : "

    Returns the JSON null.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "js:null", "description" : "The JSON null." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "parse-json", "qname" : "jn:parse-json", "signature" : "($j as string?) as json-item()* external", "description" : " This function parses a given string as JSON and returns a sequence\n of Objects or Arrays.\n Please note that this function allows to parse sequences of whitespace\n separated objects and arrays.\n", "summary" : "

    This function parses a given string as JSON and returns a sequence\n of Objects or Arrays.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "j", "type" : "string", "occurrence" : "?", "description" : "
    A string containing a valid JSON text.
    " } ], "returns" : { "type" : "json-item()*", "description" : "A sequence of JSON Object or Array item." }, "errors" : [ "jerr:JNDY0021 if the given string is not valid JSON." ] }, { "isDocumented" : true, "arity" : 2, "name" : "parse-json", "qname" : "jn:parse-json", "signature" : "($j as string?, $o as object()) as json-item()* external", "description" : " This function parses a given string as JSON and returns a sequence\n of Objects or Arrays.\n", "summary" : "

    This function parses a given string as JSON and returns a sequence\n of Objects or Arrays.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "j", "type" : "string", "occurrence" : "?", "description" : "
    A string containing a valid JSON text.
    " }, { "name" : "o", "type" : "object()", "occurrence" : null, "description" : "
    A JSON object defining options to configure the parser. Allowed options are
    • jsoniq-multiple-top-level-items: allow parsing of sequences of JSON Objects and Arrays (boolean; default: true)
    • jsoniq-strip-top-level-array: if the top-level JSON item is an array, strip it and return its elements as multiple top-level items (boolean; default: false)
    " } ], "returns" : { "type" : "json-item()*", "description" : "a sequence of JSON Object or Array item." }, "errors" : [ "jerr:JNDY0021 if the given string is not valid JSON or if jsoniq-multiple-top-level-items is false and there is additional content after the first JSON Object or Array.", "jerr:JNTY0020 if the value for the option jsoniq-multiple-top-level-items is not of type boolean." ] }, { "isDocumented" : true, "arity" : 2, "name" : "project", "qname" : "jn:project", "signature" : "($items as item()*, $keys as string*) as item()* external", "description" : " For each item in the given sequence, this function returns the item itself,\n if it is not an object, or its \"projected\" copy if it is an object. Projecting\n an object by a set of keys means creating a new object from the specified pairs\n of the source object. Specifically, for each key in $keys, if the object has a\n pair with that key, then a copy of that pair is included in the new object.\n", "summary" : "

    For each item in the given sequence, this function returns the item itself,\n if it is not an object, or its \"projected\" copy if it is an object.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    A sequence of items.
    " }, { "name" : "keys", "type" : "string", "occurrence" : "*", "description" : "
    The keys of the pairs to include from each object in $items.
    " } ], "returns" : { "type" : "item()*", "description" : "The projection of the original sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "size", "qname" : "jn:size", "signature" : "($a as array()?) as integer? external", "description" : " Returns the size of a JSON array, or the empty sequence if no array is given.\n The size of an Array is the number of members contained within it.\n", "summary" : "

    Returns the size of a JSON array, or the empty sequence if no array is given.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "a", "type" : "array()", "occurrence" : "?", "description" : "
    rray A JSON array.
    " } ], "returns" : { "type" : "integer?", "description" : "The number of items in $array, or the empty sequence if $array is empty." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "trim", "qname" : "jn:trim", "signature" : "($items as item()*, $keys as string*) as item()* external", "description" : " For each item in the given sequence, this function returns the item itself,\n if it is not an object, or its \"trimmed\" copy, if it is an object. Trimming\n an object by a set of keys means creating a new object containing all the\n pairs of the source object except the ones whose key appears in the given\n set of keys.\n", "summary" : "

    For each item in the given sequence, this function returns the item itself,\n if it is not an object, or its \"trimmed\" copy, if it is an object.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    A sequence of items.
    " }, { "name" : "keys", "type" : "string", "occurrence" : "*", "description" : "
    The keys of the pairs to exclude from each object in $items.
    " } ], "returns" : { "type" : "item()*", "description" : "The trimmed version of the input sequence." }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/xqdoc" : { "ns" : "http://zorba.io/modules/xqdoc", "description" : "

    \n The goal of xqDoc is to provide a simple vendor neutral solution for\n documenting XQuery modules, as well as tools to generate a user friendly\n presentation of this documentation and cross referencing information.\n Therefore, xqDoc proposes a new commenting convention that extends the\n currently defined XQuery comment style. This convention is modeled\n after Java's Javadoc commenting style, and provides a simple, uniform\n way to document XQuery source code. You can find more information about\n xqDoc on the website of the xqDoc project.\n This library module provides XQDoc utility functions.\n

    \n

    \n Generating a user friendly presentation of the documentation is\n accomplished in the following steps:\n

      \n
    1. Module, variable, function, collection, and index declarations need\n to be commented using the xqDoc commenting conventions. For example,\n this module contains xqDoc-style comments
    2. \n
    3. A xqDoc-enabled processor can parse such documentation and generate\n a vendor neutral XML document which stores all the information about\n the code and the comments. Such a document adheres to the xqDoc\n Schema.
    4. \n
    5. The information of an XML document generated by the second step,\n can be transformed into arbitrary presentation formats\n (e.g. html).
    6. \n
    \n

    \n

    \n This module implements the first and second step of this process.\n That is, Zorba can parse XQuery modules which are annotated with\n xqDoc-style documentation and generate the vendor neutral\n XML representation.\n

    \n", "sees" : [ "xqDoc specification", "xqDoc tutorial with Zorba" ], "authors" : [ "Gabriel Petrovay" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://zorba.io/modules/fetch", "prefix" : "fetch" }, { "uri" : "http://zorba.io/modules/xqdoc-options", "prefix" : "opt" }, { "uri" : "http://zorba.io/modules/schema", "prefix" : "schema" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/modules/xqdoc", "prefix" : "xqd" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "xqdoc-content", "qname" : "xqd:xqdoc-content", "signature" : "($module as xs:string) as element(*)", "description" : " Generated the an XQDoc XML document for the module provided\n as parameter to this function.\n", "summary" : "

    Generated the an XQDoc XML document for the module provided\n as parameter to this function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "module", "type" : "xs:string", "occurrence" : null, "description" : "
    The module (as string) for which to generate the XQDoc documentation.
    " } ], "returns" : { "type" : "element(*)", "description" : "An element according to the xqdoc schema (http://zorba.io/modules/xqdoc.xsd)." }, "errors" : [ "zerr::ZXQD0002 if the xqdoc comments in the module contain invalid XML" ] }, { "isDocumented" : true, "arity" : 2, "name" : "xqdoc-content", "qname" : "xqd:xqdoc-content", "signature" : "($module as xs:string, $options as element(opt:enable)) as element(*)", "description" : " Generated the an XQDoc XML document for the module provided\n as parameter to this function.\n In comparison to the single parameter version, this function does not\n generate XQDoc for all language components. By default, the\n following components are deactivated: XQuery comments, import\n statements, variable declarations, function declarations, collection\n declarations, and index declarations. The second parameter is used to\n enable the XQDoc generation of those components.\n", "summary" : "

    Generated the an XQDoc XML document for the module provided\n as parameter to this function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "module", "type" : "xs:string", "occurrence" : null, "description" : "
    The module (as string) for which to generate the XQDoc documentation.
    " }, { "name" : "options", "type" : "element(opt:enable)", "occurrence" : null, "description" : "
    XQDoc generation options, e.g.:
     <enable xmlns=\"http://zorba.io/modules/xqdoc-options\" comments=\"true\" functions=\"true\" indexes=\"true\" > 
    " } ], "returns" : { "type" : "element(*)", "description" : "An element according to the xqdoc schema (http://zorba.io/modules/xqdoc.xsd)." }, "errors" : [ "zerr::ZXQD0002 if the xqdoc comments in the module contain invalid XML" ] }, { "isDocumented" : true, "arity" : 1, "name" : "xqdoc", "qname" : "xqd:xqdoc", "signature" : "($module-uri as xs:string) as element(*)", "description" : " Generates an XQDoc XML document for the module located\n at the URI provided as parameter to this function.\n", "summary" : "

    Generates an XQDoc XML document for the module located\n at the URI provided as parameter to this function.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "module-uri", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL of the module for which to generate XQDoc.
    " } ], "returns" : { "type" : "element(*)", "description" : "An element according to the xqdoc schema (http://zorba.io/modules/xqdoc.xsd)." }, "errors" : [ "zerr::ZXQD0002 if the xqdoc comments in the module contain invalid XML" ] }, { "isDocumented" : true, "arity" : 2, "name" : "xqdoc", "qname" : "xqd:xqdoc", "signature" : "($module-uri as xs:string, $options as element(opt:enable)) as element(*)", "description" : " Generates an XQDoc XML document for the module located\n at the URI provided as parameter to this function.\n In comparison to the single parameter version, this function does not\n generate XQDoc for all language components. By default, the\n following components are deactivated: XQuery comments, import\n statements, variable declarations, function declarations, collection\n declarations, and index declarations. The second parameter is used to\n enable the XQDoc generation of those components.\n", "summary" : "

    Generates an XQDoc XML document for the module located\n at the URI provided as parameter to this function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "module-uri", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL of the module for which to generate XQDoc.
    " }, { "name" : "options", "type" : "element(opt:enable)", "occurrence" : null, "description" : "
    XQDoc generation options, e.g.:
     <enable xmlns=\"http://zorba.io/modules/xqdoc-options\" comments=\"true\" functions=\"true\" indexes=\"true\" /> 
    " } ], "returns" : { "type" : "element(*)", "description" : "An element according to the xqdoc schema (http://zorba.io/modules/xqdoc.xsd)." }, "errors" : [ "zerr::ZXQD0002 if the xqdoc comments in the module contain invalid XML" ] } ], "variables" : [ ] }, "http://zorba.io/modules/data-cleaning/character-based-string-similarity" : { "ns" : "http://zorba.io/modules/data-cleaning/character-based-string-similarity", "description" : "

    This library module provides character-based string similarity functions\n that view strings as sequences of characters, generally computing a similarity score\n that corresponds to the cost of transforming one string into another.\n These functions are particularly useful for matching near duplicate strings\n in the presence of typographical errors.

    \n

    The logic contained in this module is not specific to any particular XQuery implementation.

    \n", "sees" : [ ], "authors" : [ "Bruno Martins and Diogo Simões" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/data-cleaning/character-based-string-similarity", "prefix" : "simc" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "edit-distance", "qname" : "simc:edit-distance", "signature" : "($s1 as xs:string, $s2 as xs:string) as xs:integer", "description" : "

    Returns the edit distance between two strings.

    \n

    \n

    This distance, also refered to as the Levenshtein distance, is defined as the minimum number\n of edits needed to transform one string into the other, with the allowable edit operations\n being insertion, deletion, or substitution of a single character.

    \n

    \n

    Example usage :

    edit-distance(\"FLWOR\", \"FLOWER\")

    \n

    \n

    The function invocation in the example above returns :

    2

    \n", "summary" : "

    Returns the edit distance between two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The edit distance between the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "jaro-winkler", "qname" : "simc:jaro-winkler", "signature" : "($s1 as xs:string, $s2 as xs:string, $prefix as xs:integer, $fact as xs:double) as xs:double", "description" : "

    Returns the Jaro-Winkler similarity coefficient between two strings.

    \n

    \n

    This similarity coefficient corresponds to an extension of the Jaro similarity coefficient that weights or\n penalizes strings based on their similarity at the beginning of the string, up to a given prefix size.

    \n

    \n

    Example usage :

    jaro-winkler(\"DWAYNE\", \"DUANE\", 4, 0.1 )

    \n

    \n

    The function invocation in the example above returns :

    0.8577777777777778

    \n", "summary" : "

    Returns the Jaro-Winkler similarity coefficient between two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "prefix", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of characters to consider when testing for equal prefixes in the strings.
    " }, { "name" : "fact", "type" : "xs:double", "occurrence" : null, "description" : "
    The weighting factor to consider when the input strings have equal prefixes.
    " } ], "returns" : { "type" : "xs:double", "description" : "The Jaro-Winkler similarity coefficient between the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "jaro", "qname" : "simc:jaro", "signature" : "($s1 as xs:string, $s2 as xs:string) as xs:double", "description" : "

    Returns the Jaro similarity coefficient between two strings.

    \n

    \n

    This similarity coefficient is based on the number of transposed characters and on a\n weighted sum of the percentage of matched characters held within the strings. The higher\n the Jaro-Winkler value is, the more similar the strings are. The coefficient is\n normalized such that 0 equates to no similarity and 1 is an exact match.

    \n

    \n

    Example usage :

    jaro(\"FLWOR Found.\", \"FLWOR Foundation\")

    \n

    \n

    The function invocation in the example above returns :

    0.5853174603174603

    \n", "summary" : "

    Returns the Jaro similarity coefficient between two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " } ], "returns" : { "type" : "xs:double", "description" : "The Jaro similarity coefficient between the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "needleman-wunsch", "qname" : "simc:needleman-wunsch", "signature" : "($s1 as xs:string, $s2 as xs:string, $score as xs:integer, $penalty as xs:integer) as xs:double", "description" : "

    Returns the Needleman-Wunsch distance between two strings.

    \n

    \n

    The Needleman-Wunsch distance is similar to the basic edit distance metric, adding a\n variable cost adjustment to the cost of a gap (i.e., an insertion or deletion) in the\n distance metric.

    \n

    \n

    Example usage :

    needleman-wunsch(\"KAK\", \"KQRK\", 1, 1)

    \n

    \n

    The function invocation in the example above returns :

    0

    \n", "summary" : "

    Returns the Needleman-Wunsch distance between two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "score", "type" : "xs:integer", "occurrence" : null, "description" : "
    The score value.
    " }, { "name" : "penalty", "type" : "xs:integer", "occurrence" : null, "description" : "
    The penalty value.
    " } ], "returns" : { "type" : "xs:double", "description" : "The Needleman-Wunsch distance between the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "smith-waterman", "qname" : "simc:smith-waterman", "signature" : "($s1 as xs:string, $s2 as xs:string, $score as xs:integer, $penalty as xs:integer) as xs:double", "description" : "

    Returns the Smith-Waterman distance between two strings.

    \n

    \n

    Example usage :

    smith-waterman(\"ACACACTA\", \"AGCACACA\", 2, 1)

    \n

    \n

    The function invocation in the example above returns :

    12

    \n", "summary" : "

    Returns the Smith-Waterman distance between two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "score", "type" : "xs:integer", "occurrence" : null, "description" : "
    The score value.
    " }, { "name" : "penalty", "type" : "xs:integer", "occurrence" : null, "description" : "
    The penalty value.
    " } ], "returns" : { "type" : "xs:double", "description" : "The Smith-Waterman distance between the two strings." }, "errors" : [ ] } ], "variables" : [ ] }, "http://expath.org/ns/error" : { "ns" : "http://expath.org/ns/error", "description" : " This module defines all errors for the http-client module.\n", "sees" : [ ], "authors" : [ "Markus Pilman" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://expath.org/ns/error", "prefix" : "err" } ], "functions" : [ ], "variables" : [ { "name" : "err:errNS", "type" : "xs:string", "description" : " Error namespace URI.\n" }, { "name" : "err:HC001", "type" : "xs:QName", "description" : " An HTTP error occurred.\n" }, { "name" : "err:HC002", "type" : "xs:QName", "description" : " Error parsing the entity content as XML or HTML.\n" }, { "name" : "err:HC003", "type" : "xs:QName", "description" : " With a multipart response, the override-media-type must be either a multipart media type or application/octet-stream.\n" }, { "name" : "err:HC004", "type" : "xs:QName", "description" : " The src attribute on the body element is mutually exclusive with all other attribute (except the media-type).\n" }, { "name" : "err:HC005", "type" : "xs:QName", "description" : " The request element is not valid.\n" }, { "name" : "err:HC006", "type" : "xs:QName", "description" : " A timeout occurred waiting for the response.\n" }, { "name" : "err:HCV01", "type" : "xs:QName", "description" : " This error is not defined in the specification but used by the Zorba implementation.\n It gets thrown when the user gives wrong arguments which are statically correct,\n but make no sense (for example: http:send-request((), ())).\n" }, { "name" : "err:HCV02", "type" : "xs:QName", "description" : " Zorba specific error\n This error is raised if trying to follow a redirect for a POST, PUT, or\n DELETE request\n" } ] }, "http://www.28msec.com/modules/s3" : { "ns" : "http://www.28msec.com/modules/s3", "description" : "

    This module provides functionality for managing S3 buckets and object.

    \n

    It is not possible to access buckets whose names are not DNS-compliant. For\n instance a bucket name which contains uppercase letters or is longer than 63\n characters is not DNS-compliant. For additional details on bucket naming\n conventions refer to\n \n Bucket Restrictions and Limitations.

    \n

    Authentication

    \n

    For each functionality two methods are provided:\n

      \n
    • one which allows to specify the credentials to use, by means of the\n optional $credentials parameter (named). If the parameter is not specified,\n the default credentials in the \"S3\" category will be used. If the parameter\n is specified it must be either a string or an object. If it is a string it\n will be interpreted as the name of a credentials in the \"S3\" category. If\n it is an object it must have the following structure:\n
        \n
      • accessKey: the AWS access key to use (string, mandatory).
      • \n
      • secretKey: the AWS secret key to use (string, mandatory).
      • \n
      • useHttps: whether to use secure HTTPS connections or not.\n (boolean, optional). The default is false
      • \n
      • defaultBucket: the default bucket name (string, optional).
      • \n
      \n
    • \n
    • one which does not allow to specify which credentials to use.\n In this case the default credentials in the \"S3\" category will be used.
    • \n
    \n

    \n

    Important Notice Regarding Function Determinism

    \n

    The non side-effecting functions:\n

    \n are declared deterministic, which means that their results could be cached\n when invoked multiple times with the same arguments in the same query execution.

    \n

    To not use cached results you can use the following alternative functions:\n

    \n which have been declared as being non deterministic.

    \n", "sees" : [ ], "authors" : [ "Alexander Kreutz", "Federico Cavalieri" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://www.zorba-xquery.com/modules/cryptography/hmac", "prefix" : "hmac" }, { "uri" : "http://zorba.io/modules/http-client", "prefix" : "http" }, { "uri" : "http://jsoniq.org/errors", "prefix" : "jerr" }, { "uri" : "http://www.28msec.com/modules/s3", "prefix" : "s3" }, { "uri" : "http://s3.amazonaws.com/doc/2006-03-01/", "prefix" : "s3s" }, { "uri" : "http://www.28msec.com/modules/sleep", "prefix" : "sleep" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "copy-object", "qname" : "s3:copy-object", "signature" : "($s3-object-source as item(), $s3-object-target as item()) as item()*", "description" : "

    Copies an object already stored on s3 into a target bucket using the\n default credentials. If the target object already exists it will be overwritten.

    \n

    The source object metadata is copied to the target object, unless new\n metadata is specified. In this case the target object will possess only the\n specified metadata.

    \n

    Unless the permissions for the target are specified, the target object will\n have the \"private\" ACL, that is, the owner gets FULL_CONTROL, and no one else\n has access rights.

    \n

    The source S3 object is specified through the $s3-object-source parameter.\n Either a string or a JSON object can be used. If a string is specified, it is\n interpreted as key for an object in the default bucket of the default\n credentials. If no default bucket is present in the default credentials, the\n s3:BUCKET error is raised. If a JSON object is used, it must have\n the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the default credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the latest version of\n the object will be copied. If specified, only that particular version of the\n object will be copied.
    • \n
    \n

    \n

    The target S3 object is specified through the $s3-object-target parameter.\n Either a string or a JSON object can be used. If a string is specified and the\n default credentials contain a default bucket, the object will be copied in\n the credentials default bucket. Otherwise, the object will be copied in the\n source object bucket. If a JSON object is used, it must have the following\n structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the default credentials contain a default bucket, the object will be\n copied in the credentials default bucket. Otherwise, the object will be\n copied in the source object bucket.
    • \n
    • metadata: an object specifying additional metadata. Each metadata is a\n name-value pair and is represented as different fields (object, optional).\n If not specified, the source object metadata will be copied to the target\n object. Otherwise the target object metadata will be the specified one.
    • \n
    • reducedRedundancy: whether to use reduced-redundancy or not (bool,\n optional). Default is false.
    • \n
    • permission: the permission to set (string, optional). It must be one of\n \"private\", \"public-read\", \"public-read-write\", \"authenticated-read\",\n \"bucket-owner-read\", \"bucket-owner-full-control\". For your convenience the\n following variables can be used: $s3:ACL-GRANT-PRIVATE,\n $s3:ACL-GRANT-PUBLIC-READ, $s3:ACL-GRANT-PUBLIC-READ-WRITE,\n $s3:ACL-GRANT-AUTHENTICATED-READ, $s3:ACL-GRANT-BUCKET-OWNER-READ,\n $s3:ACL-GRANT-BUCKET-OWNER-FULL-CONTROL. If this field is not\n specified, the \"private\" ACL is used, that is, the owner gets FULL_CONTROL,\n and no one else has access rights.
    • \n
    \n

    \n

    Example:\n

    \n let $s3-object-source :=\n {\n   \"key\" : \"test.xml\",\n   \"bucket\": \"28msec\"\n }\n let $s3-object-target :=\n {\n   \"key\" : \"test-copy.xml\",\n   \"bucket\": \"28msec\",\n   \"permisstion\": $s3:ACL-GRANT-PUBLIC-READ\n   \"metadata\":\n   {\n     \"author\": \"28msec\"\n   }\n }\n return s3:copy-object($s3-object-source, $s3-object-target)\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"sourceVersion\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\",\n   \"version\": \"QUpfdndhfd8438MNFDN93jdnJFkdmqnh893\",\n   \"lastModified\": \"2009-10-28T22:32:00\",\n   \"eTag\": \"\\\"9b2cf535f27731c974343645a3985328\\\"\",\n   \"expiration\": \"expiry-date=\\\"Fri, 21 Dec 2012 00:00:00 GMT\\\", rule-id=\\\"Rule for testfile.txt\\\"\"\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • sourceVersion: the version of the copied object. When you enable versioning,\n Amazon S3 generates a random number for objects added to a bucket. The value\n is UTF-8 encoded and URL ready. When the soruce object is copied in a bucket where\n versioning has been suspended, the version ID is always null. (string, optional)
    • \n
    • version: the version of the copied object. When you enable versioning,\n Amazon S3 generates a random number for objects added to a bucket. The value\n is UTF-8 encoded and URL ready. When the soruce object is copied in a bucket where\n versioning has been suspended, the version ID is always null. (string, optional)
    • \n
    • lastModified: the last modification date of the target object. (dateTime, optional)
    • \n
    • eTag: the entity tag is a hash of the copeid object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. The eTag returned by this method is a quoted,\n 32-digit hexadecimal string representing the MD5 digest of the object data.\n For other objects, the eTag may or may not be an MD5 digest of the object data.\n (string, optional).
    • \n
    • expiration: if the object expiration is configured (see\n PUT Bucket lifecycle),\n this field is present. It includes the expiry-date and rule-id key value\n pairs providing object expiration information. The value of rule-id is URL\n encoded.(string, optional).
    • \n
    \n

    \n", "summary" : "

    Copies an object already stored on s3 into a target bucket using the\n default credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "s3-object-source", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to copy from.
    " }, { "name" : "s3-object-target", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object to write to.
    " } ], "returns" : { "type" : "item()*", "description" : "the S3 copy result." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 3, "name" : "copy-object", "qname" : "s3:copy-object", "signature" : "($credentials as item()?, $s3-object-source as item(), $s3-object-target as item()) as object()", "description" : "

    Copies an object already stored on S3 into a target bucket using the\n specified credentials. If the target object already exists it will be overwritten.

    \n

    The source object metadata is copied to the target object, unless new\n metadata is specified. In this case the target object will possess only the\n specified metadata.

    \n

    Unless the permissions for the target are specified, the target object will\n have the \"private\" ACL, that is, the owner gets FULL_CONTROL, and no one else\n has access rights.

    \n

    The source S3 object is specified through the $s3-object-source parameter.\n Either a string or a JSON object can be used. If a string is specified, it is\n interpreted as key for an object in the default bucket of the specified\n credentials. If no default bucket is present in the specified credentials, the\n s3:BUCKET error is raised. If a JSON object is used, it must have\n the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the specified credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the latest version of\n the object will be copied. If specified, only that particular version of the\n object will be copied.
    • \n
    \n

    \n

    The target S3 object is specified through the $s3-object-target parameter.\n Either a string or a JSON object can be used. If a string is specified and the\n specified credentials contain a default bucket, the object will be copied in\n the credentials default bucket. Otherwise, the object will be copied in the\n source object bucket. If a JSON object is used, it must have the following\n structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the specified credentials contain a default bucket, the object will be\n copied in the credentials default bucket. Otherwise, the object will be\n copied in the source object bucket.
    • \n
    • metadata: an object specifying additional metadata. Each metadata is a\n name-value pair and is represented as different fields (object, optional).\n If not specified, the source object metadata will be copied to the target\n object. Otherwise the target object metadata will be the specified one.
    • \n
    • reducedRedundancy: whether to use reduced-redundancy or not (bool,\n optional). Default is false.
    • \n
    • permission: the permission to set (string, optional). It must be one of\n \"private\", \"public-read\", \"public-read-write\", \"authenticated-read\",\n \"bucket-owner-read\", \"bucket-owner-full-control\". For your convenience the\n following variables can be used: $s3:ACL-GRANT-PRIVATE,\n $s3:ACL-GRANT-PUBLIC-READ, $s3:ACL-GRANT-PUBLIC-READ-WRITE,\n $s3:ACL-GRANT-AUTHENTICATED-READ, $s3:ACL-GRANT-BUCKET-OWNER-READ,\n $s3:ACL-GRANT-BUCKET-OWNER-FULL-CONTROL. If this field is not\n specified, the \"private\" ACL is used, that is, the owner gets FULL_CONTROL,\n and no one else has access rights.
    • \n
    \n

    \n

    Example:\n

    \n let $s3-object-source :=\n {\n   \"key\" : \"test.xml\",\n   \"bucket\": \"28msec\"\n }\n let $s3-object-target :=\n {\n   \"key\" : \"test-copy.xml\",\n   \"bucket\": \"28msec\",\n   \"permisstion\": $s3:ACL-GRANT-PUBLIC-READ\n   \"metadata\":\n   {\n     \"author\": \"28msec\"\n   }\n }\n return s3:copy-object(\"credentials\", $s3-object-source, $s3-object-target)\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"sourceVersion\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\",\n   \"version\": \"QUpfdndhfd8438MNFDN93jdnJFkdmqnh893\",\n   \"lastModified\": \"2009-10-28T22:32:00\",\n   \"eTag\": \"\\\"9b2cf535f27731c974343645a3985328\\\"\",\n   \"expiration\": \"expiry-date=\\\"Fri, 21 Dec 2012 00:00:00 GMT\\\", rule-id=\\\"Rule for testfile.txt\\\"\"\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • sourceVersion: the version of the copied object. When you enable versioning,\n Amazon S3 generates a random number for objects added to a bucket. The value\n is UTF-8 encoded and URL ready. When the soruce object is copied in a bucket where\n versioning has been suspended, the version ID is always null. (string, optional)
    • \n
    • version: the version of the copied object. When you enable versioning,\n Amazon S3 generates a random number for objects added to a bucket. The value\n is UTF-8 encoded and URL ready. When the soruce object is copied in a bucket where\n versioning has been suspended, the version ID is always null. (string, optional)
    • \n
    • lastModified: the last modification date of the target object. (dateTime, optional)
    • \n
    • eTag: the entity tag is a hash of the copeid object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. The eTag returned by this method is a quoted,\n 32-digit hexadecimal string representing the MD5 digest of the object data.\n For other objects, the eTag may or may not be an MD5 digest of the object data.\n (string, optional).
    • \n
    \n

    \n", "summary" : "

    Copies an object already stored on S3 into a target bucket using the\n specified credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object-source", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to copy from.
    " }, { "name" : "s3-object-target", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object to write to.
    " } ], "returns" : { "type" : "object()", "description" : "the S3 copy result." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "create-bucket", "qname" : "s3:create-bucket", "signature" : "($bucket as string) as empty-sequence()", "description" : "

    Creates a bucket using the default S3 credentials. The bucket owner will\n be the account of the default S3 credentials.

    \n

    The bucket is created with the S3 default bucket settings. Specifically,\n it is created in the US Standard region and the default credentials\n account becomes its owner. The bucket ACL permissions are set to \"private\",\n that is, the owner gets FULL_CONTROL, whereas no one else has access rights.\n The bucket name must comply with the following rules:\n

      \n
    • bucket names must be no more than 255 characters long.
    • \n
    • bucket names must be a combination of uppercase letters, lowercase letters,\n numbers, periods (.), dashes (-) and underscores (_).
    • \n
    \n For more details, refer to the\n \n Amazon S3 Bucket Restrictions page.\n

    \n

    If the specified bucket already exists in the US Standard region and has\n the same owner, its permissions settings are reset and its contents are\n preserved. Otherwise, if the specified bucket already exists an s3:REQUEST\n error is raised.

    \n

    Example:\n

    \n s3:create-bucket(\"28msec\");\n 
    \n

    \n", "summary" : "

    Creates a bucket using the default S3 credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "bucket", "type" : "string", "occurrence" : null, "description" : "
    The bucket name.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty sequence" }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 2, "name" : "create-bucket", "qname" : "s3:create-bucket", "signature" : "($credentials as item()?, $bucket as string) as empty-sequence()", "description" : "

    Creates a bucket using the specified S3 credentials. The bucket owner will\n be the account of the specified S3 credentials.

    \n

    The bucket is created with the S3 default bucket settings. Specifically,\n it is created in the US Standard region and the specified credentials\n account becomes its owner. The bucket ACL permissions are set to \"private\",\n that is, the owner gets FULL_CONTROL, whereas no one else has access rights.\n The bucket name must comply with the following rules:\n

      \n
    • bucket names must be no more than 255 characters long.
    • \n
    • bucket names must be a combination of uppercase letters, lowercase letters,\n numbers, periods (.), dashes (-) and underscores (_).
    • \n
    \n For more details, refer to the\n \n Amazon S3 Bucket Restrictions page.\n

    \n

    If the specified bucket already exists in the US Standard region and has\n the same owner, its permissions settings are reset and its contents are\n preserved. Otherwise, if the specified bucket already exists an s3:REQUEST\n error is raised.

    \n", "summary" : "

    Creates a bucket using the specified S3 credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "bucket", "type" : "string", "occurrence" : null, "description" : "
    The bucket name.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty sequence" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 1, "name" : "delete-bucket", "qname" : "s3:delete-bucket", "signature" : "($bucket as string) as empty-sequence()", "description" : "

    Deletes a bucket using the default S3 credentials. The bucket must be owned\n by the account of the default S3 credentials.

    \n

    This operation will fail if the deleted bucket is not empty. All objects,\n object versions, and delete markers have to be deleted beforehand using this\n function.

    \n

    Example:\n

    \n s3:delete-bucket(\"28msec\");\n 
    \n

    \n", "summary" : "

    Deletes a bucket using the default S3 credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "bucket", "type" : "string", "occurrence" : null, "description" : "
    The bucket name.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty sequence" }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 2, "name" : "delete-bucket", "qname" : "s3:delete-bucket", "signature" : "($credentials as item()?, $bucket as string) as empty-sequence()", "description" : "

    Deletes a bucket using the specified S3 credentials. The bucket must be owned\n by the account of the specified S3 credentials.

    \n

    This operation will fail if the deleted bucket is not empty. All objects,\n object versions, and delete markers have to be deleted beforehand using this\n function.

    \n

    Example:\n

    \n s3:delete-bucket(\"credentials\", \"28msec\");\n 
    \n

    \n", "summary" : "

    Deletes a bucket using the specified S3 credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "bucket", "type" : "string", "occurrence" : null, "description" : "
    The bucket name.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty sequence" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 1, "name" : "delete-object", "qname" : "s3:delete-object", "signature" : "($s3-object as item()) as empty-sequence()", "description" : "

    Deletes an object or a specific object version from a bucket using the\n default S3 credentials.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the default credentials. If no default\n bucket is present in the default credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the default credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If not specified, the\n null version of the object is removed, if there is one. To remove a specific\n version, this field must be specified.
    • \n
    \n

    \n

    If the bucket is versioned a delete marker is inserted for the object. If\n mfa-deletion is enabled you will not be able to delete an object through\n this method. If the specified bucket exists, and the specified object does not\n exist no errors will be raised.

    \n

    Example:\n

    \n s3:delete-object(\n {\n   \"key\": \"test.xml\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\"\n });\n 
    \n

    \n", "summary" : "

    Deletes an object or a specific object version from a bucket using the\n default S3 credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to delete.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty sequence" }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "delete-object", "qname" : "s3:delete-object", "signature" : "($credentials as item()?, $s3-object as item()) as empty-sequence()", "description" : "

    Deletes an object or a specific object version from a bucket using the\n specified S3 credentials.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the specified credentials. If no default\n bucket is present in the specified credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the specified credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If not specified, the\n null version of the object is removed, if there is one. To remove a specific\n version, this field must be specified.
    • \n
    \n

    \n

    If the bucket is versioned a delete marker is inserted for the object. If\n mfa-deletion is enabled you will not be able to delete an object through\n this method. If the specified bucket exists, and the specified object does not\n exist no errors will be raised.

    \n

    Example:\n

    \n s3:delete-object(\"credentials\",\n {\n   \"key\": \"test.xml\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\"\n });\n 
    \n

    \n", "summary" : "

    Deletes an object or a specific object version from a bucket using the\n specified S3 credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to delete.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty sequence" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 0, "name" : "list-bucket-nondeterministic", "qname" : "s3:list-bucket-nondeterministic", "signature" : "() as object()", "description" : "

    Lists the objects in the default bucket of the default S3 credentials.

    \n

    This function has the same semantics as\n list-bucket#0,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists the objects in the default bucket of the default S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "the list of objects in the default bucket of the default S3 credentials" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no default bucket is present in the default S3 credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "list-bucket-nondeterministic", "qname" : "s3:list-bucket-nondeterministic", "signature" : "($bucket as string?) as object()", "description" : "

    Lists the objects in a bucket using the default S3 credentials.

    \n

    This function has the same semantics as\n list-bucket#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists the objects in a bucket using the default S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "bucket", "type" : "string", "occurrence" : "?", "description" : "
    The bucket to list. If the empty sequence is given, the default bucket of the default S3 credentials will be listed.
    " } ], "returns" : { "type" : "object()", "description" : "the list of the objects in the specified bucket." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-bucket-nondeterministic", "qname" : "s3:list-bucket-nondeterministic", "signature" : "($bucket as string?, $options as object()?) as object()", "description" : "

    Lists the objects in a bucket using the default S3 credentials.\n This method allows the specification of additional listing options.

    \n

    This function has the same semantics as\n list-bucket#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists the objects in a bucket using the default S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "bucket", "type" : "string", "occurrence" : "?", "description" : "
    The bucket to list. If the empty sequence is given, the default bucket of the default S3 credentials will be listed.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    The listing options.
    " } ], "returns" : { "type" : "object()", "description" : "the list of the object in the specified bucket" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the default credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-bucket-nondeterministic", "qname" : "s3:list-bucket-nondeterministic", "signature" : "($credentials as item()?, $bucket as string?, $options as object()?) as object()", "description" : "

    Lists the objects in a bucket using the specified credentials.\n This method allows the specification of additional listing options.

    \n

    This function has the same semantics as\n list-bucket#3,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists the objects in a bucket using the specified credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "bucket", "type" : "string", "occurrence" : "?", "description" : "
    The bucket to list. If the empty sequence is given, the default bucket of the specified credentials will be listed.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    The listing options.
    " } ], "returns" : { "type" : "object()", "description" : "the list of the object in the specified bucket" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 0, "name" : "list-bucket-versions-nondeterministic", "qname" : "s3:list-bucket-versions-nondeterministic", "signature" : "() as object()", "description" : "

    Lists the objects versions in the default bucket of the default S3\n credentials.

    \n

    This function has the same semantics as\n list-bucket-versions#0,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists the objects versions in the default bucket of the default S3\n credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "the list of the object versions in the default bucket of the default S3 credentials" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no default bucket is present in the default S3 credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "list-bucket-versions-nondeterministic", "qname" : "s3:list-bucket-versions-nondeterministic", "signature" : "($bucket as string?) as object()", "description" : "

    Lists the objects versions in a bucket using the default S3 credentials.

    \n

    This function has the same semantics as\n list-bucket-versions#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists the objects versions in a bucket using the default S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "bucket", "type" : "string", "occurrence" : "?", "description" : "
    The bucket to list. If the empty sequence is given, the default bucket of the default credentials will be listed.
    " } ], "returns" : { "type" : "object()", "description" : "the list of the object versions in the specified bucket" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-bucket-versions-nondeterministic", "qname" : "s3:list-bucket-versions-nondeterministic", "signature" : "($bucket as string?, $options as object()?) as object()", "description" : "

    Lists the objects versions in a bucket using the default S3 credentials.\n This method allows the specification of additional listing options.

    \n

    This function has the same semantics as\n list-bucket-versions#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists the objects versions in a bucket using the default S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "bucket", "type" : "string", "occurrence" : "?", "description" : "
    The bucket to list. If the empty sequence is given, the default bucket of the default credentials will be listed.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    The listing options.
    " } ], "returns" : { "type" : "object()", "description" : "the list of the object versions in the specified bucket" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the default credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-bucket-versions-nondeterministic", "qname" : "s3:list-bucket-versions-nondeterministic", "signature" : "($credentials as item()?, $bucket as string?, $options as object()?) as object()", "description" : "

    Lists the objects versions in a bucket using the specified credentials.\n This method allows the specification of additional listing options.

    \n

    This function has the same semantics as\n list-bucket-versions#3,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists the objects versions in a bucket using the specified credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "bucket", "type" : "string", "occurrence" : "?", "description" : "
    The bucket to list. If the empty sequence is given, the default bucket of the specified credentials will be listed.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    The listing options.
    " } ], "returns" : { "type" : "object()", "description" : "the list of the object in the specified bucket" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 0, "name" : "list-bucket-versions", "qname" : "s3:list-bucket-versions", "signature" : "() as object()", "description" : "

    Lists the objects versions in the default bucket of the default S3\n credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Example:\n

    \n s3:list-bucket-versions()\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"name\": \"bucket\",\n   \"prefix\": \"\",\n   \"keyMarker\" : \"image.jpg\",\n   \"versionIdMarker\" : \"QUpfdndhfd8438MNFDN93jdnJFkdmqnh893\",\n   \"nextKeyMarker\": \"marker\",\n   \"nextVersionIdMarker\": \"UIORUnfndfhnw89493jJFJ\",\n   \"maxKeys\": 1,\n   \"delimiter\": \"/\",\n   \"isTruncated\": true,\n   \"revisions\":\n   [\n     {\n       \"kind\": \"Version\",\n       \"key\": \"image.jpg\",\n       \"versionId\": \"QUpfdndhfd8438MNFDN93jdnJFkdmqnh893\",\n       \"isLatest\": false,\n       \"lastModified\": \"2009-10-12T17:50:30.000Z\",\n       \"eTag\": \"\\\"fba9dede5f27731c9771645a39863328\\\"\",\n       \"size\": 434234,\n       \"storageClass\": \"STANDARD\",\n       \"owner\":\n       {\n         \"id\": \"75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a\"\n         \"displayName\": \"mtd@amazon.com\"\n       }\n     },\n     {\n       \"kind\": \"DeleteMarker\",\n       \"key\": \"image.jpg\",\n       \"versionId\": \"03jpff543dhffds434rfdsFDN943fdsFkdmqnh892\",\n       \"isLatest\": true,\n       \"lastModified\": \"2009-10-12T17:50:30.000Z\",\n       \"owner\":\n       {\n         \"id\": \"75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a\"\n         \"displayName\": \"mtd@amazon.com\"\n       }\n     }\n   ],\n   \"commonPrefixes\": [\"photos/\"]\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • name: the bucket name (string, mandatory).
    • \n
    • prefix: the used prefix (string, mandatory).
    • \n
    • keyMarker: indicates from which key in the listing begins\n (string, mandatory).
    • \n
    • versionMarker: indicates from which version the listing begins\n (string, optional).
    • \n
    • nextKeyMarker: when the number of responses exceeds the value of maxKeys,\n nextKeyMarker specifies the first key not returned that satisfies the search\n criteria. Use this value for the keyMarker request parameter in a subsequent\n request. (string, optional)
    • \n
    • nextVersionMarker: when the number of responses exceeds the value of maxKeys,\n nextVersionIdMarker specifies the first object version not returned that\n satisfies the search criteria. Use this value for the versionMarker request\n parameter in a subsequent request. (string, optional)
    • \n
    • maxKeys: the maximum number of keys returned in the response body\n (integer, mandatory).
    • \n
    • delimiter: the used delimiter (string, optional).
    • \n
    • isTruncated: whether or not all of the results were returned. All of the\n results may not be returned if the number of results exceeds that specified\n by the maxKeys request parameter (boolean, mandatory).
    • \n
    • revisions: an array of objects listing the bucket object versions\n (array, mandatory). The fields of each contained object have the following\n meaning:\n
        \n
      • kind: the revision kind. One of \"Version\" or \"DeleteMarker\" (string,\n mandatory).
      • \n
      • key: the object key (string, mandatory).
      • \n
      • versionId: the object version id (string, mandatory).
      • \n
      • lastModified: the object last modification date (dateTime, mandatory).
      • \n
      • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. For objects created by the PUT Object operation\n and the POST Object operation, the eTag is a quoted, 32-digit hexadecimal\n string representing the MD5 digest of the object data. For other objects,\n the eTag may or may not be an MD5 digest of the object data. If the eTag is\n not an MD5 digest of the object data, it will contain one or more non-hexadecimal\n characters and/or will consist of less than 32 or more than 32 hexadecimal\n digits.(string, mandatory for \"Version\" objects, not present for\n \"DeleteMarker\" objects).
      • \n
      • size: the object size in bytes (integer, mandatory for \"Version\" objects,\n not present for \"DeleteMarker\" objects).
      • \n
      • storageClass: the object storage class. One of \"STANDARD\",\n \"REDUCED_REDUNDANCY\" or \"GLACIER\" (string, mandatory for \"Version\" objects,\n not present for \"DeleteMarker\" objects).
      • \n
      • owner: an object which specifies the owner of the object (object,\n optional). It has the following fields:\n
          \n
        • id: the user identifier of the object owner (string, mandatory).
        • \n
        • displayName: the screen name of the object owner (string, mandatory).
        • \n
        \n
      • \n
      \n
    • \n
    • commonPrefixes: an array of strings which contains the list of the common\n prefixes. It can be present only when the delimiter request parameter is\n specified (array, optional).
    • \n
    \n

    \n", "summary" : "

    Lists the objects versions in the default bucket of the default S3\n credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "the list of the object versions in the default bucket of the default S3 credentials" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no default bucket is present in the default S3 credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "list-bucket-versions", "qname" : "s3:list-bucket-versions", "signature" : "($bucket as string?) as object()", "description" : "

    Lists the objects versions in a bucket using the default S3 credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Example:\n

    \n s3:list-bucket-versions(\"28msec\")\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"name\": \"bucket\",\n   \"prefix\": \"\",\n   \"keyMarker\" : \"image.jpg\",\n   \"versionIdMarker\" : \"QUpfdndhfd8438MNFDN93jdnJFkdmqnh893\",\n   \"nextKeyMarker\": \"marker\",\n   \"nextVersionIdMarker\": \"UIORUnfndfhnw89493jJFJ\",\n   \"maxKeys\": 1,\n   \"delimiter\": \"/\",\n   \"isTruncated\": true,\n   \"revisions\":\n   [\n     {\n       \"kind\": \"Version\",\n       \"key\": \"image.jpg\",\n       \"versionId\": \"QUpfdndhfd8438MNFDN93jdnJFkdmqnh893\",\n       \"isLatest\": false,\n       \"lastModified\": \"2009-10-12T17:50:30.000Z\",\n       \"eTag\": \"\\\"fba9dede5f27731c9771645a39863328\\\"\",\n       \"size\": 434234,\n       \"storageClass\": \"STANDARD\",\n       \"owner\":\n       {\n         \"id\": \"75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a\"\n         \"displayName\": \"mtd@amazon.com\"\n       }\n     },\n     {\n       \"kind\": \"DeleteMarker\",\n       \"key\": \"image.jpg\",\n       \"versionId\": \"03jpff543dhffds434rfdsFDN943fdsFkdmqnh892\",\n       \"isLatest\": true,\n       \"lastModified\": \"2009-10-12T17:50:30.000Z\",\n       \"owner\":\n       {\n         \"id\": \"75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a\"\n         \"displayName\": \"mtd@amazon.com\"\n       }\n     }\n   ],\n   \"commonPrefixes\": [\"photos/\"]\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • name: the bucket name (string, mandatory).
    • \n
    • prefix: the used prefix (string, mandatory).
    • \n
    • keyMarker: indicates from which key in the listing begins\n (string, mandatory).
    • \n
    • versionMarker: indicates from which version the listing begins\n (string, optional).
    • \n
    • nextKeyMarker: when the number of responses exceeds the value of maxKeys,\n nextKeyMarker specifies the first key not returned that satisfies the search\n criteria. Use this value for the keyMarker request parameter in a subsequent\n request. (string, optional)
    • \n
    • nextVersionMarker: when the number of responses exceeds the value of maxKeys,\n nextVersionIdMarker specifies the first object version not returned that\n satisfies the search criteria. Use this value for the versionMarker request\n parameter in a subsequent request. (string, optional)
    • \n
    • maxKeys: the maximum number of keys returned in the response body\n (integer, mandatory).
    • \n
    • delimiter: the used delimiter (string, optional).
    • \n
    • isTruncated: whether or not all of the results were returned. All of the\n results may not be returned if the number of results exceeds that specified\n by the maxKeys request parameter (boolean, mandatory).
    • \n
    • revisions: an array of objects listing the bucket object versions\n (array, mandatory). The fields of each contained object have the following\n meaning:\n
        \n
      • kind: the revision kind. One of \"Version\" or \"DeleteMarker\" (string,\n mandatory).
      • \n
      • key: the object key (string, mandatory).
      • \n
      • versionId: the object version id (string, mandatory).
      • \n
      • lastModified: the object last modification date (dateTime, mandatory).
      • \n
      • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. For objects created by the PUT Object operation\n and the POST Object operation, the eTag is a quoted, 32-digit hexadecimal\n string representing the MD5 digest of the object data. For other objects,\n the eTag may or may not be an MD5 digest of the object data. If the eTag is\n not an MD5 digest of the object data, it will contain one or more non-hexadecimal\n characters and/or will consist of less than 32 or more than 32 hexadecimal\n digits.(string, mandatory for \"Version\" objects, not present for\n \"DeleteMarker\" objects).
      • \n
      • size: the object size in bytes (integer, mandatory for \"Version\" objects,\n not present for \"DeleteMarker\" objects).
      • \n
      • storageClass: the object storage class. One of \"STANDARD\",\n \"REDUCED_REDUNDANCY\" or \"GLACIER\" (string, mandatory for \"Version\" objects,\n not present for \"DeleteMarker\" objects).
      • \n
      • owner: an object which specifies the owner of the object (object,\n optional). It has the following fields:\n
          \n
        • id: the user identifier of the object owner (string, mandatory).
        • \n
        • displayName: the screen name of the object owner (string, mandatory).
        • \n
        \n
      • \n
      \n
    • \n
    • commonPrefixes: an array of strings which contains the list of the common\n prefixes. It can be present only when the delimiter request parameter is\n specified (array, optional).
    • \n
    \n

    \n", "summary" : "

    Lists the objects versions in a bucket using the default S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "bucket", "type" : "string", "occurrence" : "?", "description" : "
    The bucket to list. If the empty sequence is given, the default bucket of the default credentials will be listed.
    " } ], "returns" : { "type" : "object()", "description" : "the list of the object versions in the specified bucket" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-bucket-versions", "qname" : "s3:list-bucket-versions", "signature" : "($bucket as string?, $options as object()?) as object()", "description" : "

    Lists the objects versions in a bucket using the default S3 credentials.\n This method allows the specification of additional listing options.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Example:\n

    \n let $options :=\n {\n   \"delimiter\": \"/\",\n   \"maxKeys\": 2,\n   \"keyMarker\": \"image.jpg\",\n   \"versionIdMarker\" : \"QUpfdndhfd8438MNFDN93jdnJFkdmqnh893\"\n }\n return s3:list-bucket-versions(\"28msec\", $options)\n 
    \n

    \n

    The options object must have the following structure:\n

      \n
    • delimiter: the delimiter marks where the listed results stop. For example,\n a delimiter / lists all objects starting with $prefix plus arbitrary\n characters but not / (string, optional). Default is the empty string,\n that is, all objects are listed.
    • \n
    • keyMarker: specifies a key as starting point; following keys (lexicographically\n greater than the marker) in alphabetical order are listed (string, optional).\n Default is the empty string, that is, all objects are listed.
    • \n
    • versionMarker: specifies the object version you want starting from;\n following revisions (newer than the marker) are listed (string, optional).\n By default all versions are listed. Empty string is not allowed.
    • \n
    • maxKeys: the maximum number of keys returned. If more keys than maxKeys\n can be fetched, the result contains true\n (integer, optional). Default is 1000.
    • \n
    • prefix: only keys starting with the prefix are returned (string, optional).\n Default is the empty string, that is, all objects are listed.
    • \n
    \n

    \n

    Example return object:\n

    \n {\n   \"name\": \"bucket\",\n   \"prefix\": \"\",\n   \"keyMarker\" : \"image.jpg\",\n   \"versionIdMarker\" : \"QUpfdndhfd8438MNFDN93jdnJFkdmqnh893\",\n   \"nextKeyMarker\": \"marker\",\n   \"nextVersionIdMarker\": \"UIORUnfndfhnw89493jJFJ\",\n   \"maxKeys\": 1,\n   \"delimiter\": \"/\",\n   \"isTruncated\": true,\n   \"revisions\":\n   [\n     {\n       \"kind\": \"Version\",\n       \"key\": \"image.jpg\",\n       \"versionId\": \"QUpfdndhfd8438MNFDN93jdnJFkdmqnh893\",\n       \"isLatest\": false,\n       \"lastModified\": \"2009-10-12T17:50:30.000Z\",\n       \"eTag\": \"\\\"fba9dede5f27731c9771645a39863328\\\"\",\n       \"size\": 434234,\n       \"storageClass\": \"STANDARD\",\n       \"owner\":\n       {\n         \"id\": \"75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a\"\n         \"displayName\": \"mtd@amazon.com\"\n       }\n     },\n     {\n       \"kind\": \"DeleteMarker\",\n       \"key\": \"image.jpg\",\n       \"versionId\": \"03jpff543dhffds434rfdsFDN943fdsFkdmqnh892\",\n       \"isLatest\": true,\n       \"lastModified\": \"2009-10-12T17:50:30.000Z\",\n       \"owner\":\n       {\n         \"id\": \"75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a\"\n         \"displayName\": \"mtd@amazon.com\"\n       }\n     }\n   ],\n   \"commonPrefixes\": [\"photos/\"]\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • name: the bucket name (string, mandatory).
    • \n
    • prefix: the used prefix (string, mandatory).
    • \n
    • keyMarker: indicates from which key in the listing begins\n (string, mandatory).
    • \n
    • versionMarker: indicates from which version the listing begins\n (string, optional).
    • \n
    • nextKeyMarker: when the number of responses exceeds the value of maxKeys,\n nextKeyMarker specifies the first key not returned that satisfies the search\n criteria. Use this value for the keyMarker request parameter in a subsequent\n request. (string, optional)
    • \n
    • nextVersionMarker: when the number of responses exceeds the value of maxKeys,\n nextVersionIdMarker specifies the first object version not returned that\n satisfies the search criteria. Use this value for the versionMarker request\n parameter in a subsequent request. (string, optional)
    • \n
    • maxKeys: the maximum number of keys returned in the response body\n (integer, mandatory).
    • \n
    • delimiter: the used delimiter (string, optional).
    • \n
    • isTruncated: whether or not all of the results were returned. All of the\n results may not be returned if the number of results exceeds that specified\n by the maxKeys request parameter (boolean, mandatory).
    • \n
    • revisions: an array of objects listing the bucket object versions\n (array, mandatory). The fields of each contained object have the following\n meaning:\n
        \n
      • kind: the revision kind. One of \"Version\" or \"DeleteMarker\" (string,\n mandatory).
      • \n
      • key: the object key (string, mandatory).
      • \n
      • versionId: the object version id (string, mandatory).
      • \n
      • lastModified: the object last modification date (dateTime, mandatory).
      • \n
      • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. For objects created by the PUT Object operation\n and the POST Object operation, the eTag is a quoted, 32-digit hexadecimal\n string representing the MD5 digest of the object data. For other objects,\n the eTag may or may not be an MD5 digest of the object data. If the eTag is\n not an MD5 digest of the object data, it will contain one or more non-hexadecimal\n characters and/or will consist of less than 32 or more than 32 hexadecimal\n digits.(string, mandatory for \"Version\" objects, not present for\n \"DeleteMarker\" objects).
      • \n
      • size: the object size in bytes (integer, mandatory for \"Version\" objects,\n not present for \"DeleteMarker\" objects).
      • \n
      • storageClass: the object storage class. One of \"STANDARD\",\n \"REDUCED_REDUNDANCY\" or \"GLACIER\" (string, mandatory for \"Version\" objects,\n not present for \"DeleteMarker\" objects).
      • \n
      • owner: an object which specifies the owner of the object (object,\n optional). It has the following fields:\n
          \n
        • id: the user identifier of the object owner (string, mandatory).
        • \n
        • displayName: the screen name of the object owner (string, mandatory).
        • \n
        \n
      • \n
      \n
    • \n
    • commonPrefixes: an array of strings which contains the list of the common\n prefixes. It can be present only when the delimiter request parameter is\n specified (array, optional).
    • \n
    \n

    \n", "summary" : "

    Lists the objects versions in a bucket using the default S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "bucket", "type" : "string", "occurrence" : "?", "description" : "
    The bucket to list. If the empty sequence is given, the default bucket of the default credentials will be listed.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    The listing options.
    " } ], "returns" : { "type" : "object()", "description" : "the list of the object versions in the specified bucket" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the default credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-bucket-versions", "qname" : "s3:list-bucket-versions", "signature" : "($credentials as item()?, $bucket as string?, $options as object()?) as object()", "description" : "

    Lists the objects versions in a bucket using the specified credentials.\n This method allows the specification of additional listing options.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Example:\n

    \n let $options :=\n {\n   \"delimiter\": \"/\",\n   \"maxKeys\": 2,\n   \"keyMarker\": \"image.jpg\",\n   \"versionIdMarker\": \"QUpfdndhfd8438MNFDN93jdnJFkdmqnh893\"\n }\n return s3:list-bucket-versions(\"credentials\", \"28msec\", $options)\n 
    \n

    \n

    The options object must have the following structure:\n

      \n
    • delimiter: the delimiter marks where the listed results stop. For example,\n a delimiter / lists all objects starting with $prefix plus arbitrary\n characters but not / (string, optional). Default is the empty string,\n that is, all objects are listed.
    • \n
    • keyMarker: specifies a key as starting point; following keys (lexicographically\n greater than the marker) in alphabetical order are listed (string, optional).\n Default is the empty string, that is, all objects are listed.
    • \n
    • versionMarker: specifies the object version you want starting from;\n following revisions (newer than the marker) are listed (string, optional).\n By default all versions are listed. Empty string is not allowed.
    • \n
    • maxKeys: the maximum number of keys returned. If more keys than maxKeys\n can be fetched, the result contains true\n (integer, optional). Default is 1000.
    • \n
    • prefix: only keys starting with the prefix are returned (string, optional).\n Default is the empty string, that is, all objects are listed.
    • \n
    \n

    \n

    Example return object:\n

    \n {\n   \"name\": \"bucket\",\n   \"prefix\": \"\",\n   \"keyMarker\" : \"image.jpg\",\n   \"VersionIdMarker\" : \"QUpfdndhfd8438MNFDN93jdnJFkdmqnh893\",\n   \"nextKeyMarker\": \"marker\",\n   \"nextVersionIdMarker\": \"UIORUnfndfhnw89493jJFJ\",\n   \"maxKeys\": 1,\n   \"delimiter\": \"/\",\n   \"isTruncated\": true,\n   \"revisions\":\n   [\n     {\n       \"kind\": \"Version\",\n       \"key\": \"image.jpg\",\n       \"versionId\": \"QUpfdndhfd8438MNFDN93jdnJFkdmqnh893\",\n       \"isLatest\": false,\n       \"lastModified\": \"2009-10-12T17:50:30.000Z\",\n       \"eTag\": \"\\\"fba9dede5f27731c9771645a39863328\\\"\",\n       \"size\": 434234,\n       \"storageClass\": \"STANDARD\",\n       \"owner\":\n       {\n         \"id\": \"75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a\"\n         \"displayName\": \"mtd@amazon.com\"\n       }\n     },\n     {\n       \"kind\": \"DeleteMarker\",\n       \"key\": \"image.jpg\",\n       \"versionId\": \"03jpff543dhffds434rfdsFDN943fdsFkdmqnh892\",\n       \"isLatest\": true,\n       \"lastModified\": \"2009-10-12T17:50:30.000Z\",\n       \"owner\":\n       {\n         \"id\": \"75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a\"\n         \"displayName\": \"mtd@amazon.com\"\n       }\n     }\n   ],\n   \"commonPrefixes\": [\"photos/\"]\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • name: the bucket name (string, mandatory).
    • \n
    • prefix: the used prefix (string, mandatory).
    • \n
    • keyMarker: indicates from which key in the listing begins\n (string, mandatory).
    • \n
    • versionMarker: indicates from which version the listing begins\n (string, optional).
    • \n
    • nextKeyMarker: when the number of responses exceeds the value of maxKeys,\n nextKeyMarker specifies the first key not returned that satisfies the search\n criteria. Use this value for the keyMarker request parameter in a subsequent\n request. (string, optional)
    • \n
    • nextVersionMarker: when the number of responses exceeds the value of maxKeys,\n nextVersionIdMarker specifies the first object version not returned that\n satisfies the search criteria. Use this value for the versionMarker request\n parameter in a subsequent request. (string, optional)
    • \n
    • maxKeys: the maximum number of keys returned in the response body\n (integer, mandatory).
    • \n
    • delimiter: the used delimiter (string, optional).
    • \n
    • isTruncated: whether or not all of the results were returned. All of the\n results may not be returned if the number of results exceeds that specified\n by the maxKeys request parameter (boolean, mandatory).
    • \n
    • revisions: an array of objects listing the bucket object versions\n (array, mandatory). The fields of each contained object have the following\n meaning:\n
        \n
      • kind: the revision kind. One of \"Version\" or \"DeleteMarker\" (string,\n mandatory).
      • \n
      • key: the object key (string, mandatory).
      • \n
      • versionId: the object version id (string, mandatory).
      • \n
      • lastModified: the object last modification date (dateTime, mandatory).
      • \n
      • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. For objects created by the PUT Object operation\n and the POST Object operation, the eTag is a quoted, 32-digit hexadecimal\n string representing the MD5 digest of the object data. For other objects,\n the eTag may or may not be an MD5 digest of the object data. If the eTag is\n not an MD5 digest of the object data, it will contain one or more non-hexadecimal\n characters and/or will consist of less than 32 or more than 32 hexadecimal\n digits.(string, mandatory for \"Version\" objects, not present for\n \"DeleteMarker\" objects).
      • \n
      • size: the object size in bytes (integer, mandatory for \"Version\" objects,\n not present for \"DeleteMarker\" objects).
      • \n
      • storageClass: the object storage class. One of \"STANDARD\",\n \"REDUCED_REDUNDANCY\" or \"GLACIER\" (string, mandatory for \"Version\" objects,\n not present for \"DeleteMarker\" objects).
      • \n
      • owner: an object which specifies the owner of the object (object,\n optional). It has the following fields:\n
          \n
        • id: the user identifier of the object owner (string, mandatory).
        • \n
        • displayName: the screen name of the object owner (string, mandatory).
        • \n
        \n
      • \n
      \n
    • \n
    • commonPrefixes: an array of strings which contains the list of the common\n prefixes. It can be present only when the delimiter request parameter is\n specified (array, optional).
    • \n
    \n

    \n", "summary" : "

    Lists the objects versions in a bucket using the specified credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "bucket", "type" : "string", "occurrence" : "?", "description" : "
    The bucket to list. If the empty sequence is given, the default bucket of the specified credentials will be listed.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    The listing options.
    " } ], "returns" : { "type" : "object()", "description" : "the list of the object in the specified bucket" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 0, "name" : "list-bucket", "qname" : "s3:list-bucket", "signature" : "() as object()", "description" : "

    Lists the objects in the default bucket of the default S3 credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Example:\n

    \n s3:list-bucket(\"28msec\")\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"name\": \"28msec\",\n   \"prefix\": \"\",\n   \"marker\" : \"\",\n   \"nextMarker\": \"marker\",\n   \"maxKeys\": 1,\n   \"delimiter\": \"\",\n   \"isTruncated\": true,\n   \"contents\":\n   [\n     {\n       \"key\": \"image.jpg\",\n       \"lastModified\": \"2009-10-12T17:50:30.000Z\",\n       \"eTag\": \"\\\"fba9dede5f27731c9771645a39863328\\\"\",\n       \"size\": 434234,\n       \"storageClass\": \"STANDARD\"\n       \"owner\":\n       {\n         \"id\": \"75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a\"\n         \"displayName\": \"mtd@amazon.com\"\n       }\n     }\n   ]\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • name: the bucket name (string, mandatory).
    • \n
    • prefix: the used prefix (string, mandatory).
    • \n
    • marker: indicates where in the bucket listing begins (string, mandatory).
    • \n
    • nextMarker: when the response is truncated, you can use the key name\n in this field as marker in the subsequent request to get next set of objects.\n Amazon S3 lists objects in alphabetical order. This field is returned only\n if you have specified the delimiter request parameter. If the response does\n not include the nextMaker field and it is truncated, you can use the value\n of the last Key in the response as the marker in the subsequent request to\n get the next set of object keys. (string, optional)
    • \n
    • maxKeys: the maximum number of keys returned in the response body\n (integer, mandatory).
    • \n
    • delimiter: the used delimiter (string, optional).
    • \n
    • isTruncated: whether or not all of the results were returned. All of the\n results may not be returned if the number of results exceeds that specified\n by the maxKeys request parameter (boolean, mandatory).
    • \n
    • contents: an array of objects listing the bucket content (array, mandatory).\n The fields of each contained object have the following meaning:\n
        \n
      • key: the object key (string, mandatory).
      • \n
      • lastModified: the object last modification date (dateTime, mandatory).
      • \n
      • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. For objects created by the PUT Object operation\n and the POST Object operation, the eTag is a quoted, 32-digit hexadecimal\n string representing the MD5 digest of the object data. For other objects,\n the eTag may or may not be an MD5 digest of the object data. If the eTag is\n not an MD5 digest of the object data, it will contain one or more non-hexadecimal\n characters and/or will consist of less than 32 or more than 32 hexadecimal\n digits.(string, mandatory).
      • \n
      • storageClass: the object storage class. One of \"STANDARD\",\n \"REDUCED_REDUNDANCY\" or \"GLACIER\" (string, mandatory).
      • \n
      • owner: an object which specifies the owner of the object (object,\n optional). It has the following fields:\n
          \n
        • id: the user identifier of the object owner (string, mandatory).
        • \n
        • displayName: the screen name of the object owner (string, mandatory).
        • \n
        \n
      • \n
      \n
    • \n
    \n

    \n", "summary" : "

    Lists the objects in the default bucket of the default S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "the list of objects in the default bucket of the default S3 credentials" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no default bucket is present in the default S3 credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "list-bucket", "qname" : "s3:list-bucket", "signature" : "($bucket as string?) as object()", "description" : "

    Lists the objects in a bucket using the default S3 credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Example:\n

    \n s3:list-bucket(\"28msec\")\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"name\": \"28msec\",\n   \"prefix\": \"\",\n   \"marker\" : \"\",\n   \"nextMarker\": \"marker\",\n   \"maxKeys\": 1,\n   \"delimiter\": \"\",\n   \"isTruncated\": true,\n   \"contents\":\n   [\n     {\n       \"key\": \"image.jpg\",\n       \"lastModified\": \"2009-10-12T17:50:30.000Z\",\n       \"eTag\": \"\\\"fba9dede5f27731c9771645a39863328\\\"\",\n       \"size\": 434234,\n       \"storageClass\": \"STANDARD\"\n       \"owner\":\n       {\n         \"id\": \"75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a\"\n         \"displayName\": \"mtd@amazon.com\"\n       }\n     }\n   ]\n }\n 
    \n The meanings of the fields in the return object are the following:\n
      \n
    • name: the bucket name (string, mandatory).
    • \n
    • prefix: the used prefix (string, mandatory).
    • \n
    • marker: indicates where in the bucket listing begins (string, mandatory).
    • \n
    • nextMarker: when the response is truncated, you can use the key name\n in this field as marker in the subsequent request to get next set of objects.\n Amazon S3 lists objects in alphabetical order. This field is returned only\n if you have specified the delimiter request parameter. If the response does\n not include the nextMaker field and it is truncated, you can use the value\n of the last Key in the response as the marker in the subsequent request to\n get the next set of object keys. (string, optional)
    • \n
    • maxKeys: the maximum number of keys returned in the response body\n (integer, mandatory).
    • \n
    • delimiter: the used delimiter (string, optional).
    • \n
    • isTruncated: whether or not all of the results were returned. All of the\n results may not be returned if the number of results exceeds that specified\n by the maxKeys request parameter (boolean, mandatory).
    • \n
    • contents: an array of objects listing the bucket content (array, mandatory).\n The fields of each contained object have the following meaning:\n
        \n
      • key: the object key (string, mandatory).
      • \n
      • lastModified: the object last modification date (dateTime, mandatory).
      • \n
      • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. For objects created by the PUT Object operation\n and the POST Object operation, the eTag is a quoted, 32-digit hexadecimal\n string representing the MD5 digest of the object data. For other objects,\n the eTag may or may not be an MD5 digest of the object data. If the eTag is\n not an MD5 digest of the object data, it will contain one or more non-hexadecimal\n characters and/or will consist of less than 32 or more than 32 hexadecimal\n digits.(string, mandatory).
      • \n
      • storageClass: the object storage class. One of \"STANDARD\",\n \"REDUCED_REDUNDANCY\" or \"GLACIER\" (string, mandatory).
      • \n
      • owner: an object which specifies the owner of the object (object,\n optional). It has the following fields:\n
          \n
        • id: the user identifier of the object owner (string, mandatory).
        • \n
        • displayName: the screen name of the object owner (string, mandatory).
        • \n
        \n
      • \n
      \n
    • \n
    \n

    \n", "summary" : "

    Lists the objects in a bucket using the default S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "bucket", "type" : "string", "occurrence" : "?", "description" : "
    The bucket to list. If the empty sequence is given, the default bucket of the default S3 credentials will be listed.
    " } ], "returns" : { "type" : "object()", "description" : "the list of the objects in the specified bucket." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-bucket", "qname" : "s3:list-bucket", "signature" : "($bucket as string?, $options as object()?) as object()", "description" : "

    Lists the objects in a bucket using the default S3 credentials.\n This method allows the specification of additional listing options.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Example:\n

    \n let $options :=\n {\n   \"delimiter\": \"/\",\n   \"marker\": \"\",\n   \"maxKeys\": 1,\n   \"prefix\": \"\"\n }\n return s3:list-bucket(\"credentials\", \"28msec\", $options)\n 
    \n

    \n

    The options object must have the following structure:\n

      \n
    • delimiter: the delimiter marks where the listed results stop. For example,\n a delimiter / lists all objects starting with $prefix plus arbitrary\n characters but not / (string, optional). Default is the empty string,\n that is, all objects are listed.
    • \n
    • marker: specifies a key as starting point; following keys (lexicographically\n greater than the marker) in alphabetical order are listed (string, optional).\n Default is the empty string, that is, all objects are listed.
    • \n
    • maxKeys: the maximum number of keys returned. If more keys than maxKeys\n can be fetched, the result contains true\n (integer, optional). Default is 1000.
    • \n
    • prefix: only keys starting with the prefix are returned (string, optional).\n Default is the empty string, that is, all objects are listed.
    • \n
    \n

    \n

    Example return object:\n

    \n {\n   \"name\": \"bucket\",\n   \"prefix\": \"\",\n   \"marker\" : \"\",\n   \"nextMarker\": \"marker\",\n   \"maxKeys\": 1,\n   \"delimiter\": \"/\",\n   \"isTruncated\": true,\n   \"contents\":\n   [\n     {\n       \"key\": \"image.jpg\",\n       \"lastModified\": \"2009-10-12T17:50:30.000Z\",\n       \"eTag\": \"\\\"fba9dede5f27731c9771645a39863328\\\"\",\n       \"size\": 434234,\n       \"storageClass\": \"STANDARD\"\n       \"owner\":\n       {\n         \"id\": \"75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a\"\n         \"displayName\": \"mtd@amazon.com\"\n       }\n     }\n   ],\n   \"commonPrefixes\": [\"photos/\"]\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • name: the bucket name (string, mandatory).
    • \n
    • prefix: the used prefix (string, mandatory).
    • \n
    • marker: indicates where in the bucket listing begins (string, mandatory).
    • \n
    • nextMarker: when the response is truncated, you can use the key name\n in this field as marker in the subsequent request to get next set of objects.\n Amazon S3 lists objects in alphabetical order. This field is returned only\n if you have specified the delimiter request parameter. If the response does\n not include the nextMaker field and it is truncated, you can use the value\n of the last Key in the response as the marker in the subsequent request to\n get the next set of object keys. (string, optional)
    • \n
    • maxKeys: the maximum number of keys returned in the response body\n (integer, mandatory).
    • \n
    • delimiter: the used delimiter (string, optional).
    • \n
    • isTruncated: whether or not all of the results were returned. All of the\n results may not be returned if the number of results exceeds that specified\n by the maxKeys request parameter (boolean, mandatory).
    • \n
    • contents: an array of objects listing the bucket content (array, mandatory).\n The fields of each contained object have the following meaning:\n
        \n
      • key: the object key (string, mandatory).
      • \n
      • lastModified: the object last modification date (dateTime, mandatory).
      • \n
      • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. For objects created by the PUT Object operation\n and the POST Object operation, the eTag is a quoted, 32-digit hexadecimal\n string representing the MD5 digest of the object data. For other objects,\n the eTag may or may not be an MD5 digest of the object data. If the eTag is\n not an MD5 digest of the object data, it will contain one or more non-hexadecimal\n characters and/or will consist of less than 32 or more than 32 hexadecimal\n digits.(string, mandatory).
      • \n
      • storageClass: the object storage class. One of \"STANDARD\",\n \"REDUCED_REDUNDANCY\" or \"GLACIER\" (string, mandatory).
      • \n
      • owner: an object which specifies the owner of the object (object,\n optional). It has the following fields:\n
          \n
        • id: the user identifier of the object owner (string, mandatory).
        • \n
        • displayName: the screen name of the object owner (string, mandatory).
        • \n
        \n
      • \n
      \n
    • \n
    • commonPrefixes: an array of strings which contains the list of the common\n prefixes. It can be present only when the delimiter request parameter is\n specified (array, optional).
    • \n
    \n

    \n", "summary" : "

    Lists the objects in a bucket using the default S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "bucket", "type" : "string", "occurrence" : "?", "description" : "
    The bucket to list. If the empty sequence is given, the default bucket of the default S3 credentials will be listed.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    The listing options.
    " } ], "returns" : { "type" : "object()", "description" : "the list of the object in the specified bucket" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the default credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-bucket", "qname" : "s3:list-bucket", "signature" : "($credentials as item()?, $bucket as string?, $options as object()?) as object()", "description" : "

    Lists the objects in a bucket using the specified credentials.\n This method allows the specification of additional listing options.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Example:\n

    \n let $options :=\n {\n   \"delimiter\": \"/\",\n   \"marker\": \"\",\n   \"maxKeys\": 1,\n   \"prefix\": \"\"\n }\n return s3:list-bucket(\"credentials\", \"28msec\", $options)\n 
    \n

    \n

    The options object must have the following structure:\n

      \n
    • delimiter: the delimiter marks where the listed results stop. For example,\n a delimiter / lists all objects starting with $prefix plus arbitrary\n characters but not / (string, optional). Default is the empty string,\n that is, all objects are listed.
    • \n
    • marker: specifies a key as starting point; following keys (lexicographically\n greater than the marker) in alphabetical order are listed (string, optional).\n Default is the empty string, that is, all objects are listed.
    • \n
    • maxKeys: the maximum number of keys returned. If more keys than maxKeys\n can be fetched, the result contains true\n (integer, optional). Default is 1000.
    • \n
    • prefix: only keys starting with the prefix are returned (string, optional).\n Default is the empty string, that is, all objects are listed.
    • \n
    \n

    \n

    Example result:\n

    \n {\n   \"name\": \"bucket\",\n   \"prefix\": \"\",\n   \"marker\" : \"\",\n   \"nextMarker\": \"marker\",\n   \"maxKeys\": 1,\n   \"delimiter\": \"/\",\n   \"isTruncated\": true,\n   \"contents\":\n   [\n     {\n       \"key\": \"image.jpg\",\n       \"lastModified\": \"2009-10-12T17:50:30.000Z\",\n       \"eTag\": \"\\\"fba9dede5f27731c9771645a39863328\\\"\",\n       \"size\": 434234,\n       \"storageClass\": \"STANDARD\"\n       \"owner\":\n       {\n         \"id\": \"75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a\"\n         \"displayName\": \"mtd@amazon.com\"\n       }\n     }\n   ],\n   \"commonPrefixes\": [\"photos/\"]\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • name: the bucket name (string, mandatory).
    • \n
    • prefix: the used prefix (string, mandatory).
    • \n
    • marker: indicates where in the bucket listing begins (string, mandatory).
    • \n
    • nextMarker: when the response is truncated, you can use the key name\n in this field as marker in the subsequent request to get next set of objects.\n Amazon S3 lists objects in alphabetical order. This field is returned only\n if you have specified the delimiter request parameter. If the response does\n not include the nextMaker field and it is truncated, you can use the value\n of the last Key in the response as the marker in the subsequent request to\n get the next set of object keys. (string, optional)
    • \n
    • maxKeys: the maximum number of keys returned in the response body\n (integer, mandatory).
    • \n
    • delimiter: the used delimiter (string, optional).
    • \n
    • isTruncated: whether or not all of the results were returned. All of the\n results may not be returned if the number of results exceeds that specified\n by the maxKeys request parameter (boolean, mandatory).
    • \n
    • contents: an array of objects listing the bucket content (array, mandatory).\n The fields of each contained object have the following meaning:\n
        \n
      • key: the object key (string, mandatory).
      • \n
      • lastModified: the object last modification date (dateTime, mandatory).
      • \n
      • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. For objects created by the PUT Object operation\n and the POST Object operation, the eTag is a quoted, 32-digit hexadecimal\n string representing the MD5 digest of the object data. For other objects,\n the eTag may or may not be an MD5 digest of the object data. If the eTag is\n not an MD5 digest of the object data, it will contain one or more non-hexadecimal\n characters and/or will consist of less than 32 or more than 32 hexadecimal\n digits.(string, mandatory).
      • \n
      • storageClass: the object storage class. One of \"STANDARD\",\n \"REDUCED_REDUNDANCY\" or \"GLACIER\" (string, mandatory).
      • \n
      • owner: an object which specifies the owner of the object (object,\n optional). It has the following fields:\n
          \n
        • id: the user identifier of the object owner (string, mandatory).
        • \n
        • displayName: the screen name of the object owner (string, mandatory).
        • \n
        \n
      • \n
      \n
    • \n
    • commonPrefixes: an array of strings which contains the list of the common\n prefixes. It can be present only when the delimiter request parameter is\n specified (array, optional).
    • \n
    \n

    \n", "summary" : "

    Lists the objects in a bucket using the specified credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "bucket", "type" : "string", "occurrence" : "?", "description" : "
    The bucket to list. If the empty sequence is given, the default bucket of the specified credentials will be listed.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    The listing options.
    " } ], "returns" : { "type" : "object()", "description" : "the list of the object in the specified bucket" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:OPTIONS if the specified options are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 0, "name" : "list-buckets-nondeterministic", "qname" : "s3:list-buckets-nondeterministic", "signature" : "() as object()", "description" : "

    Lists all buckets owned by the account of the default S3 credentials.

    \n

    This function has the same semantics as\n list-buckets#0,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists all buckets owned by the account of the default S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "the owned buckets list" }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "list-buckets-nondeterministic", "qname" : "s3:list-buckets-nondeterministic", "signature" : "($credentials as item()?) as object()", "description" : "

    Lists all buckets owned by the account of the specified S3 credentials.

    \n

    This function has the same semantics as\n list-buckets#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists all buckets owned by the account of the specified S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " } ], "returns" : { "type" : "object()", "description" : "the owned buckets list" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 0, "name" : "list-buckets", "qname" : "s3:list-buckets", "signature" : "() as object()", "description" : "

    Lists all buckets owned by the account of the default S3 credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Example:\n

    \n s3:list-buckets()\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"owner\" :\n   {\n     \"id\": \"dfe08489302934392afe39239fe953039d9e2af0c94\",\n     \"displayName\": \"28msec\"\n   },\n   \"buckets\" :\n   [\n     {\n       \"name\": \"28msec\",\n       \"creationDate\": \"2010-11-03T17:42:45.000Z\",\n     }\n   ]\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • owner: an object which specifies the owner of the bucket (object,\n mandatory). It has the following fields:\n
        \n
      • id: the user identifier of the bucket owner (string, mandatory).
      • \n
      • displayName: the screen name of the bucket owner (string, mandatory).
      • \n
      \n
    • \n
    • buckets: an array which contains an object for each owned bucket\n (array, mandatory). Each object contains the following fields:\n
        \n
      • name: the bucket name (string, mandatory).
      • \n
      • creationDate: the bucket creation date. (dateTime, mandatory).
      • \n
      \n
    • \n
    \n

    \n", "summary" : "

    Lists all buckets owned by the account of the default S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "the owned buckets list" }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "list-buckets", "qname" : "s3:list-buckets", "signature" : "($credentials as item()?) as object()", "description" : "

    Lists all buckets owned by the account of the specified S3 credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Example:\n

    \n s3:list-buckets(\"credentials\")\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"owner\" :\n   {\n     \"id\": \"dfe08489302934392afe39239fe953039d9e2af0c94\",\n     \"displayName\": \"28msec\"\n   },\n   \"buckets\" :\n   [\n     {\n       \"name\": \"28msec\",\n       \"creationDate\": \"2010-11-03T17:42:45.000Z\",\n     }\n   ]\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • owner: an object which specifies the owner of the bucket (object,\n mandatory). It has the following fields:\n
        \n
      • id: the user identifier of the bucket owner (string, mandatory).
      • \n
      • displayName: the screen name of the bucket owner (string, mandatory).
      • \n
      \n
    • \n
    • buckets: an array which contains an object for each owned bucket\n (array, mandatory). Each object contains the following fields:\n
        \n
      • name: the bucket name (string, mandatory).
      • \n
      • creationDate: the bucket creation date. (dateTime, mandatory).
      • \n
      \n
    • \n
    \n

    \n", "summary" : "

    Lists all buckets owned by the account of the specified S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " } ], "returns" : { "type" : "object()", "description" : "the owned buckets list" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "object-metadata-nondeterministic", "qname" : "s3:object-metadata-nondeterministic", "signature" : "($s3-object as item()) as object()", "description" : "

    Retrieves an object metadata using the default S3 credentials.

    \n

    This function has the same semantics as\n object-metadata#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves an object metadata using the default S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve the metadata for.
    " } ], "returns" : { "type" : "object()", "description" : "the specified object metadata." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "object-metadata-nondeterministic", "qname" : "s3:object-metadata-nondeterministic", "signature" : "($credentials as item()?, $s3-object as item()) as object()", "description" : "

    Retrieves an object metadata using the specified S3 credentials.

    \n

    This function has the same semantics as\n object-metadata#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves an object metadata using the specified S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve the metadata for.
    " } ], "returns" : { "type" : "object()", "description" : "the specified object metadata." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "object-metadata", "qname" : "s3:object-metadata", "signature" : "($s3-object as item()) as object()", "description" : "

    Retrieves an object metadata using the default S3 credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the default credentials. If no default\n bucket is present in the default credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the default credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the metadata of the\n latest version of the object will be returned. If specified, only the\n metadata of that particular version of the object will be returned.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\"\n }\n return s3:metadata-object($object)\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"key\": \"test.xml\",\n   \"bucket\": \"28msec\",\n   \"metadata\":\n   {\n     \"author\": \"28msec\"\n   },\n   \"missing-metadata\" : 1,\n   \"version\": \"3GL4kqtJlcpXroDTDm3vjVBH40Nr8X8g\",\n   \"expiration\": \"expiry-date=\\\"Fri, 21 Dec 2012 00:00:00 GMT\\\", rule-id=\\\"Rule for testfile.txt\\\"\"\n   \"restore\": \"x-amz-restore: ongoing-request=\\\"false\\\", expiry-date=\\\"Wed, 07 Nov 2012 00:00:00 GMT\\\"\"\n   \"serverSideEncryption\": \"AES256\",\n   \"lastModified\": \"Mon, 15 Oct 2012 21:58:07 GMT\",\n   \"eTag\": \"1accb31fcf202eba0c0f41fa2f09b4d7\",\n   \"mediaType\": \"text/plain\"\n   \"length\": \"28\"\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, mandatory).
    • \n
    • metadata: an object specifying additional metadata. Each metadata is a\n name-value pair and is represented as different fields (object, optional).
    • \n
    • missing-metadata: the number of metadata entries that were not returned\n in the metadata object. This can happen if you create metadata using an API\n like SOAP that supports more flexible metadata than the REST API. (integer,\n optional).
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the permissions for the\n latest version of the object will be returned. If specified, only the\n permissions for that particular version of the object will be returned.
    • \n
    • expiration: if the object expiration is configured (see\n PUT Bucket lifecycle),\n this field is present. It includes the expiry-date and rule-id key value\n pairs providing object expiration information. The value of rule-id is URL\n encoded.(string, optional).
    • \n
    • restore: if the object is an archived object (an object whose storage\n class is Glacier), the response includes this header if either the archive\n restoration is in progress (see\n POST Object restore),\n or an archive copy is already restored.(string, optional).
    • \n
    • serverSideEncryption: If the object is stored by using server-side\n encryption, the response includes this header with a value of the encryption\n algorithm that was used.(string, optional).
    • \n
    • lastModified: the date in which the object was last modified (dateTime,\n optional).
    • \n
    • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. For objects created by the PUT Object operation\n and the POST Object operation, the eTag is a quoted, 32-digit hexadecimal\n string representing the MD5 digest of the object data. For other objects,\n the eTag may or may not be an MD5 digest of the object data. If the eTag is\n not an MD5 digest of the object data, it will contain one or more non-hexadecimal\n characters and/or will consist of less than 32 or more than 32 hexadecimal\n digits.(string, optional).
    • \n
    • mediaType: the object media-type (string, mandatory).
    • \n
    • length: the object content length (integer, optional).
    • \n
    \n

    \n", "summary" : "

    Retrieves an object metadata using the default S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve the metadata for.
    " } ], "returns" : { "type" : "object()", "description" : "the specified object metadata." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "object-metadata", "qname" : "s3:object-metadata", "signature" : "($credentials as item()?, $s3-object as item()) as object()", "description" : "

    Retrieves an object metadata using the specified S3 credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the specified credentials. If no default\n bucket is present in the specified credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the specified credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the metadata of the\n latest version of the object will be returned. If specified, only the\n metadata of that particular version of the object will be returned.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\"\n }\n return s3:metadata-object(\"credentials\", $object)\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"key\": \"test.xml\",\n   \"bucket\": \"28msec\",\n   \"metadata\":\n   {\n     \"author\": \"28msec\"\n   },\n   \"missing-metadata\" : 1,\n   \"version\": \"3GL4kqtJlcpXroDTDm3vjVBH40Nr8X8g\",\n   \"expiration\": \"expiry-date=\\\"Fri, 21 Dec 2012 00:00:00 GMT\\\", rule-id=\\\"Rule for testfile.txt\\\"\"\n   \"restore\": \"x-amz-restore: ongoing-request=\\\"false\\\", expiry-date=\\\"Wed, 07 Nov 2012 00:00:00 GMT\\\"\"\n   \"serverSideEncryption\": \"AES256\",\n   \"lastModified\": \"Mon, 15 Oct 2012 21:58:07 GMT\",\n   \"eTag\": \"1accb31fcf202eba0c0f41fa2f09b4d7\",\n   \"mediaType\": \"text/plain\"\n   \"length\": \"28\"\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, mandatory).
    • \n
    • metadata: an object specifying additional metadata. Each metadata is a\n name-value pair and is represented as different fields (object, optional).
    • \n
    • missing-metadata: the number of metadata entries that were not returned\n in the metadata object. This can happen if you create metadata using an API\n like SOAP that supports more flexible metadata than the REST API. (integer,\n optional).
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the permissions for the\n latest version of the object will be returned. If specified, only the\n permissions for that particular version of the object will be returned.
    • \n
    • expiration: if the object expiration is configured (see\n PUT Bucket lifecycle),\n this field is present. It includes the expiry-date and rule-id key value\n pairs providing object expiration information. The value of rule-id is URL\n encoded.(string, optional).
    • \n
    • restore: if the object is an archived object (an object whose storage\n class is Glacier), the response includes this header if either the archive\n restoration is in progress (see\n POST Object restore),\n or an archive copy is already restored.(string, optional).
    • \n
    • serverSideEncryption: If the object is stored by using server-side\n encryption, the response includes this header with a value of the encryption\n algorithm that was used.(string, optional).
    • \n
    • lastModified: the date in which the object was last modified (dateTime,\n optional).
    • \n
    • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. For objects created by the PUT Object operation\n and the POST Object operation, the eTag is a quoted, 32-digit hexadecimal\n string representing the MD5 digest of the object data. For other objects,\n the eTag may or may not be an MD5 digest of the object data. If the eTag is\n not an MD5 digest of the object data, it will contain one or more non-hexadecimal\n characters and/or will consist of less than 32 or more than 32 hexadecimal\n digits.(string, optional).
    • \n
    • mediaType: the object media-type (string, mandatory).
    • \n
    • length: the object content length (integer, optional).
    • \n
    \n

    \n", "summary" : "

    Retrieves an object metadata using the specified S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve the metadata for.
    " } ], "returns" : { "type" : "object()", "description" : "the specified object metadata." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "object-permissions-nondeterministic", "qname" : "s3:object-permissions-nondeterministic", "signature" : "($s3-object as item()) as object()", "description" : "

    Retrieves the access control list (ACL) of an S3 object using the default\n S3 credentials.

    \n

    This function has the same semantics as\n object-permissions#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves the access control list (ACL) of an S3 object using the default\n S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve the ACL for.
    " } ], "returns" : { "type" : "object()", "description" : "the object ACL" }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "object-permissions-nondeterministic", "qname" : "s3:object-permissions-nondeterministic", "signature" : "($credentials as item()?, $s3-object as item()) as object()", "description" : "

    Retrieves the access control list (ACL) of an S3 object using the specified\n credentials.

    \n

    This function has the same semantics as\n object-permissions#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves the access control list (ACL) of an S3 object using the specified\n credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve the ACL for.
    " } ], "returns" : { "type" : "object()", "description" : "the object ACL" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "object-permissions", "qname" : "s3:object-permissions", "signature" : "($s3-object as item()) as object()", "description" : "

    Retrieves the access control list (ACL) of an S3 object using the default\n S3 credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the default credentials. If no default\n bucket is present in the default credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the default credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the permissions for the\n latest version of the object will be returned. If specified, only the\n permissions for that particular version of the object will be returned.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\"\n }\n return s3:object-permissions($object)\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"owner\" :\n   {\n     \"id\" : \"ea3617f5543e366a51bf51f440c221410b8001c34744e9d3a81acb79cff9d2ed\",\n     \"displayName\" : \"28msec\"\n   },\n   \"acl\" :\n   [\n     {\n       \"grantee\" :\n       {\n         \"type\" : \"CanonicalUser\",\n         \"id\" : \"ea3617f5543e366a51bf51f440c221410b8001c34744e9d3a81acb79cff9d2ed\",\n         \"displayName\" : \"28msec\"\n       },\n       \"permission\" : \"FULL_CONTROL\"\n     }\n   ]\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • owner: an object which specifies the owner of the object (object,\n mandatory). It has the following fields:\n
        \n
      • id: the user identifier of the object owner (string, mandatory).
      • \n
      • displayName: the screen name of the object owner (string, mandatory).
      • \n
      \n
    • \n
    • acl: an array which contains an object for each grantee with the corresponding\n ACL settings (array, mandatory). Each object contains the following fields:\n
        \n
      • grantee: specifies the permissions grantee (object, mandatory). It\n contains the following fields:\n
          \n
        • type: one of \"AmazonCustomerByEmail\", \"CanonicalUser\" or \"Group\".
        • \n
        • emailAddress: the customer email address (string, present in all\n and only AmazonCustomerByEmail grantees).
        • \n
        • id: the user identifier (string, present in all and only CanonicalUser\n grantees).
        • \n
        • displayName: the user screen name (string, present in all and only\n CanonicalUser grantees).
        • \n
        • URI: the group URI (string, present in all and only Group grantees).
        • \n
        \n
      • \n
      • permission: the granted permissions. One of \"READ\", \"WRITE\", \"READ_ACP\",\n \"WRITE_ACP\", \"FULL_CONTROL\". (string, mandatory).
      • \n
      \n
    • \n
    \n

    \n", "summary" : "

    Retrieves the access control list (ACL) of an S3 object using the default\n S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve the ACL for.
    " } ], "returns" : { "type" : "object()", "description" : "the object ACL" }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "object-permissions", "qname" : "s3:object-permissions", "signature" : "($credentials as item()?, $s3-object as item()) as object()", "description" : "

    Retrieves the access control list (ACL) of an S3 object using the specified\n credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the specified credentials. If no default\n bucket is present in the specified credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the specified credentials does not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the permissions for the\n latest version of the object will be returned. If specified, only the\n permissions for that particular version of the object will be returned.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\"\n }\n return s3:object-permissions(\"credentials\", $object)\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"owner\" :\n   {\n     \"id\" : \"ea3617f5543e366a51bf51f440c221410b8001c34744e9d3a81acb79cff9d2ed\",\n     \"displayName\" : \"28msec\"\n   },\n   \"acl\" :\n   [\n     {\n       \"grantee\" :\n       {\n         \"type\" : \"CanonicalUser\",\n         \"id\" : \"ea3617f5543e366a51bf51f440c221410b8001c34744e9d3a81acb79cff9d2ed\",\n         \"displayName\" : \"28msec\"\n       },\n       \"permission\" : \"FULL_CONTROL\"\n     }\n   ]\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • owner: an object which specifies the owner of the object (object,\n mandatory). It has the following fields:\n
        \n
      • id: the user identifier of the object owner (string, mandatory).
      • \n
      • displayName: the screen name of the object owner (string, mandatory).
      • \n
      \n
    • \n
    • acl: an array which contains an object for each grantee with the corresponding\n ACL settings (array, mandatory). Each object contains the following fields:\n
        \n
      • grantee: specifies the permissions grantee (object, mandatory). It contains\n the following fields:\n
          \n
        • type: one of \"AmazonCustomerByEmail\", \"CanonicalUser\" or \"Group\".
        • \n
        • emailAddress: the customer email address (string, present in all\n and only AmazonCustomerByEmail grantees).
        • \n
        • id: the user identifier (string, present in all and only CanonicalUser\n grantees).
        • \n
        • displayName: the user screen name (string, present in all and only\n CanonicalUser grantees).
        • \n
        • URI: the group URI (string, present in all and only Group grantees).
        • \n
        \n
      • \n
      • permission: the granted permissions. One of \"READ\", \"WRITE\", \"READ_ACP\",\n \"WRITE_ACP\", \"FULL_CONTROL\". (string, mandatory).
      • \n
      \n
    • \n
    \n

    \n", "summary" : "

    Retrieves the access control list (ACL) of an S3 object using the specified\n credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve the ACL for.
    " } ], "returns" : { "type" : "object()", "description" : "the object ACL" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "object-torrent-nondeterministic", "qname" : "s3:object-torrent-nondeterministic", "signature" : "($s3-object as item()) as base64Binary", "description" : "

    Returns a torrent file for a given object using the default S3 credentials.

    \n

    This function has the same semantics as\n object-torrent#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Returns a torrent file for a given object using the default S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object to retrieve the torrent file for
    " } ], "returns" : { "type" : "base64Binary", "description" : "the base64 encoded torrent file for the specified object." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "object-torrent-nondeterministic", "qname" : "s3:object-torrent-nondeterministic", "signature" : "($credentials as item()?, $s3-object as item()) as base64Binary", "description" : "

    Returns a torrent file for a given object using the specified S3 credentials.

    \n

    This function has the same semantics as\n object-torrent#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Returns a torrent file for a given object using the specified S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object to retrieve the torrent file for
    " } ], "returns" : { "type" : "base64Binary", "description" : "the base64 encoded torrent file of the specified object." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "object-torrent", "qname" : "s3:object-torrent", "signature" : "($s3-object as item()) as base64Binary", "description" : "

    Returns a torrent file for a given object using the default S3 credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the default credentials. If no default\n bucket is present in the default credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the default credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\"\n }\n return s3:object-torrent($object)\n 
    \n

    \n", "summary" : "

    Returns a torrent file for a given object using the default S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object to retrieve the torrent file for
    " } ], "returns" : { "type" : "base64Binary", "description" : "the base64 encoded torrent file for the specified object." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "object-torrent", "qname" : "s3:object-torrent", "signature" : "($credentials as item()?, $s3-object as item()) as base64Binary", "description" : "

    Returns a torrent file for a given object using the specified S3 credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the specified credentials. If no default\n bucket is present in the specified credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the specified credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\"\n }\n return s3:object-torrent($object)\n 
    \n

    \n", "summary" : "

    Returns a torrent file for a given object using the specified S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object to retrieve the torrent file for
    " } ], "returns" : { "type" : "base64Binary", "description" : "the base64 encoded torrent file of the specified object." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "read-binary-nondeterministic", "qname" : "s3:read-binary-nondeterministic", "signature" : "($s3-object as item()) as base64Binary", "description" : "

    Retrieves the binary content of an S3 object using the default S3 credentials.\n The object content is forced to be interpreted as binaryand will be returned\n as a base64Binary item.

    \n

    This function has the same semantics as\n read-binary#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves the binary content of an S3 object using the default S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve.
    " } ], "returns" : { "type" : "base64Binary", "description" : "the object or object version binary content." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 2, "name" : "read-binary-nondeterministic", "qname" : "s3:read-binary-nondeterministic", "signature" : "($credentials as item()?, $s3-object as item()) as base64Binary", "description" : "

    Retrieves the binary content of an S3 object using the specified S3 credentials.\n The object content is forced to be interpreted as binaryand will be returned\n as a base64Binary item.

    \n

    This function has the same semantics as\n read-binary#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves the binary content of an S3 object using the specified S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve.
    " } ], "returns" : { "type" : "base64Binary", "description" : "the object or object version binary content." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 1, "name" : "read-binary", "qname" : "s3:read-binary", "signature" : "($s3-object as item()) as base64Binary", "description" : "

    Retrieves the binary content of an S3 object using the default S3 credentials.\n The object content is forced to be interpreted as binaryand will be returned\n as a base64Binary item.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the default credentials. If no default\n bucket is present in the default credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the default credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the latest version of\n the object will be returned. If specified, only that particular version of\n the object will be returned.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\"\n }\n return s3:read-binary($object)\n 
    \n

    \n", "summary" : "

    Retrieves the binary content of an S3 object using the default S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve.
    " } ], "returns" : { "type" : "base64Binary", "description" : "the object or object version binary content." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 2, "name" : "read-binary", "qname" : "s3:read-binary", "signature" : "($credentials as item()?, $s3-object as item()) as base64Binary", "description" : "

    Retrieves the binary content of an S3 object using the specified S3 credentials.\n The object content is forced to be interpreted as binaryand will be returned\n as a base64Binary item.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the specified credentials. If no default\n bucket is present in the specified credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the specified credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the latest version of\n the object will be returned. If specified, only that particular version of\n the object will be returned.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\"\n }\n return s3:read-binary(\"credentials\", $object)\n 
    \n

    \n", "summary" : "

    Retrieves the binary content of an S3 object using the specified S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve.
    " } ], "returns" : { "type" : "base64Binary", "description" : "the object or object version binary content." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 1, "name" : "read-object-nondeterministic", "qname" : "s3:read-object-nondeterministic", "signature" : "($s3-object as item()) as object()", "description" : "

    Retrieves an S3 object using the default S3 credentials.

    \n

    This function has the same semantics as\n read-object#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves an S3 object using the default S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve.
    " } ], "returns" : { "type" : "object()", "description" : "the specified object." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "read-object-nondeterministic", "qname" : "s3:read-object-nondeterministic", "signature" : "($credentials as item()?, $s3-object as item()) as object()", "description" : "

    Retrieves an S3 object using the specified S3 credentials.

    \n

    This function has the same semantics as\n read-object#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves an S3 object using the specified S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve.
    " } ], "returns" : { "type" : "object()", "description" : "the specified object." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "read-object", "qname" : "s3:read-object", "signature" : "($s3-object as item()) as object()", "description" : "

    Retrieves an S3 object using the default S3 credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the default credentials. If no default\n bucket is present in the default credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the default credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the latest version of\n the object will be returned. If specified, only that particular version of\n the object will be returned.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\"\n }\n return s3:read-object($object)\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"key\": \"test.xml\",\n   \"bucket\": \"28msec\",\n   \"metadata\":\n   {\n     \"author\": \"28msec\"\n   },\n   \"missing-metadata\" : 1,\n   \"version\": \"3GL4kqtJlcpXroDTDm3vjVBH40Nr8X8g\",\n   \"expiration\": \"expiry-date=\\\"Fri, 21 Dec 2012 00:00:00 GMT\\\", rule-id=\\\"Rule for testfile.txt\\\"\"\n   \"restore\": \"x-amz-restore: ongoing-request=\\\"false\\\", expiry-date=\\\"Wed, 07 Nov 2012 00:00:00 GMT\\\"\"\n   \"serverSideEncryption\": \"AES256\",\n   \"lastModified\": \"Mon, 15 Oct 2012 21:58:07 GMT\",\n   \"eTag\": \"1accb31fcf202eba0c0f41fa2f09b4d7\",\n   \"mediaType\": \"text/plain\"\n   \"length\": \"28\",\n   \"content: \"1234567890123456789012345678\"\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, mandatory).
    • \n
    • metadata: an object specifying additional metadata. Each metadata is a\n name-value pair and is represented as different fields (object, optional).
    • \n
    • missing-metadata: the number of metadata entries that were not returned\n in the metadata object. This can happen if you create metadata using an API\n like SOAP that supports more flexible metadata than the REST API. (integer,\n optional).
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the permissions for the\n latest version of the object will be returned. If specified, only the\n permissions for that particular version of the object will be returned.
    • \n
    • expiration: if the object expiration is configured (see\n PUT Bucket lifecycle),\n this field is present. It includes the expiry-date and rule-id key value\n pairs providing object expiration information. The value of rule-id is URL\n encoded.(string, optional).
    • \n
    • restore: if the object is an archived object (an object whose storage\n class is Glacier), the response includes this header if either the archive\n restoration is in progress (see\n POST Object restore),\n or an archive copy is already restored.(string, optional).
    • \n
    • serverSideEncryption: If the object is stored by using server-side\n encryption, the response includes this header with a value of the encryption\n algorithm that was used.(string, optional).
    • \n
    • lastModified: the date in which the object was last modified (dateTime,\n optional).
    • \n
    • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. For objects created by the PUT Object operation\n and the POST Object operation, the eTag is a quoted, 32-digit hexadecimal\n string representing the MD5 digest of the object data. For other objects,\n the eTag may or may not be an MD5 digest of the object data. If the eTag is\n not an MD5 digest of the object data, it will contain one or more non-hexadecimal\n characters and/or will consist of less than 32 or more than 32 hexadecimal\n digits.(string, optional).
    • \n
    • mediaType: the object media-type (string, mandatory).
    • \n
    • length: the object content length (integer, optional).
    • \n
    • content: the object content. (item, optional). The type of this field\n is determined by the media-type returned by the server. If the media-type\n indicates that the body content is textual, then the content has type string,\n base64Binary otherwise. Specifically, the body content is considered textual\n if and only if the MIME-type specified in the media-type is one of:\n
        \n
      • \"application/json\"
      • \n
      • \"application/x-javascript\"
      • \n
      • \"application/xml\"
      • \n
      • \"application/xml-external-parsed-entity\"
      • \n
      \n or if the MIME-type starts with \"text/\" or ends with \"+xml\".
    • \n
    \n

    \n", "summary" : "

    Retrieves an S3 object using the default S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve.
    " } ], "returns" : { "type" : "object()", "description" : "the specified object." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "read-object", "qname" : "s3:read-object", "signature" : "($credentials as item()?, $s3-object as item()) as object()", "description" : "

    Retrieves an S3 object using the specified S3 credentials.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the specified credentials. If no default\n bucket is present in the specified credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the specified credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the latest version of\n the object will be returned. If specified, only that particular version of\n the object will be returned.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\"\n }\n return s3:read-object($object)\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"key\": \"test.xml\",\n   \"bucket\": \"28msec\",\n   \"metadata\":\n   {\n     \"author\": \"28msec\"\n   },\n   \"missing-metadata\" : 1,\n   \"version\": \"3GL4kqtJlcpXroDTDm3vjVBH40Nr8X8g\",\n   \"expiration\": \"expiry-date=\\\"Fri, 21 Dec 2012 00:00:00 GMT\\\", rule-id=\\\"Rule for testfile.txt\\\"\"\n   \"restore\": \"x-amz-restore: ongoing-request=\\\"false\\\", expiry-date=\\\"Wed, 07 Nov 2012 00:00:00 GMT\\\"\"\n   \"serverSideEncryption\": \"AES256\",\n   \"lastModified\": \"Mon, 15 Oct 2012 21:58:07 GMT\",\n   \"eTag\": \"1accb31fcf202eba0c0f41fa2f09b4d7\",\n   \"mediaType\": \"text/plain\"\n   \"length\": \"28\",\n   \"content: \"1234567890123456789012345678\"\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, mandatory).
    • \n
    • metadata: an object specifying additional metadata. Each metadata is a\n name-value pair and is represented as different fields (object, optional).
    • \n
    • missing-metadata: the number of metadata entries that were not returned\n in the metadata object. This can happen if you create metadata using an API\n like SOAP that supports more flexible metadata than the REST API. (integer,\n optional).
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the permissions for the\n latest version of the object will be returned. If specified, only the\n permissions for that particular version of the object will be returned.
    • \n
    • expiration: if the object expiration is configured (see\n PUT Bucket lifecycle),\n this field is present. It includes the expiry-date and rule-id key value\n pairs providing object expiration information. The value of rule-id is URL\n encoded.(string, optional).
    • \n
    • restore: if the object is an archived object (an object whose storage\n class is Glacier), the response includes this header if either the archive\n restoration is in progress (see\n POST Object restore),\n or an archive copy is already restored.(string, optional).
    • \n
    • serverSideEncryption: If the object is stored by using server-side\n encryption, the response includes this header with a value of the encryption\n algorithm that was used.(string, optional).
    • \n
    • lastModified: the date in which the object was last modified (dateTime,\n optional).
    • \n
    • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. For objects created by the PUT Object operation\n and the POST Object operation, the eTag is a quoted, 32-digit hexadecimal\n string representing the MD5 digest of the object data. For other objects,\n the eTag may or may not be an MD5 digest of the object data. If the eTag is\n not an MD5 digest of the object data, it will contain one or more non-hexadecimal\n characters and/or will consist of less than 32 or more than 32 hexadecimal\n digits.(string, optional).
    • \n
    • mediaType: the object media-type (string, mandatory).
    • \n
    • length: the object content length (integer, optional).
    • \n
    • content: the object content. (item, optional). The type of this field\n is determined by the media-type returned by the server. If the media-type\n indicates that the body content is textual,then the content has type string,\n base64Binary otherwise. Specifically, the body content is considered textual\n if and only if the MIME-type specified in the media-type is one of:\n
        \n
      • \"application/json\"
      • \n
      • \"application/x-javascript\"
      • \n
      • \"application/xml\"
      • \n
      • \"application/xml-external-parsed-entity\"
      • \n
      \n or if the MIME-type starts with \"text/\" or ends with \"+xml\".
    • \n
    \n

    \n", "summary" : "

    Retrieves an S3 object using the specified S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve.
    " } ], "returns" : { "type" : "object()", "description" : "the specified object." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "read-text-nondeterministic", "qname" : "s3:read-text-nondeterministic", "signature" : "($s3-object as item()) as string", "description" : "

    Retrieves the textual content of an S3 object using the default S3 credentials.\n The object content is forced to be interpreted as textual, with a UTF-8 charset\n and will be returned as string.

    \n

    This function has the same semantics as\n read-text#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves the textual content of an S3 object using the default S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve.
    " } ], "returns" : { "type" : "string", "description" : "the object or object version textual content." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "read-text-nondeterministic", "qname" : "s3:read-text-nondeterministic", "signature" : "($credentials as item()?, $s3-object as item()) as string", "description" : "

    Retrieves the textual content of an S3 object using the specified S3 credentials.\n The object content is forced to be interpreted as textual, with a UTF-8 charset\n and will be returned as string.

    \n

    This function has the same semantics as\n read-text#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves the textual content of an S3 object using the specified S3 credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve.
    " } ], "returns" : { "type" : "string", "description" : "the object or object version textual content." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "read-text", "qname" : "s3:read-text", "signature" : "($s3-object as item()) as string", "description" : "

    Retrieves the textual content of an S3 object using the default S3 credentials.\n The object content is forced to be interpreted as textual, with a UTF-8 charset\n and will be returned as string.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the default credentials. If no default\n bucket is present in the default credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the default credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the latest version of\n the object will be returned. If specified, only that particular version of\n the object will be returned.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\"\n }\n return s3:read-text(\"credentials\", $object)\n 
    \n

    \n", "summary" : "

    Retrieves the textual content of an S3 object using the default S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve.
    " } ], "returns" : { "type" : "string", "description" : "the object or object version textual content." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "read-text", "qname" : "s3:read-text", "signature" : "($credentials as item()?, $s3-object as item()) as string", "description" : "

    Retrieves the textual content of an S3 object using the specified S3 credentials.\n The object content is forced to be interpreted as textual, with a UTF-8 charset\n and will be returned as string.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the specified credentials. If no default\n bucket is present in the specified credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the specified credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the latest version of\n the object will be returned. If specified, only that particular version of\n the object will be returned.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\"\n }\n return s3:read-text(\"credentials\", $object)\n 
    \n

    \n", "summary" : "

    Retrieves the textual content of an S3 object using the specified S3 credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version to retrieve.
    " } ], "returns" : { "type" : "string", "description" : "the object or object version textual content." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request", "s3:RESPONSE the response received from S3 cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "set-object-permissions", "qname" : "s3:set-object-permissions", "signature" : "($s3-object as item()) as empty-sequence()", "description" : "

    Sets the access control list (ACL) of an S3 object using the default S3\n credentials.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the default credentials. If no default\n bucket is present in the default credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the default credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the permissions for the\n latest version of the object will be set. If specified, only the\n permissions for that particular version of the object will be set.
    • \n
    • permission: the permission to set (string, optional). It must be one of\n \"private\", \"public-read\", \"public-read-write\", \"authenticated-read\",\n \"bucket-owner-read\", \"bucket-owner-full-control\". For your convenience the\n following variables can be used: $s3:ACL-GRANT-PRIVATE,\n $s3:ACL-GRANT-PUBLIC-READ, $s3:ACL-GRANT-PUBLIC-READ-WRITE,\n $s3:ACL-GRANT-AUTHENTICATED-READ, $s3:ACL-GRANT-BUCKET-OWNER-READ,\n $s3:ACL-GRANT-BUCKET-OWNER-FULL-CONTROL. If this field is not\n specified, the \"private\" ACL is used, that is, the owner gets FULL_CONTROL,\n and no one else has access rights.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\",\n   \"permission\": $s3:ACL-GRANT-PUBLIC-READ\n }\n return s3:set-object-permissions($object)\n 
    \n

    \n", "summary" : "

    Sets the access control list (ACL) of an S3 object using the default S3\n credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version and ACL to set.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty sequence" }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 2, "name" : "set-object-permissions", "qname" : "s3:set-object-permissions", "signature" : "($credentials as item()?, $s3-object as item()) as empty-sequence()", "description" : "

    Sets the access control list (ACL) of an S3 object using the specified S3\n credentials.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used. If a string is specified, it is interpreted as\n key for an object in the default bucket of the specified credentials. If no default\n bucket is present in the specified credentials, the s3:BUCKET error\n is raised. If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the specified credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • version: the object version (string, optional). If versioning is enabled\n for the specified object and no version is specified the permissions for the\n latest version of the object will be set. If specified, only the\n permissions for that particular version of the object will be set.
    • \n
    • permission: the permission to set (string, optional). It must be one of\n \"private\", \"public-read\", \"public-read-write\", \"authenticated-read\",\n \"bucket-owner-read\", \"bucket-owner-full-control\". For your convenience the\n following variables can be used: $s3:ACL-GRANT-PRIVATE,\n $s3:ACL-GRANT-PUBLIC-READ, $s3:ACL-GRANT-PUBLIC-READ-WRITE,\n $s3:ACL-GRANT-AUTHENTICATED-READ, $s3:ACL-GRANT-BUCKET-OWNER-READ,\n $s3:ACL-GRANT-BUCKET-OWNER-FULL-CONTROL. If this field is not\n specified, the \"private\" ACL is used, that is, the owner gets FULL_CONTROL,\n and no one else has access rights.
    • \n
    \n

    \n

    Example:\n

    \n let $object :=\n {\n   \"key\": \"object\",\n   \"bucket\": \"28msec\",\n   \"version\": \"3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo\",\n   \"permission\": $s3:ACL-GRANT-PUBLIC-READ\n }\n return s3:set-object-permissions($object)\n 
    \n

    \n", "summary" : "

    Sets the access control list (ACL) of an S3 object using the specified S3\n credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object or object version and ACL to set.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty sequence" }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 2, "name" : "write-binary", "qname" : "s3:write-binary", "signature" : "($object as item(), $binary-content as base64Binary) as object()", "description" : "

    Writes a binary object in an S3 bucket using the default S3 credentials.\n If the object already exists it is overwritten.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used.

    \n

    If a string is specified, it is interpreted as\n key for an object in the default bucket of the default credentials. If no default\n bucket is present in the default credentials, the s3:BUCKET error\n is raised. The object media-type will be set to \"binary/octet-stream\", no metadata will\n be set for the object, the object will be stored on standard redundancy storage,\n and the object permission will be set to \"private\", that is, the owner gets\n FULL_CONTROL, and no one else has access rights.

    \n

    If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the default credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • mediaType: the media-type of the object (string, optional). If not specified,\n \"binary/octet-stream\" is used.
    • \n
    • metadata: an object specifying additional metadata. Each metadata is a\n name-value pair and is represented as different fields (object, optional).
    • \n
    • permission: the permission to set (string, optional). It must be one of\n \"private\", \"public-read\", \"public-read-write\", \"authenticated-read\",\n \"bucket-owner-read\", \"bucket-owner-full-control\". For your convenience the\n following variables can be used: $s3:ACL-GRANT-PRIVATE,\n $s3:ACL-GRANT-PUBLIC-READ, $s3:ACL-GRANT-PUBLIC-READ-WRITE,\n $s3:ACL-GRANT-AUTHENTICATED-READ, $s3:ACL-GRANT-BUCKET-OWNER-READ,\n $s3:ACL-GRANT-BUCKET-OWNER-FULL-CONTROL. If this field is not\n specified, the \"private\" ACL is used, that is, the owner gets FULL_CONTROL,\n and no one else has access rights.
    • \n
    • reducedRedundancy: whether to use reduced-redundancy or not (bool,\n optional). Default is false.
    • \n
    \n

    \n

    Example:\n

    \n variable $s3-object :=\n {\n   \"key\": \"test.xml\",\n   \"bucket\": \"28msec\",\n   \"permission\": $const:ACL-GRANT-PUBLIC-READ,\n   \"metadata\": { \"author\": \"28msec\" },\n   \"mediaType\": \"application/octet-stream\"\n }\n s3:write-binary($s3-object, base64Binary(\"Mjhtc2Vj\"))\n 
    \n Example Result:\n
    \n {\n   \"expiration\": \"expiry-date=\\\"Fri, 23 Dec 2012 00:00:00 GMT\\\", rule-id=\\\"1\\\"\",\n   \"version\": \"3GL4kqtJlcpXroDTDm3vjVBH40Nr8X8g\",\n   \"eTag\": \"\\\"1b2cf535f27731c974343645a3985328\\\"\"\n }\n 
    \n

    \n

    The meaning of the fields in the result object is the following:\n

      \n
    • expiration: if the object expiration is configured, the response\n includes this header. It includes the expiry-date and rule-id key-value\n pairs providing object expiration information. The value of the rule-id is\n URL encoded. (string, optional)
    • \n
    • version: the version of the object. When you enable versioning,\n Amazon S3 generates a random number for objects added to a bucket. The value\n is UTF-8 encoded and URL ready. When you PUT an object in a bucket where\n versioning has been suspended, the version ID is always null. (string, optional)
    • \n
    • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. The eTag returned by this method is a quoted,\n 32-digit hexadecimal string representing the MD5 digest of the object data.\n For other objects, the eTag may or may not be an MD5 digest of the object data.\n (string, optional).
    • \n
    \n

    \n", "summary" : "

    Writes a binary object in an S3 bucket using the default S3 credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "object", "type" : "item()", "occurrence" : null, "description" : "" }, { "name" : "binary-content", "type" : "base64Binary", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "object()", "description" : "the S3 operation result." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 3, "name" : "write-binary", "qname" : "s3:write-binary", "signature" : "($credentials as item()?, $object as item(), $binary-content as base64Binary) as object()", "description" : "

    Writes a binary object in an S3 bucket using the specified S3 credentials.\n If the object already exists it is overwritten.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used.

    \n

    If a string is specified, it is interpreted as\n key for an object in the default bucket of the specified credentials. If no default\n bucket is present in the specified credentials, the s3:BUCKET error\n is raised. The object media-type will be set to \"binary/octet-stream\", no metadata will\n be set for the object, the object will be stored on standard redundancy storage,\n and the object permission will be set to \"private\", that is, the owner gets\n FULL_CONTROL, and no one else has access rights.

    \n

    If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the specified credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • mediaType: the media-type of the object (string, optional). If not specified,\n \"binary/octet-stream\" is used.
    • \n
    • metadata: an object specifying additional metadata. Each metadata is a\n name-value pair and is represented as different fields (object, optional).
    • \n
    • permission: the permission to set (string, optional). It must be one of\n \"private\", \"public-read\", \"public-read-write\", \"authenticated-read\",\n \"bucket-owner-read\", \"bucket-owner-full-control\". For your convenience the\n following variables can be used: $s3:ACL-GRANT-PRIVATE,\n $s3:ACL-GRANT-PUBLIC-READ, $s3:ACL-GRANT-PUBLIC-READ-WRITE,\n $s3:ACL-GRANT-AUTHENTICATED-READ, $s3:ACL-GRANT-BUCKET-OWNER-READ,\n $s3:ACL-GRANT-BUCKET-OWNER-FULL-CONTROL. If this field is not\n specified, the \"private\" ACL is used, that is, the owner gets FULL_CONTROL,\n and no one else has access rights.
    • \n
    • reducedRedundancy: whether to use reduced-redundancy or not (bool,\n optional). Default is false.
    • \n
    \n

    \n

    Example:\n

    \n variable $s3-object :=\n {\n   \"key\": \"test.xml\",\n   \"bucket\": \"28msec\",\n   \"permission\": $const:ACL-GRANT-PUBLIC-READ,\n   \"metadata\": { \"author\": \"28msec\" },\n   \"mediaType\": \"application/octet-stream\"\n }\n s3:write-binary(\"credentials\", $s3-object, base64Binary(\"Mjhtc2Vj\"))\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"expiration\": \"expiry-date=\\\"Fri, 23 Dec 2012 00:00:00 GMT\\\", rule-id=\\\"1\\\"\",\n   \"version\": \"3GL4kqtJlcpXroDTDm3vjVBH40Nr8X8g\",\n   \"eTag\": \"\\\"1b2cf535f27731c974343645a3985328\\\"\"\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • expiration: if the object expiration is configured, the response\n includes this header. It includes the expiry-date and rule-id key-value\n pairs providing object expiration information. The value of the rule-id is\n URL encoded. (string, optional)
    • \n
    • version: the version of the object. When you enable versioning,\n Amazon S3 generates a random number for objects added to a bucket. The value\n is UTF-8 encoded and URL ready. When you PUT an object in a bucket where\n versioning has been suspended, the version ID is always null. (string, optional)
    • \n
    • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. The eTag returned by this method is a quoted,\n 32-digit hexadecimal string representing the MD5 digest of the object data.\n For other objects, the eTag may or may not be an MD5 digest of the object data.\n (string, optional).
    • \n
    \n

    \n", "summary" : "

    Writes a binary object in an S3 bucket using the specified S3 credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "object", "type" : "item()", "occurrence" : null, "description" : "" }, { "name" : "binary-content", "type" : "base64Binary", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "object()", "description" : "the S3 operation result." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 1, "name" : "write-object", "qname" : "s3:write-object", "signature" : "($s3-object as item()) as object()", "description" : "

    Writes an object in an S3 bucket using the default S3 credentials.\n If the object already exists it is overwritten.

    \n

    The object to write and its contents are specified through the $s3-object\n parameter, which must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the default credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • content: the object content. It must either be a string or a base64Binary\n atomic. (item, mandatory).
    • \n
    • mediaType: the media-type of the object (string, optional). If not specified,\n \"text/plain\" is used if the content field is of type string, \"binary/octet-stream\"\n if it is of type base64Binary.
    • \n
    • metadata: an object specifying additional metadata. Each metadata is a\n name-value pair and is represented as different fields (object, optional).
    • \n
    • permission: the permission to set (string, optional). It must be one of\n \"private\", \"public-read\", \"public-read-write\", \"authenticated-read\",\n \"bucket-owner-read\", \"bucket-owner-full-control\". For your convenience the\n following variables can be used: $s3:ACL-GRANT-PRIVATE,\n $s3:ACL-GRANT-PUBLIC-READ, $s3:ACL-GRANT-PUBLIC-READ-WRITE,\n $s3:ACL-GRANT-AUTHENTICATED-READ, $s3:ACL-GRANT-BUCKET-OWNER-READ,\n $s3:ACL-GRANT-BUCKET-OWNER-FULL-CONTROL. If this field is not\n specified, the \"private\" ACL is used, that is, the owner gets FULL_CONTROL,\n and no one else has access rights.
    • \n
    • reducedRedundancy: whether to use reduced-redundancy or not (bool,\n optional). Default is false.
    • \n
    \n

    \n

    Example:\n

    \n variable $s3-object :=\n {\n   \"key\": \"test.xml\",\n   \"bucket\": \"28msec\",\n   \"permission\": $const:ACL-GRANT-PUBLIC-READ,\n   \"metadata\": { \"author\": \"28msec\" },\n   \"content\": serialize({ \"Hello\": \"World\" }),\n   \"mediaType\": \"application/xml\"\n }\n s3:write-object($s3-object)\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"expiration\": \"expiry-date=\\\"Fri, 23 Dec 2012 00:00:00 GMT\\\", rule-id=\\\"1\\\"\",\n   \"version\": \"3GL4kqtJlcpXroDTDm3vjVBH40Nr8X8g\",\n   \"eTag\": \"\\\"1b2cf535f27731c974343645a3985328\\\"\"\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • expiration: if the object expiration is configured, the response\n includes this header. It includes the expiry-date and rule-id key-value\n pairs providing object expiration information. The value of the rule-id is\n URL encoded. (string, optional)
    • \n
    • version: the version of the object. When you enable versioning,\n Amazon S3 generates a random number for objects added to a bucket. The value\n is UTF-8 encoded and URL ready. When you PUT an object in a bucket where\n versioning has been suspended, the version ID is always null. (string, optional)
    • \n
    • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. The eTag returned by this method is a quoted,\n 32-digit hexadecimal string representing the MD5 digest of the object data.\n For other objects, the eTag may or may not be an MD5 digest of the object data.\n (string, optional).
    • \n
    \n

    \n", "summary" : "

    Writes an object in an S3 bucket using the default S3 credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "s3-object", "type" : "item()", "occurrence" : null, "description" : "
    The S3 object to write.
    " } ], "returns" : { "type" : "object()", "description" : "the S3 operation result." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 2, "name" : "write-object", "qname" : "s3:write-object", "signature" : "($credentials as item()?, $s3-object as object()) as object()", "description" : "

    Writes an object in an S3 bucket using the specified credentials.\n If the object already exists it is overwritten.

    \n

    The object to write and its contents are specified through the $s3-object\n parameter, which must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the specified credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • content: the object content. It must either be a string or a base64Binary\n atomic. (item, mandatory).
    • \n
    • mediaType: the media-type of the object (string, optional). If not specified,\n \"text/plain\" is used if the content field is of type string, \"binary/octet-stream\"\n if it is of type base64Binary.
    • \n
    • metadata: an object specifying additional metadata. Each metadata is a\n name-value pair and is represented as different fields (object, optional).
    • \n
    • permission: the permission to set (string, optional). It must be one of\n \"private\", \"public-read\", \"public-read-write\", \"authenticated-read\",\n \"bucket-owner-read\", \"bucket-owner-full-control\". For your convenience the\n following variables can be used: $s3:ACL-GRANT-PRIVATE,\n $s3:ACL-GRANT-PUBLIC-READ, $s3:ACL-GRANT-PUBLIC-READ-WRITE,\n $s3:ACL-GRANT-AUTHENTICATED-READ, $s3:ACL-GRANT-BUCKET-OWNER-READ,\n $s3:ACL-GRANT-BUCKET-OWNER-FULL-CONTROL. If this field is not\n specified, the \"private\" ACL is used, that is, the owner gets FULL_CONTROL,\n and no one else has access rights.
    • \n
    • reducedRedundancy: whether to use reduced-redundancy or not (bool,\n optional). Default is false.
    • \n
    \n

    \n

    Example:\n

    \n variable $s3-object :=\n {\n   \"key\": \"test.xml\",\n   \"bucket\": \"28msec\",\n   \"permission\": $const:ACL-GRANT-PUBLIC-READ,\n   \"metadata\": { \"author\": \"28msec\" },\n   \"content\": serialize({ \"Hello\": \"World\" }),\n   \"mediaType\": \"application/xml\"\n }\n s3:write-object(\"s3\", $s3-object)\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"expiration\": \"expiry-date=\\\"Fri, 23 Dec 2012 00:00:00 GMT\\\", rule-id=\\\"1\\\"\",\n   \"version\": \"3GL4kqtJlcpXroDTDm3vjVBH40Nr8X8g\",\n   \"eTag\": \"\\\"1b2cf535f27731c974343645a3985328\\\"\"\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • expiration: if the object expiration is configured, the response\n includes this header. It includes the expiry-date and rule-id key-value\n pairs providing object expiration information. The value of the rule-id is\n URL encoded. (string, optional)
    • \n
    • version: the version of the object. When you enable versioning,\n Amazon S3 generates a random number for objects added to a bucket. The value\n is UTF-8 encoded and URL ready. When you PUT an object in a bucket where\n versioning has been suspended, the version ID is always null. (string, optional)
    • \n
    • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. The eTag returned by this method is a quoted,\n 32-digit hexadecimal string representing the MD5 digest of the object data.\n For other objects, the eTag may or may not be an MD5 digest of the object data.\n (string, optional).
    • \n
    \n

    \n", "summary" : "

    Writes an object in an S3 bucket using the specified credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "s3-object", "type" : "object()", "occurrence" : null, "description" : "
    The S3 object to write.
    " } ], "returns" : { "type" : "object()", "description" : "the S3 operation result." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 2, "name" : "write-text", "qname" : "s3:write-text", "signature" : "($object as item(), $text-content as string) as object()", "description" : "

    Writes a textual object in an S3 bucket using the default S3 credentials.\n If the object already exists it is overwritten.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used.

    \n

    If a string is specified, it is interpreted as\n key for an object in the default bucket of the default credentials. If no default\n bucket is present in the default credentials, the s3:BUCKET error\n is raised. The object media-type will be set to \"text/plain\", no metadata will\n be set for the object, the object will be stored on standard redundancy storage,\n and the object permission will be set to \"private\", that is, the owner gets\n FULL_CONTROL, and no one else has access rights.

    \n

    If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the default credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • mediaType: the media-type of the object (string, optional). If not specified,\n \"text/plain\" is used.
    • \n
    • metadata: an object specifying additional metadata. Each metadata is a\n name-value pair and is represented as different fields (object, optional).
    • \n
    • permission: the permission to set (string, optional). It must be one of\n \"private\", \"public-read\", \"public-read-write\", \"authenticated-read\",\n \"bucket-owner-read\", \"bucket-owner-full-control\". For your convenience the\n following variables can be used: $s3:ACL-GRANT-PRIVATE,\n $s3:ACL-GRANT-PUBLIC-READ, $s3:ACL-GRANT-PUBLIC-READ-WRITE,\n $s3:ACL-GRANT-AUTHENTICATED-READ, $s3:ACL-GRANT-BUCKET-OWNER-READ,\n $s3:ACL-GRANT-BUCKET-OWNER-FULL-CONTROL. If this field is not\n specified, the \"private\" ACL is used, that is, the owner gets FULL_CONTROL,\n and no one else has access rights.
    • \n
    • reducedRedundancy: whether to use reduced-redundancy or not (bool,\n optional). Default is false.
    • \n
    \n

    \n

    Example:\n

    \n variable $s3-object :=\n {\n   \"key\": \"test.xml\",\n   \"bucket\": \"28msec\",\n   \"permission\": $const:ACL-GRANT-PUBLIC-READ,\n   \"metadata\": { \"author\": \"28msec\" },\n   \"mediaType\": \"text/xml\"\n }\n s3:write-text($s3-object, serialize(<a/>))\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"expiration\": \"expiry-date=\\\"Fri, 23 Dec 2012 00:00:00 GMT\\\", rule-id=\\\"1\\\"\",\n   \"version\": \"3GL4kqtJlcpXroDTDm3vjVBH40Nr8X8g\",\n   \"eTag\": \"\\\"1b2cf535f27731c974343645a3985328\\\"\"\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • expiration: if the object expiration is configured, the response\n includes this header. It includes the expiry-date and rule-id key-value\n pairs providing object expiration information. The value of the rule-id is\n URL encoded. (string, optional)
    • \n
    • version: the version of the object. When you enable versioning,\n Amazon S3 generates a random number for objects added to a bucket. The value\n is UTF-8 encoded and URL ready. When you PUT an object in a bucket where\n versioning has been suspended, the version ID is always null. (string, optional)
    • \n
    • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. The eTag returned by this method is a quoted,\n 32-digit hexadecimal string representing the MD5 digest of the object data.\n For other objects, the eTag may or may not be an MD5 digest of the object data.\n (string, optional).
    • \n
    \n

    \n", "summary" : "

    Writes a textual object in an S3 bucket using the default S3 credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "object", "type" : "item()", "occurrence" : null, "description" : "" }, { "name" : "text-content", "type" : "string", "occurrence" : null, "description" : "
    The textual object content.
    " } ], "returns" : { "type" : "object()", "description" : "the S3 operation result." }, "errors" : [ "s3:CREDENTIALS if the default S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] }, { "isDocumented" : true, "arity" : 3, "name" : "write-text", "qname" : "s3:write-text", "signature" : "($credentials as item()?, $object as item(), $text-content as string) as object()", "description" : "

    Writes a text object in an S3 bucket using the specified S3 credentials.\n If the object already exists it is overwritten.

    \n

    The S3 object is specified through the $s3-object parameter. Either a string\n or a JSON object can be used.

    \n

    If a string is specified, it is interpreted as\n key for an object in the default bucket of the specified credentials. If no default\n bucket is present in the specified credentials, the s3:BUCKET error\n is raised. The object media-type will be set to \"text/plain\", no metadata will\n be set for the object, the object will be stored on standard redundancy storage,\n and the object permission will be set to \"private\", that is, the owner gets\n FULL_CONTROL, and no one else has access rights.

    \n

    If a JSON object is used, it must have the following structure:\n

      \n
    • key: the object key (string, mandatory).
    • \n
    • bucket: the bucket name (string, optional). If this field is not present\n and the specified credentials do not have a default bucket, the\n s3:BUCKET error is raised.
    • \n
    • mediaType: the media-type of the object (string, optional). If not specified,\n \"text/plain\" is used.
    • \n
    • metadata: an object specifying additional metadata. Each metadata is a\n name-value pair and is represented as different fields (object, optional).
    • \n
    • permission: the permission to set (string, optional). It must be one of\n \"private\", \"public-read\", \"public-read-write\", \"authenticated-read\",\n \"bucket-owner-read\", \"bucket-owner-full-control\". For your convenience the\n following variables can be used: $s3:ACL-GRANT-PRIVATE,\n $s3:ACL-GRANT-PUBLIC-READ, $s3:ACL-GRANT-PUBLIC-READ-WRITE,\n $s3:ACL-GRANT-AUTHENTICATED-READ, $s3:ACL-GRANT-BUCKET-OWNER-READ,\n $s3:ACL-GRANT-BUCKET-OWNER-FULL-CONTROL. If this field is not\n specified, the \"private\" ACL is used, that is, the owner gets FULL_CONTROL,\n and no one else has access rights.
    • \n
    • reducedRedundancy: whether to use reduced-redundancy or not (bool,\n optional). Default is false.
    • \n
    \n

    \n

    Example:\n

    \n variable $s3-object :=\n {\n   \"key\": \"test.xml\",\n   \"bucket\": \"28msec\",\n   \"permission\": $const:ACL-GRANT-PUBLIC-READ,\n   \"metadata\": { \"author\": \"28msec\" },\n   \"mediaType\": \"text/xml\"\n }\n s3:write-text(\"credentials\", $s3-object, serialize(<a/>))\n 
    \n

    \n

    Example return object:\n

    \n {\n   \"expiration\": \"expiry-date=\\\"Fri, 23 Dec 2012 00:00:00 GMT\\\", rule-id=\\\"1\\\"\",\n   \"version\": \"3GL4kqtJlcpXroDTDm3vjVBH40Nr8X8g\",\n   \"eTag\": \"\\\"1b2cf535f27731c974343645a3985328\\\"\"\n }\n 
    \n

    \n

    The fields in the returned object have the following meanings:\n

      \n
    • expiration: if the object expiration is configured, the response\n includes this header. It includes the expiry-date and rule-id key-value\n pairs providing object expiration information. The value of the rule-id is\n URL encoded. (string, optional)
    • \n
    • version: the version of the object. When you enable versioning,\n Amazon S3 generates a random number for objects added to a bucket. The value\n is UTF-8 encoded and URL ready. When you PUT an object in a bucket where\n versioning has been suspended, the version ID is always null. (string, optional)
    • \n
    • eTag: the entity tag is a hash of the object. The eTag only reflects\n changes to the contents of an object, not its metadata. The eTag is determined\n when an object is created. The eTag returned by this method is a quoted,\n 32-digit hexadecimal string representing the MD5 digest of the object data.\n For other objects, the eTag may or may not be an MD5 digest of the object data.\n (string, optional).
    • \n
    \n

    \n", "summary" : "

    Writes a text object in an S3 bucket using the specified S3 credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : "?", "description" : "
    The credentials to use.
    " }, { "name" : "object", "type" : "item()", "occurrence" : null, "description" : "" }, { "name" : "text-content", "type" : "string", "occurrence" : null, "description" : "
    The textual object content.
    " } ], "returns" : { "type" : "object()", "description" : "the S3 operation result." }, "errors" : [ "s3:CREDENTIALS if the specified S3 credentials cannot be found or are invalid", "s3:OBJECT if the object specification is invalid", "s3:BUCKET if no bucket has been specified and no default bucket is present in the used credentials", "s3:HTTP an HTTP error occurred sending the request to S3", "s3:REQUEST S3 refused to execute the request" ] } ], "variables" : [ { "name" : "s3:ACL-GRANT-PRIVATE", "type" : "item()*", "description" : " The private canned ACL. It is applicable to buckets and objects.\n Owner gets FULL_CONTROL. No one else has access rights.\n" }, { "name" : "s3:ACL-GRANT-PUBLIC-READ", "type" : "item()*", "description" : " The public-read canned ACL. Applicable to buckets and objects.\n Owner gets FULL_CONTROL. The AllUsers group gets READ access.\n" }, { "name" : "s3:ACL-GRANT-PUBLIC-READ-WRITE", "type" : "item()*", "description" : " The public-read-write canned ACL. Applicable to buckets and objects.\n Owner gets FULL_CONTROL. The AllUsers group gets READ and WRITE access.\n Granting this on a bucket is generally not recommended.\n" }, { "name" : "s3:ACL-GRANT-AUTHENTICATED-READ", "type" : "item()*", "description" : " The autenticated-read canned ACL. Applicable to buckets and objects.\n Owner gets FULL_CONTROL. The AuthenticatedUsers group gets READ access.\n" }, { "name" : "s3:ACL-GRANT-BUCKET-OWNER-READ", "type" : "item()*", "description" : " The grant-bucket-owner-read canned ACL. Applicable to objects.\n Object owner gets FULL_CONTROL. Bucket owner gets READ access.\n If you specify this canned ACL when creating a bucket, Amazon S3 ignores it.\n" }, { "name" : "s3:ACL-GRANT-BUCKET-OWNER-FULL-CONTROL", "type" : "item()*", "description" : " The grant-bucket-owner-full-control canned ACL. Applicable to objects.\n Both the object owner and the bucket owner get FULL_CONTROL over the object.\n If you specify this canned ACL when creating a bucket, Amazon S3 ignores it.\n" } ] }, "http://api.28.io/authorization" : { "ns" : "http://api.28.io/authorization", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://api.28.io/authorization", "prefix" : "authorization" }, { "uri" : "http://zorba.io/modules/base64", "prefix" : "base64" }, { "uri" : "http://zorba.io/modules/hmac", "prefix" : "hmac" }, { "uri" : "http://expath.org/ns/http-client", "prefix" : "http-client" }, { "uri" : "http://www.28msec.com/modules/project", "prefix" : "project" }, { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "req" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "res" } ], "functions" : [ { "isDocumented" : false, "arity" : 0, "name" : "authorized", "qname" : "authorization:authorized", "signature" : "() as xs:boolean", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "html-do-login", "qname" : "authorization:html-do-login", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "html-show-login", "qname" : "authorization:html-show-login", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/store/static/integrity-constraints/dml" : { "ns" : "http://zorba.io/modules/store/static/integrity-constraints/dml", "description" : " This module defines a function to check if an integrity constraint is\n satisfied.\n The integrity constraint needs to be declared in the prolog of a module.\n

    \n This module is part of\n Zorba's XQuery Data Definition Facility.\n All the integrity constraints managed by this module have to be pre-declared\n in the prolog of a module.\n Please refer to the\n general documentation\n for more information and examples.\n", "sees" : [ "Data Lifecycle", "XQuery Data Definition Facility", "http://zorba.io/modules/store/static/integrity-constraints/dml", "http://zorba.io/modules/store/static/collections/dml", "http://zorba.io/modules/store/static/collections/ddl", "http://zorba.io/modules/store/static/indexes/ddl", "http://zorba.io/modules/store/static/indexes/dml", "http://zorba.io/errors" ], "authors" : [ "Nicolae Brinza, Matthias Brantner, David Graf, Till Westmann, Markos Zaharioudakis" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/store/static/integrity-constraints/dml", "prefix" : "icdml" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "check-integrity-constraint", "qname" : "icdml:check-integrity-constraint", "signature" : "($name as xs:QName) as xs:boolean external", "description" : " Checks if the specified constraints are valid in the database.\n", "summary" : "

    Checks if the specified constraints are valid in the database.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the integrity constraint to check.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the constraints are valid; false otherwise." }, "errors" : [ "zerr:ZDDY0031 if the integrity constraint is not declared.", "zerr:ZDDY0032 if the integrity constraint is not available." ] } ], "variables" : [ ] }, "http://zorba.io/modules/excel/statistical" : { "ns" : "http://zorba.io/modules/excel/statistical", "description" : " This is a library module offering a part of the set of statistical functions\n defined by Microsoft Excel 2003.\n", "sees" : [ "Excel 2003 Documentation: Statistical Functions" ], "authors" : [ "Daniel Turcanu" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/excel/statistical", "prefix" : "excel" }, { "uri" : "http://zorba.io/modules/excel/errors", "prefix" : "excel-err" }, { "uri" : "http://zorba.io/modules/excel/math", "prefix" : "excel-math" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "avedev", "qname" : "excel:avedev", "signature" : "($numbers as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " Returns the average of the absolute deviations of data points from their mean.\n The formula is sum(abs(x - average_x))/n, where n is the count of x in the sequence.\n", "summary" : "

    Returns the average of the absolute deviations of data points from their mean.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of numbers or values castable to numeric. Sequence can be of any length from 1 up.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The formula result" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "average", "qname" : "excel:average", "signature" : "($numbers as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Returns the average (arithmetic mean) of the arguments.\n Arguments can be empty values, otherwise must be castable to numeric.\n If sequence is empty then zero is returned.\n The sequence can be of any length.\n", "summary" : "

    Returns the average (arithmetic mean) of the arguments.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The sequence of numbers or empty values.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The sum of all numbers divided by the number of non-empty values." }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 1, "name" : "averagea", "qname" : "excel:averagea", "signature" : "($numbers as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " Calculates the average (arithmetic mean) of the values in the sequence of arguments.\n Arguments can be of any type.\n The numbers are added, and the sum is divided by the size of entire sequence.\n", "summary" : "

    Calculates the average (arithmetic mean) of the values in the sequence of arguments.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of values of any type. The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The result" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "count", "qname" : "excel:count", "signature" : "($numbers as xs:anyAtomicType*) as xs:integer", "description" : " Counts the number of cells that contain numbers or values castable to numeric.\n", "summary" : "

    Counts the number of cells that contain numbers or values castable to numeric.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The sequence of values, of any length.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The count of numbers." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "counta", "qname" : "excel:counta", "signature" : "($numbers as xs:anyAtomicType*) as xs:integer", "description" : " Counts the number of values that are not empty.\n Empty values are the one with string value \"\".\n", "summary" : "

    Counts the number of values that are not empty.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of values of any type, any length
    " } ], "returns" : { "type" : "xs:integer", "description" : "The count of non-empty values" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "countblank", "qname" : "excel:countblank", "signature" : "($cells as xs:anyAtomicType*) as xs:integer", "description" : " Counts the empty values in a sequence.\n The empty values are the ones with string value \"\".\n The value 0 is not counted.\n", "summary" : "

    Counts the empty values in a sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "cells", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of values, of any length
    " } ], "returns" : { "type" : "xs:integer", "description" : "The count" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "large", "qname" : "excel:large", "signature" : "($numbers as xs:anyAtomicType*, $k as xs:integer) as xs:anyAtomicType", "description" : " Returns the k-th largest value in a data set.\n If n is the number of data points in a range,\n then LARGE(array,1) returns the largest value,\n and LARGE(array,n) returns the smallest value.\n", "summary" : "

    Returns the k-th largest value in a data set.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of numbers or values castable to numeric. The sequence can be of any length, from 1 up.
    " }, { "name" : "k", "type" : "xs:integer", "occurrence" : null, "description" : "
    the position of largest value, with value from 1 to count of values
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The k-th largest value as numeric type" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type", "excel-err:Num if the sequence is empty", "excel-err:Num if k is not a value between 1 and the sequence size" ] }, { "isDocumented" : true, "arity" : 1, "name" : "max", "qname" : "excel:max", "signature" : "($numbers as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Returns the largest number in a sequence.\n", "summary" : "

    Returns the largest number in a sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of numbers or values castable to numeric. The sequence can be of any length.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The max" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "maxa", "qname" : "excel:maxa", "signature" : "($numbers as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Returns the largest value in a list of arguments.\n In this implementation there is no difference between MAX and MAXA.\n", "summary" : "

    Returns the largest value in a list of arguments.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of numbers or values castable to numeric The sequence can be of any length.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The max" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "median", "qname" : "excel:median", "signature" : "($numbers as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Returns the median of the given numbers.\n The median is the number in the middle of a set of numbers.\n Half the numbers have values that are greater than the median,\n and half the numbers have values that are less than the median.\n", "summary" : "

    Returns the median of the given numbers.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of numbers, of any length
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "for odd count of numbers return the number in the middle of the sorted sequence. For even count of numbers return the average of the two numbers in the middle." }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "min", "qname" : "excel:min", "signature" : "($numbers as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Returns the smallest number in a sequence.\n", "summary" : "

    Returns the smallest number in a sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of numbers or values castable to numeric. The sequence can be of any length.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The min" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "mina", "qname" : "excel:mina", "signature" : "($numbers as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Returns the smallest value in a list of arguments.\n In this implementation there is no difference between MAX and MAXA.\n", "summary" : "

    Returns the smallest value in a list of arguments.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of numbers or values castable to numeric The sequence can be of any length.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The min" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "mode", "qname" : "excel:mode", "signature" : "($numbers as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Returns the most frequently occurring, or repetitive, value in a sequence.\n Arguments must be castable to numeric.\n", "summary" : "

    Returns the most frequently occurring, or repetitive, value in a sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of numbers, of any length
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The most occuring number" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type", "fn:QName(\"http://zorba.io/modules/excel/errors\", \"excel-err:NA\") if there are no duplicate numbers" ] }, { "isDocumented" : true, "arity" : 2, "name" : "percentile", "qname" : "excel:percentile", "signature" : "($numbers as xs:anyAtomicType*, $k_at as xs:anyAtomicType) as xs:anyAtomicType", "description" : " Returns the k-th percentile of values in a sequence.\n If k is not a multiple of 1/(n - 1),\n PERCENTILE interpolates to determine the value at the k-th percentile.\n The function is computed by (max-min)*k + min\n", "summary" : "

    Returns the k-th percentile of values in a sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of numbers, of any length
    " }, { "name" : "k_at", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the percentile, with value between 0 .. 1 inclusive
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The computed percentile" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type", "excel-err:Num if percentile is not between 0 .. 1" ] }, { "isDocumented" : true, "arity" : 2, "name" : "percentrank", "qname" : "excel:percentrank", "signature" : "($numbers as xs:anyAtomicType*, $x as xs:anyAtomicType) as xs:decimal", "description" : " Returns the rank of a value in a data set as a percentage of the data set.\n If x does not match one of the values in array,\n PERCENTRANK interpolates to return the correct percentage rank.

    \n The formula is uses: (RANK - 1) / (size - 1) .\n", "summary" : "

    Returns the rank of a value in a data set as a percentage of the data set.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of numbers or values castable to numbers. The sequence can be of any length, from 1 up.
    " }, { "name" : "x", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the value for which you want to know the rank
    " } ], "returns" : { "type" : "xs:decimal", "description" : "The percentage of rank." }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type", "excel-err:Num if the sequence is zero length" ] }, { "isDocumented" : true, "arity" : 3, "name" : "prob", "qname" : "excel:prob", "signature" : "($x_range as xs:anyAtomicType+, $prob_range as xs:anyAtomicType+, $range_lower_limit as xs:anyAtomicType) as xs:anyAtomicType", "description" : " This is the same as above, only that upper_limit is not specified.\n The probability is computed only for range_lower_limit.\n", "summary" : "

    This is the same as above, only that upper_limit is not specified.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x_range", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    is the range of numeric values of x with which there are associated probabilities. This does not need to be ordered.
    " }, { "name" : "prob_range", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    is a set of probabilities associated with values in x_range.
    " }, { "name" : "range_lower_limit", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the value for which you want a probability.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The probability of the range_lower_limit value" }, "errors" : [ "excel-err:Num if any probability is not between 0 and 1", "excel-err:Num if the sum of probabilities is not equal to 1", "excel-err:Value if any parameter is not castable to numeric", "excel-err:Num if x_range and prob_range do not have the same number of values" ] }, { "isDocumented" : true, "arity" : 4, "name" : "prob", "qname" : "excel:prob", "signature" : "($x_range as xs:anyAtomicType+, $prob_range as xs:anyAtomicType+, $range_lower_limit as xs:anyAtomicType, $upper_limit as xs:anyAtomicType) as xs:anyAtomicType", "description" : " Returns the probability that values in a range are between two limits.\n", "summary" : "

    Returns the probability that values in a range are between two limits.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x_range", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    is the range of numeric values of x with which there are associated probabilities. This does not need to be ordered.
    " }, { "name" : "prob_range", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    is a set of probabilities associated with values in x_range.
    " }, { "name" : "range_lower_limit", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the lower bound on the value for which you want a probability.
    " }, { "name" : "upper_limit", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the upper bound on the value for which you want a probability.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The probability of the entire range" }, "errors" : [ "excel-err:Num if any probability is not between 0 and 1", "excel-err:Num if the sum of probabilities is not equal to 1", "excel-err:Value if any parameter is not castable to numeric", "excel-err:Num if x_range and prob_range do not have the same number of values" ] }, { "isDocumented" : true, "arity" : 2, "name" : "quartile", "qname" : "excel:quartile", "signature" : "($numbers as xs:anyAtomicType*, $quart as xs:integer) as xs:anyAtomicType", "description" : " Returns the quartile of a data set.\n", "summary" : "

    Returns the quartile of a data set.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    sequence of numbers or values castable to numbers. The sequence can be of any length, from 1 up.
    " }, { "name" : "quart", "type" : "xs:integer", "occurrence" : null, "description" : "
    one of the values 0, 1, 2, 3, 4 with meaning:
    0
    compute minimum value
    1
    compute first quartile (25th percentile)
    2
    compute median value (50th percentile)
    3
    compute third quartile (75th percentile)
    4
    compute maximum value
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the computed quartile, as numeric type" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type", "excel-err:Num if the sequence is zero length", "excel-err:Num if $quart is not one of the values 0, 1, 2, 3, 4" ] }, { "isDocumented" : true, "arity" : 2, "name" : "rank", "qname" : "excel:rank", "signature" : "($x as xs:anyAtomicType, $numbers as xs:anyAtomicType*) as xs:decimal", "description" : " This RANK function is same as the above, only that $order_ascending is set by default to false.\n", "summary" : "

    This RANK function is same as the above, only that $order_ascending is set by default to false.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The number whose rank you want to find.
    " }, { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of numbers or values castable to numbers. The sequence can be of any length.
    " } ], "returns" : { "type" : "xs:decimal", "description" : "The rank of $x." }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 3, "name" : "rank", "qname" : "excel:rank", "signature" : "($x as xs:anyAtomicType, $numbers as xs:anyAtomicType*, $order_ascending as xs:boolean) as xs:decimal", "description" : " Returns the rank of a number in a list of numbers.\n The rank of a number is its size relative to other values in a list.\n (If you were to sort the list, the rank of the number would be its position.)\n RANK gives duplicate numbers the same rank.\n", "summary" : "

    Returns the rank of a number in a list of numbers.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The number whose rank you want to find.
    " }, { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The sequence of numbers or values castable to numbers. The sequence can be of any length.
    " }, { "name" : "order_ascending", "type" : "xs:boolean", "occurrence" : null, "description" : "
    A boolean having the meaning:
    false
    then rank the number as if the sequence was sorted in descending order.
    true
    then rank the number as if the sequence was sorted in ascending order.
    " } ], "returns" : { "type" : "xs:decimal", "description" : "The rank of $x." }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 2, "name" : "slope", "qname" : "excel:slope", "signature" : "($known_y as xs:anyAtomicType+, $known_x as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " Returns the slope of the linear regression line through data points in known_y's and known_x's.\n The slope is the vertical distance divided by the horizontal distance between\n any two points on the line, which is the rate of change along the regression line.\n It computes the formula:

    \n sum((x - average_x)(y - average_y)) / sum((x - average_x)^2)

    \n where average_x and average_y are computed with AVERAGE function.\n", "summary" : "

    Returns the slope of the linear regression line through data points in known_y's and known_x's.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "known_y", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of y numbers. The sequence can be of any length, from 1 up.
    " }, { "name" : "known_x", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of x numbers. The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The slope value, as numeric type" }, "errors" : [ "excel-err:Value if any parameter cannot be casted to numeric", "fn:QName(\"http://zorba.io/modules/excel/errors\", \"excel-err:NA\") if there are different numbers of x's and y's", "fn:QName(\"http://zorba.io/modules/excel/errors\", \"excel-err:NA\") if any sequence is empty", "excel-err:Div0 if all x's are equal" ] }, { "isDocumented" : true, "arity" : 2, "name" : "small", "qname" : "excel:small", "signature" : "($numbers as xs:anyAtomicType*, $k as xs:integer) as xs:anyAtomicType", "description" : " This function computes the k-th smallest value in a data set.\n Use this function to return values with a particular relative standing in a data set.\n If n is the number of data points in array, SMALL(array,1) equals the smallest value,\n and SMALL(array,n) equals the largest value.\n", "summary" : "

    This function computes the k-th smallest value in a data set.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    A sequence of numbers or values castable to numeric. The sequence can be of any length, from 1 up.
    " }, { "name" : "k", "type" : "xs:integer", "occurrence" : null, "description" : "
    The position (from the smallest) in the sequence of data to return. Must have value between 1 and size of sequence.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The k-th smallest value of $numbers." }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type.", "excel-err:Num if the sequence is zero length.", "excel-err:Num if $k is not a value between 1 and the size of sequence." ] }, { "isDocumented" : true, "arity" : 3, "name" : "standardize", "qname" : "excel:standardize", "signature" : "($x as xs:anyAtomicType, $mean as xs:anyAtomicType, $standard_dev as xs:anyAtomicType) as xs:double", "description" : " Returns a normalized value from a distribution characterized by mean and standard_dev.

    \n The formula is (x - mean) / standard_dev .\n", "summary" : "

    Returns a normalized value from a distribution characterized by mean and standard_dev.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the value you want to normalize
    " }, { "name" : "mean", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the arithmetic mean of the distribution.
    " }, { "name" : "standard_dev", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the standard deviation of the distribution.
    " } ], "returns" : { "type" : "xs:double", "description" : "The normalized x, as numeric type" }, "errors" : [ "excel-err:Value if any parameter cannot be casted to numeric", "excel-err:Num if standard_dev is a value smaller than zero or equal" ] }, { "isDocumented" : true, "arity" : 1, "name" : "var", "qname" : "excel:var", "signature" : "($numbers as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " Estimates variance based on a sample.

    \n The formula is sum(x - average_x)^2 / (n - 1).

    \n average_x is computed with AVERAGE function.

    \n n is the count of numbers from the sequence, excluding empty values.\n", "summary" : "

    Estimates variance based on a sample.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of numbers or values castable to numeric. The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The variance, as numeric type" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "vara", "qname" : "excel:vara", "signature" : "($numbers as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " Estimates variance based on a sample.

    \n The formula is sum(x - average_x)^2 / (n - 1).

    \n average_x is computed with AVERAGE function.

    \n n is the size of sequence, including empty values.

    \n", "summary" : "

    Estimates variance based on a sample.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of numbers or values castable to numeric. The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The variance, as numeric type" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "varp", "qname" : "excel:varp", "signature" : "($numbers as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " Calculates variance based on the entire population.

    \n The formula is sum(x - average_x)^2 / n.

    \n average_x is computed with AVERAGE function.

    \n n is the count of numbers from the sequence, excluding empty values.

    \n", "summary" : "

    Calculates variance based on the entire population.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of numbers or values castable to numeric. The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The variance, as numeric type" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "varpa", "qname" : "excel:varpa", "signature" : "($numbers as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " Calculates variance based on the entire population.

    \n The formula is sum(x - average_x)^2 / n.

    \n average_x is computed with AVERAGE function.

    \n n is the size of sequence, including empty values.

    \n", "summary" : "

    Calculates variance based on the entire population.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of numbers or values castable to numeric. The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The variance, as numeric type" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/languages/xslt" : { "ns" : "http://www.zorba-xquery.com/modules/languages/xslt", "description" : " This module provides XSLT 1.0 transformation functionality.\n

    For details on XSLT see\n XSLT 1.0 specification.

    \n

    This module implements the invoking of an XSLT transformation from XQuery\n described in \n Michael Kay's proposal.

    \n

    Example:\n

    import module namespace\n        xslt = \"http://www.zorba-xquery.com/modules/languages/xslt\";\n let $source :=\n     <catalog>\n         <cd>\n           <title>Empire Burlesque</title>\n           <artist>Bob Dylan</artist>\n           <country>USA</country>\n           <company>Columbia</company>\n           <price>10.90</price>\n           <year>1985</year>\n         </cd>\n         <cd>\n           <title>Hide your heart</title>\n           <artist>Bonnie Tyler</artist>\n           <country>UK</country>\n           <company>CBS Records</company>\n           <price>9.90</price>\n           <year>1988</year>\n         </cd>\n     </catalog>\n let $stylesheet :=\n   <xsl:stylesheet version=\"1.0\"\n       xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n     <xsl:template match=\"/\">\n       <html>\n       <body>\n       <h2>Music Collection&lt;/h2>\n         <table border=\"1\">\n           <tr bgcolor=\"lightblue\">\n             <th>Title&lt;/th>\n             <th>Artist&lt;/th>\n           </tr>\n           <xsl:for-each select=\"catalog/cd\">\n            <tr>\n              <td>&lt;xsl:value-of select=\"title\"/></td>\n              <td>&lt;xsl:value-of select=\"artist\"/></td>\n           </tr>\n           </xsl:for-each>\n         </table>\n       </body>\n       </html>\n     </xsl:template>\n   </xsl:stylesheet>\n return\n   xslt:transform( $source, $stylesheet)

    \n", "sees" : [ ], "authors" : [ "Cezar Andrei" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://www.zorba-xquery.com/modules/languages/xslt", "prefix" : "xslt" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "transform", "qname" : "xslt:transform", "signature" : "($source as node(), $stylesheet as node()) as node() external", "description" : "

    Invokes an XSLT transformation.

    \n", "summary" : "

    Invokes an XSLT transformation.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "source", "type" : "node()", "occurrence" : null, "description" : "
    the input document to the transformation
    " }, { "name" : "stylesheet", "type" : "node()", "occurrence" : null, "description" : "
    the XSLT stylesheet module
    " } ], "returns" : { "type" : "node()", "description" : "the result tree produced by the transformation" }, "errors" : [ "xslt:XSLT001 if $stylesheet is not a valid XSLT stylesheet", "xslt:XSLT002 if result can not be imported" ] } ], "variables" : [ ] }, "http://zorba.io/modules/data-cleaning/phonetic-string-similarity" : { "ns" : "http://zorba.io/modules/data-cleaning/phonetic-string-similarity", "description" : "

    This library module provides phonetic string similarity functions, comparing strings with basis on how they sound.

    \n

    \n

    These metrics are particularly effective in matching names, since names are often spelled in different\n ways that sound the same.

    \n

    \n

    The logic contained in this module is not specific to any particular XQuery implementation.

    \n", "sees" : [ ], "authors" : [ "Bruno Martins" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/data-cleaning/phonetic-string-similarity", "prefix" : "simp" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "metaphone-key", "qname" : "simp:metaphone-key", "signature" : "($s1 as xs:string) as xs:string", "description" : "

    Returns the Metaphone key for a given string.

    \n

    The Metaphone algorithm produces variable length keys as its output, as opposed to Soundex's fixed-length keys.

    \n

    \n

    Example usage :

    metaphone-key(\"ALEKSANDER\")

    \n

    \n

    The function invocation in the example above returns :

    \"ALKSNTR\"

    \n", "summary" : "

    Returns the Metaphone key for a given string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The string.
    " } ], "returns" : { "type" : "xs:string", "description" : "The Metaphone key for the given input string." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "metaphone", "qname" : "simp:metaphone", "signature" : "($s1 as xs:string, $s2 as xs:string) as xs:boolean", "description" : "

    Checks if two strings have the same Metaphone key.

    \n

    \n

    Example usage :

    metaphone(\"ALEKSANDER\", \"ALEXANDRE\")

    \n

    \n

    The function invocation in the example above returns :

    true

    \n", "summary" : "

    Checks if two strings have the same Metaphone key.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "Returns true if both strings have the same Metaphone key and false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "soundex-key", "qname" : "simp:soundex-key", "signature" : "($s1 as xs:string) as xs:string", "description" : "

    Returns the Soundex key for a given string.

    \n

    \n

    Example usage :

    soundex-key(\"Robert\")

    \n

    \n

    The function invocation in the example above returns :

    \"R163\"

    \n", "summary" : "

    Returns the Soundex key for a given string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The string.
    " } ], "returns" : { "type" : "xs:string", "description" : "The Soundex key for the given input string." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "soundex", "qname" : "simp:soundex", "signature" : "($s1 as xs:string, $s2 as xs:string) as xs:boolean", "description" : "

    Checks if two strings have the same Soundex key.

    \n

    \n

    Example usage :

    soundex( \"Robert\" , \"Rupert\" )

    \n

    \n

    The function invocation in the example above returns :

    true

    \n", "summary" : "

    Checks if two strings have the same Soundex key.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "Returns true if both strings have the same Soundex key and false otherwise." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/collections" : { "ns" : "http://www.28msec.com/modules/collections", "description" : " This module provides functions to work with collections. For example,\n it contains functions to retrieve the content of a collection or the\n names of all collections.\n

    The module is always imported so you don't need to import it explicitly.\n Also, you don't need to fully qualify a function to invoke it.

    \n", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "apply-insert", "qname" : "db:apply-insert", "signature" : "($name as string, $content as item()*) as item()* external", "description" : " This function does the same as the insert function and it immediately applies\n the resulting pending updates and returns the items that have been inserted.\n Note that each item in the content sequence is copied before insertion. This\n function provides an efficient way to retrieve the actual copies that have\n been inserted.\n", "summary" : "

    This function does the same as the insert function and it immediately applies\n the resulting pending updates and returns the items that have been inserted.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The name of the collection to which the items should be added.
    " }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequences of items whose copies should be added to the collection.
    " } ], "returns" : { "type" : "item()*", "description" : "The result of the function is the sequence of items that have been inserted into the collection." }, "errors" : [ "zerr:ZDDY0003 if the collection identified by $name does not exist.", "zerr:ZDTY0001 if any of the items in the $content do not match the expected type (as specified in the collection declaration) or are not XML documents, XML elements, JSON objects, or JSON arrays." ] }, { "isDocumented" : true, "arity" : 0, "name" : "available-collections", "qname" : "db:available-collections", "signature" : "() as string* external", "description" : " Return the names of all existing collections.\n", "summary" : "

    Return the names of all existing collections.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "string*", "description" : "The names of all existing collections." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "collection-name", "qname" : "db:collection-name", "signature" : "($o as item()) as string external", "description" : " The collection-name function returns the name of the containing collection\n of the given item.\n", "summary" : "

    The collection-name function returns the name of the containing collection\n of the given item.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "o", "type" : "item()", "occurrence" : null, "description" : "
    The item for which to get the name of the collection.
    " } ], "returns" : { "type" : "string", "description" : "The name of the containing collection." }, "errors" : [ "zerr:ZDDY0011 if the given item does not belong to a collection." ] }, { "isDocumented" : true, "arity" : 1, "name" : "collection", "qname" : "db:collection", "signature" : "($name as string) as item()* external", "description" : " The collection function returns the sequence of items that belong\n to the collection identified by the given name.\n Please note that the order of the items returned is not deterministic,\n i.e. it might change between invocations. You can use\n db:collection($name, 0) to get a deterministic order.\n", "summary" : "

    The collection function returns the sequence of items that belong\n to the collection identified by the given name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The name of the collection.
    " } ], "returns" : { "type" : "item()*", "description" : "The content of the collection." }, "errors" : [ "zerr:ZDDY0003 if the collection identified by $name does not exist." ] }, { "isDocumented" : true, "arity" : 2, "name" : "collection", "qname" : "db:collection", "signature" : "($name as string, $skip as integer) as item()* external", "description" : " The collection function returns the sequence of items that belong to\n the collection identified\n by the given name. The skip parameter allows to (efficiently) skip\n a given number of items.\n Note that the collections are generally unordered. However, there\n is an implicit deterministic ordering (i.e. sorting by the _id field\n in MongoDB) that is used by this function. This ordering is not present\n for the db:collection#1 function. In order to return items with\n a stable ordering, db:collection($name, 0) can be used.\n", "summary" : "

    The collection function returns the sequence of items that belong to\n the collection identified\n by the given name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The name of the collection.
    " }, { "name" : "skip", "type" : "integer", "occurrence" : null, "description" : "
    The number of items to skip starting from the beginning.
    " } ], "returns" : { "type" : "item()*", "description" : "The content of the collection starting at the $skip+1 item." }, "errors" : [ "zerr:ZDDY0003 if the collection identified by $name does not exist" ] }, { "isDocumented" : true, "arity" : 3, "name" : "collection", "qname" : "db:collection", "signature" : "($name as string, $start as string, $skip as integer) as item()* external", "description" : " The collection function returns the sequence of items that belong to\n the collection identified\n by the given name. The start parameter is a reference and determines\n the first item to return. The skip parameter allows to (efficiently) skip\n a given number of items starting at the item referenced by $start.\n The start parameter is useful for efficiently implementing pagination.\n Note that the collections are generally unordered. However, there\n is an implicit deterministic ordering (i.e. sorting by the _id field\n in MongoDB) that is used by this function. This ordering is not present\n for the db:collection#1 function. In order to return items with\n a stable ordering, db:collection($name, $start, 0) can be used.\n Example:\n
    \n import module namespace ref = \"http://zorba.io/modules/reference\";\n let $ref := ref:reference(db:collection(\"test\", 1)[1])\n return\n   db:collection(\"test\", $ref, 1)\n 
    \n", "summary" : "

    The collection function returns the sequence of items that belong to\n the collection identified\n by the given name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The name of the collection.
    " }, { "name" : "start", "type" : "string", "occurrence" : null, "description" : "
    The reference to the first item to return.
    " }, { "name" : "skip", "type" : "integer", "occurrence" : null, "description" : "
    The number of collection items to skip.
    " } ], "returns" : { "type" : "item()*", "description" : "The content of the collection starting at the item referenced by $start and skipping $skip items." }, "errors" : [ "zerr:ZDDY0003 if the collection identified by $name does not exist.", "zerr:ZAPI0028 If the given reference $start is not a valid reference.", "zerr:ZSTR0066 if the given reference $start does not reference an item of this collection." ] }, { "isDocumented" : true, "arity" : 1, "name" : "create", "qname" : "db:create", "signature" : "($name as string) external", "description" : " The create function is an updating function that creates\n a new collection with the given name.\n It is not possible to create collections that start with\n \"system.\" or \"_28\" (zerr:ZDDY1000).\n Collections are identified by a name (string). Names are not allowed to\n contain the $ sign or exceed the length of 70 characters.\n This is consistent with the restrictions for names of collections in MongoDB.\n", "summary" : "

    The create function is an updating function that creates\n a new collection with the given name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The name of the collection to create.
    " } ], "returns" : { "type" : null, "description" : "The result of the function is an empty XDM instance and a pending update list which, once applied, creates a collection with the given name." }, "errors" : [ "zerr:ZDDY0002 if a collection with the given name already exists.", "zerr:ZDDY1000 if the given name is not a legal collection name" ] }, { "isDocumented" : true, "arity" : 2, "name" : "create", "qname" : "db:create", "signature" : "($name as string, $content as item()*) external", "description" : " The create function is an updating function which creates\n a new collection with the given name. Moreover, it adds copies\n of the sequence $content to the new collection.\n It is not possible to create collections that start with\n \"system.\" or \"_28\" (zerr:ZDDY1000).\n Collections are identified by a name (string). Names are not allowed to\n contain the $ sign or exceed the length of 70 characters.\n This is consistent with the restrictions for names of collections in MongoDB.\n", "summary" : "

    The create function is an updating function which creates\n a new collection with the given name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The string of the collection to create.
    " }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequences of items that should be added to the new collection.
    " } ], "returns" : { "type" : null, "description" : "The result of the function is an empty XDM instance and a pending update list which, once applied, creates a collection with the given name and inserts the given items into it." }, "errors" : [ "zerr:ZDDY0002 if a collection with the given name already exists.", "zerr:ZDTY0001 if any of the items in the $content do not match the expected type (as specified in the collection declaration) or are not XML documents, XML elements, JSON objects, or JSON arrays.", "zerr:ZDDY1000 if the given name is not a legal collection name" ] }, { "isDocumented" : true, "arity" : 1, "name" : "delete", "qname" : "db:delete", "signature" : "($target as item()*) external", "description" : " The delete function is an updating function that deletes zero or more items\n (JSON objects, JSON arrays, or XML nodes) from a collection.\n Please note that the all of the items belong to the same collection\n (zerr:ZDDY0011).\n", "summary" : "

    The delete function is an updating function that deletes zero or more items\n (JSON objects, JSON arrays, or XML nodes) from a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "target", "type" : "item()", "occurrence" : "*", "description" : "
    the items that should be deleted from the containing collection.
    " } ], "returns" : { "type" : null, "description" : "The result of this function is an empty XDM instance and a pending update list which, once applied, deletes the items from the collections." }, "errors" : [ "zerr:ZDDY0003 if the collection identified by $name does not exist.", "zerr:ZDDY0011 if any item in the $target sequence is not a member of a collection or not all items belong to the same collection." ] }, { "isDocumented" : false, "arity" : 1, "name" : "drop", "qname" : "db:drop", "signature" : "($name as string) external", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "edit", "qname" : "db:edit", "signature" : "($target as item(), $content as item()) external", "description" : " The edit function is an updating function that edits the first supplied\n item so as to make it look exactly like a copy of the second supplied item,\n while retaining its original identity.\n", "summary" : "

    The edit function is an updating function that edits the first supplied\n item so as to make it look exactly like a copy of the second supplied item,\n while retaining its original identity.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "target", "type" : "item()", "occurrence" : null, "description" : "
    The target item, that must be edited.
    " }, { "name" : "content", "type" : "item()", "occurrence" : null, "description" : "
    The content item, that serves as an edit goal.
    " } ], "returns" : { "type" : null, "description" : "The result of the function is an empty XDM instance and a pending update list which, once applied, performs the edit." }, "errors" : [ "zerr:ZDDY0017 if the $target item is not a member of a collection.", "zerr:ZDDY0040 if the target cannot be updated to match the content (for example because the target is a node and the content is an object).", "zerr:ZDTY0001 if $content does not match the expected type (as specified in the collection declaration) according to the rules for SequenceType Matching." ] }, { "isDocumented" : false, "arity" : 1, "name" : "index-keys", "qname" : "db:index-keys", "signature" : "($index-name as string) as array()* external", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "index-name", "type" : "string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "array()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "insert", "qname" : "db:insert", "signature" : "($name as string, $content as item()*) external", "description" : " The insert function is an updating function that inserts copies of the given\n items into a collection.\n", "summary" : "

    The insert function is an updating function that inserts copies of the given\n items into a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The name of the collection to which the items should be added.
    " }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequences of items whose copies should be added.
    " } ], "returns" : { "type" : null, "description" : "The result of the function is an empty XDM instance and a pending update list which, once applied, inserts the items into the collection." }, "errors" : [ "zerr:ZDDY0003 if the collection identified by $name does not exist.", "zerr:ZDTY0001 if any of the items in the $content do not match the expected type (as specified in the collection declaration) or are not XML documents, XML elements, JSON objects, or JSON arrays." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-available-collection", "qname" : "db:is-available-collection", "signature" : "($name as string) as boolean external", "description" : " Determine if the collection with the given name exists.\n", "summary" : "

    Determine if the collection with the given name exists.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The string of the collection in question.
    " } ], "returns" : { "type" : "boolean", "description" : "true if collection with the given name exists, false otherwise." }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "lookup", "qname" : "db:lookup", "signature" : "($index-name as string, $key as item()) as item()* external", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "index-name", "type" : "string", "occurrence" : null, "description" : "" }, { "name" : "key", "type" : "item()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "lookup", "qname" : "db:lookup", "signature" : "($index-name as string, $keys as item(), $skip as integer) as item()* external", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "index-name", "type" : "string", "occurrence" : null, "description" : "" }, { "name" : "keys", "type" : "item()", "occurrence" : null, "description" : "" }, { "name" : "skip", "type" : "integer", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "refresh", "qname" : "db:refresh", "signature" : "($index-name as string) external", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "index-name", "type" : "string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "truncate", "qname" : "db:truncate", "signature" : "($name as string) external", "description" : " The truncate function is an updating function that deletes the\n entire content of a given collection.\n Please note that applying this function can not be undone in case\n an error happens during the application of the containing PUL.\n", "summary" : "

    The truncate function is an updating function that deletes the\n entire content of a given collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The name of the collection whose content to delete.
    " } ], "returns" : { "type" : null, "description" : "The result of this function is an empty XDM instance and a pending update list which, once applied, deletes the nodes." }, "errors" : [ "zerr:ZDDY0003 if the collection identified by $name does not exist." ] } ], "variables" : [ ] }, "http://expath.org/ns/http-client" : { "ns" : "http://expath.org/ns/http-client", "description" : "

    \n This module provides an implementation of the\n EXPath Http Client.\n It provides functions for making HTTP requests and is a superset of the\n module specified by EXPath.\n Specifically, it implements the http:send-request() functions\n as specified by EXPath. Moreover, it adds an additional function\n http:read() (with several arities for the sake of ease).\n

    \n

    \n In general, both functions take a description of the HTTP request to make\n as parameter, execute the request, and return a representation of the HTTP\n response. For instance, in the following code snippet, we fetch the Zorba\n home page:\n

    \n
    import module namespace http = \"http://expath.org/ns/http-client\";\n http:send-request(\n  <http:request href=\"http://zorba.io\" method=\"get\" />\n )\n 
    \n

    \n The http:send-request() functions are declared as sequential.\n Sequential functions are allowed to have side effects. For example, most probably,\n an HTTP POST request is a request that has side effects because it adds/changes\n a remote resource. Sequential functions are specified in the\n XQuery Scripting Extension.\n In contrast, the http:read() functions are not declared as sequential -\n they are declared as being non deterministic though, which\n means that several calls may return different results.\n HTTP requests performed using these functions are not allowed to have\n side effects.\n

    \n

    \n The response is returned as a sequence of one or more items. The first\n one is an http:response element with quite the same\n structure as an http:request, but without the content itself.\n The content is returned as the second item (or several items in case of\n a multipart response) as a string, a document node, or a binary item.\n This depends on the content-type returned.\n Specifically, the rules are as follows:\n

      \n
    • A document node is returned if the media type has a MIME type of\n text/xml, application/xml, text/xml-external-parsed-entity, or\n application/xml-external-parsed-entity, as defined in [RFC 3023]\n (except that application/xml-dtd is considered a text media type).\n MIME types ending by +xml are also XML media types.
    • \n
    • A document node is returned if the media type has a MIME type of\n text/html. In order to be able to make HTML parseable, tidy is automatically\n invoked. If you want to prevent that, you can also set your own content-type\n by setting the override-media-type attribute in the request element.\n For tidying, the following options\n will be used:\n
        \n
      • TidyXmlOut=yes
      • \n
      • TidyDoctypeMode=TidyDoctypeOmit
      • \n
      • TidyQuoteNbsp=yes
      • \n
      • TidyCharEncoding=\"utf8\"
      • \n
      • TidyNewline=\"LF\"
      • \n
      \n
    • \n
    • An xs:string item is returned if the media type has a text MIME type,\n i.e. beginning with text/.
    • \n
    • An xs:base64Binary item is returned for all the other media types.
    • \n
    \n

    \n

    \n The structure of a request element is defined in the schema that is imported\n by this module. The details are described in the\n specification.\n Analogously, the response element is also described in this\n specification.\n

    \n", "sees" : [ "XQuery 3.0: Function Declaration" ], "authors" : [ "Federico Cavalieri, Markus Pilman" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://expath.org/ns/error", "prefix" : "err" }, { "uri" : "http://expath.org/ns/http-client", "prefix" : "http" }, { "uri" : "http://zorba.io/modules/http-client-wrapper", "prefix" : "http-wrapper" }, { "uri" : "http://expath.org/ns/http-client", "prefix" : "https" }, { "uri" : "http://www.zorba-xquery.com/modules/converters/html", "prefix" : "tidy" }, { "uri" : "http://www.zorba-xquery.com/modules/converters/html-options", "prefix" : "tidy-options" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "send-request", "qname" : "http:send-request", "signature" : "($request as element(*)) as item()+", "description" : " Function for convenience.\n Calling this function is equivalent to calling\n \n http:send-request($request, (), ())\n \n", "summary" : "

    Function for convenience.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "request", "type" : "element(*)", "occurrence" : null, "description" : "
    see request parameter of the sequential send-request function with three parameters.
    " } ], "returns" : { "type" : "item()+", "description" : "see return value of the sequential send-request function with three parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "send-request", "qname" : "http:send-request", "signature" : "($request as element(*)?, $href as xs:string?) as item()+", "description" : " Function for convenience.\n Calling this function is equivalent to calling\n \n http:send-request($request, $href, ())\n \n", "summary" : "

    Function for convenience.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "request", "type" : "element(*)", "occurrence" : "?", "description" : "
    see request parameter of the sequential send-request function with three parameters.
    " }, { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "
    see href parameter of the sequential send-request function with three parameters.
    " } ], "returns" : { "type" : "item()+", "description" : "see return of send-request" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "send-request", "qname" : "http:send-request", "signature" : "($request as element(*)?, $href as xs:string?, $bodies as item()*) as item()+", "description" : " This function sends an HTTP request and returns the corresponding response.\n

    \n This function is declared as sequential (see XQuery Scripting).\n Sequential functions are allowed to have side effects. For example, most probably,\n an HTTP POST request is a request that has side effects because it adds/changes\n a remote resource.\n

    \n", "summary" : "

    This function sends an HTTP request and returns the corresponding response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "request", "type" : "element(*)", "occurrence" : "?", "description" : "
    Contains the various parameters of the request. See the specification. for a full description of the structure of this element.
    " }, { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "
    is the HTTP or HTTPS URI to send the request to. It must be a valid xs:anyURI, but is declared as a string to be able to pass literal strings (without requiring to explicitly cast it to an xs:anyURI.)
    " }, { "name" : "bodies", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "item()+", "description" : "a sequence of items, where the first item is a element of type http:responseType. The response element is also described in the specification. If there is one (or several, in case of multipart) response body, the response bodies are the next items in the sequence." }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/schema" : { "ns" : "http://zorba.io/modules/schema", "description" : " This module provides function that are related to XML Schema support\n in Zorba.\n", "sees" : [ ], "authors" : [ "Cezar Andrei, Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/schema", "prefix" : "schema" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "is-validated", "qname" : "schema:is-validated", "signature" : "($node as node()) as xs:boolean external", "description" : " This function returns true if the given node has been validated,\n and false otherwise.\n", "summary" : "

    This function returns true if the given node has been validated,\n and false otherwise.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : null, "description" : "
    the node item that should be checked for validation
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given node has been validated, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "schema-type", "qname" : "schema:schema-type", "signature" : "($item as item()) as xs:QName? external", "description" : " This function returns the name of the type of the item passed\n as parameter.\n", "summary" : "

    This function returns the name of the type of the item passed\n as parameter.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "item", "type" : "item()", "occurrence" : null, "description" : "
    the item from which the name of the type should be returned.
    " } ], "returns" : { "type" : "xs:QName?", "description" : "the name of the type (as QName) of the item passed as parameter." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "validate-in-place", "qname" : "schema:validate-in-place", "signature" : "($node as node()) external", "description" : " Updating function that validates the document in place. After the updating\n query is applied the $node will contain the validated content.\n", "summary" : "

    Updating function that validates the document in place.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : null, "description" : "
    the document or element to be validated, otherwise error
    " } ], "returns" : { "type" : null, "description" : "The result of the function is an empty XDM instance and a pending update list that consists the schema:validate-in-place($node)) primitive." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/mongodb" : { "ns" : "http://www.28msec.com/modules/mongodb", "description" : "

    This module provides a driver to access a\n MongoDB database - similar to\n drivers for other high-level languages like e.g.\n PyMongo.

    \n

    Here is a simple example of how we can raise the salary of each\n developer by 10%.\n Starting with an employees collection in MongoDB that contains\n

    \n { \"name\" : \"Peter\", \"role\" : \"developer\" , \"salary\" : 80 }\n { \"name\" : \"Paul\",  \"role\" : \"developer\" , \"salary\" : 75 }\n { \"name\" : \"Mary\",  \"role\" : \"manager\"   , \"salary\" : 90 } 
    \n we can get a connection\n
    \n variable $conn := mongo:connect(\"hostname\", 27017, \"db\", \"user\", \"password\");\n 
    \n run this update\n
    \n for $emp in mongo:find($conn, \"employees\")\n where $emp(\"role\") = \"developer\"\n let $salary := $emp(\"salary\")\n return {\n   replace value of json $emp(\"salary\") with $salary * 1.1;\n   mongo:save($conn, \"employees\", $emp)\n };\n 
    \n and get the names and the current salaries using\n
    \n mongo:find($conn, \"employees\", {}, { \"_id\" : false, \"role\" : false }, {}) 
    \n In this query we have removed the _id and role fields from\n the results and get\n
    \n { \"name\" : \"Peter\", \"salary\" : 88   }\n { \"name\" : \"Paul\",  \"salary\" : 82.5 }\n { \"name\" : \"Mary\",  \"salary\" : 90   }\n 
    \n

    \n

    Important Notice Regarding Function Determinism

    \n

    The non side-effecting functions:\n

    \n are declared deterministic, which means that their results could be cached\n when invoked multiple times with the same arguments in the same query execution.

    \n

    To not use cached results you can use the following alternative functions:\n

    \n which have been declared as being non deterministic.

    \n

    Three different functions have been defined to run mongo commands:\n

    \n If your application depends on the ordering of side-effects from commands issued\n through these functions you should use run-cmd#2,\n which has been declared as sequential.\n For non-side-effecting commands you can also use\n run-cmd-nondeterministic#2 and\n run-cmd-deterministic#2.\n The results of commands executed by means of\n run-cmd-deterministic#2 (which is\n declared deterministic) could be cached, whereas the results of\n commands executed by means of\n run-cmd-nondeterministic#2 (which is\n declared non-deterministic) are never cached.

    \n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://www.28msec.com/modules/mongodb/types", "prefix" : "m-schema" }, { "uri" : "http://www.28msec.com/modules/mongodb", "prefix" : "mongo" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "collection-names-nondeterministic", "qname" : "mongo:collection-names-nondeterministic", "signature" : "($db as xs:anyURI) as xs:string* external", "description" : "

    Get a list of all the collection names in this database.

    \n

    This function has the same semantics as\n collection-names#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Get a list of all the collection names in this database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " } ], "returns" : { "type" : "xs:string*", "description" : "a list of the names of all collection in the given database." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 1, "name" : "collection-names", "qname" : "mongo:collection-names", "signature" : "($db as xs:anyURI) as xs:string* external", "description" : "

    Get a list of all the collection names in this database.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Get a list of all the collection names in this database.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " } ], "returns" : { "type" : "xs:string*", "description" : "a list of the names of all collection in the given database." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 0, "name" : "connect-nondeterministic", "qname" : "mongo:connect-nondeterministic", "signature" : "() as xs:anyURI", "description" : "

    Connect to this project's default MongoDB database.

    \n

    This function has the same semantics as connect#0,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Connect to this project's default MongoDB database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for a connection to the MongoDB database." }, "errors" : [ "mongo:MONGO002 connection to MongoDB failed", "mongo:MONGO003 authentication to the MongoDB database failed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "connect-nondeterministic", "qname" : "mongo:connect-nondeterministic", "signature" : "($connection-config as item()) as xs:anyURI", "description" : "

    Connect to a MongoDB database.

    \n

    This function has the same semantics as connect#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Connect to a MongoDB database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-config", "type" : "item()", "occurrence" : null, "description" : "
    the connection specification.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for a connection to the MongoDB database." }, "errors" : [ "mongo:MONGO001 if the connection specification is invalid", "mongo:MONGO002 connection to MongoDB failed", "mongo:MONGO003 authentication to the MongoDB database failed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "connect-nondeterministic", "qname" : "mongo:connect-nondeterministic", "signature" : "($credentials-name as xs:string?, $options as object()) as xs:anyURI", "description" : "

    Connect to a MongoDB database.

    \n

    This function has the same semantics as connect#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Connect to a MongoDB database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials-name", "type" : "xs:string", "occurrence" : "?", "description" : "
    the name of the credentials to use.
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    the name of the credentials to use.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for a connection to the MongoDB database." }, "errors" : [ "mongo:MONGO001 if the connection specification is invalid", "mongo:MONGO002 connection to MongoDB failed", "mongo:MONGO003 authentication to the MongoDB database failed" ] }, { "isDocumented" : true, "arity" : 5, "name" : "connect-nondeterministic", "qname" : "mongo:connect-nondeterministic", "signature" : "($host as xs:string, $port as xs:integer?, $db as xs:string, $user as xs:string?, $pass as xs:string?) as xs:anyURI", "description" : "

    Connect to a MongoDB database.

    \n

    This function has the same semantics as connect#5,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Connect to a MongoDB database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host", "type" : "xs:string", "occurrence" : null, "description" : "
    the host to connect to
    " }, { "name" : "port", "type" : "xs:integer", "occurrence" : "?", "description" : "
    the port to connect to
    " }, { "name" : "db", "type" : "xs:string", "occurrence" : null, "description" : "
    the database to connect to
    " }, { "name" : "user", "type" : "xs:string", "occurrence" : "?", "description" : "
    the user used to authorize access to the db
    " }, { "name" : "pass", "type" : "xs:string", "occurrence" : "?", "description" : "
    the password used to authorize access to the db
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for a connection to the MongoDB database." }, "errors" : [ "mongo:MONGO002 connection to MongoDB failed", "mongo:MONGO003 authentication to the MongoDB database failed" ] }, { "isDocumented" : true, "arity" : 0, "name" : "connect", "qname" : "mongo:connect", "signature" : "() as xs:anyURI", "description" : "

    Connect to this project's default MongoDB database.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Connect to this project's default MongoDB database.

    ", "annotation_str" : " %an:strictlydeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "strictlydeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for a connection to the MongoDB database." }, "errors" : [ "mongo:MONGO002 connection to MongoDB failed", "mongo:MONGO003 authentication to the MongoDB database failed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "connect", "qname" : "mongo:connect", "signature" : "($connection-config as item()) as xs:anyURI", "description" : "

    Connect to a MongoDB database.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The $connection-config parameter is used to specify the connection information.\n If a string is used, then the function will interpret it as the name of\n a credential in the MongoDB category.\n If an object is used, then the function will open a connection using it.\n The object structure is the following:\n

      \n
    • host (string; mandatory)
    • \n
    • port (integer; default: 27017)
    • \n
    • db (string; mandatory)
    • \n
    • user (string)
    • \n
    • pass (string)
    • \n
    • timeout (decimal; default: 0)
    • \n
    • pre-digested (boolean; default: false)
    • \n
    \n

    \n

    For example, using stored credential:\n

    mongo:connect(\"credentials-name\")
    \n

    For example, specifying the connection information:

    \n
    mongo:connect(\n   {\n     \"host\": \"hostname\",\n     \"port\": 11011,\n     \"db\": \"mydb\",\n     \"user\": \"myuser\"\n     \"password: \"mypass\"\n   })
    .\n

    \n", "summary" : "

    Connect to a MongoDB database.

    ", "annotation_str" : " %an:strictlydeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "strictlydeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-config", "type" : "item()", "occurrence" : null, "description" : "
    the connection specification.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for a connection to the MongoDB database." }, "errors" : [ "mongo:MONGO001 if the connection specification is invalid", "mongo:MONGO002 connection to MongoDB failed", "mongo:MONGO003 authentication to the MongoDB database failed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "connect", "qname" : "mongo:connect", "signature" : "($credentials-name as xs:string?, $options as object()) as xs:anyURI", "description" : "

    Connect to a MongoDB database.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The $credentials-name parameter is used to specify the connection information.\n If empty a connection will be opened to the project default MongoDB database.\n Otherwise, the function will use it to identify a credential in the MongoDB category.\n

    \n

    The $options object can be used to specify connection options. The following\n fields are supported:\n

      \n
    • timeout (decimal; default: 0)
    • \n
    \n

    \n

    For example, connecting to the project default MongoDB database:\n

    mongo:connect((), {\"timeout\": 10})
    \n

    \n

    For example, specifying the connection information:\n

    mongo:connect(\"credentials-name\", {\"timeout\": 10})
    \n

    \n", "summary" : "

    Connect to a MongoDB database.

    ", "annotation_str" : " %an:strictlydeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "strictlydeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials-name", "type" : "xs:string", "occurrence" : "?", "description" : "
    the name of the credentials to use.
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    the name of the credentials to use.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for a connection to the MongoDB database." }, "errors" : [ "mongo:MONGO001 if the connection specification is invalid", "mongo:MONGO002 connection to MongoDB failed", "mongo:MONGO003 authentication to the MongoDB database failed" ] }, { "isDocumented" : true, "arity" : 5, "name" : "connect", "qname" : "mongo:connect", "signature" : "($host as xs:string, $port as xs:integer?, $db as xs:string, $user as xs:string?, $pass as xs:string?) as xs:anyURI", "description" : "

    Connect to a MongoDB database.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Connect to a MongoDB database.

    ", "annotation_str" : " %an:strictlydeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "strictlydeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host", "type" : "xs:string", "occurrence" : null, "description" : "
    the host to connect to
    " }, { "name" : "port", "type" : "xs:integer", "occurrence" : "?", "description" : "
    the port to connect to
    " }, { "name" : "db", "type" : "xs:string", "occurrence" : null, "description" : "
    the database to connect to
    " }, { "name" : "user", "type" : "xs:string", "occurrence" : "?", "description" : "
    the user used to authorize access to the db
    " }, { "name" : "pass", "type" : "xs:string", "occurrence" : "?", "description" : "
    the password used to authorize access to the db
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for a connection to the MongoDB database." }, "errors" : [ "mongo:MONGO002 connection to MongoDB failed", "mongo:MONGO003 authentication to the MongoDB database failed" ] }, { "isDocumented" : true, "arity" : 3, "name" : "copy", "qname" : "mongo:copy", "signature" : "($db as xs:anyURI, $from-db as xs:string, $to-db as xs:string) as empty-sequence()", "description" : "

    Copies a MongoDB database. Be aware, you must call\n this function on the admin database.

    \n", "summary" : "

    Copies a MongoDB database.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "from-db", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the source database
    " }, { "name" : "to-db", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the target database
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function has side-effects and returns the empty sequence." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if copy operation fails", "mongo:MONGO006 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 2, "name" : "count-nondeterministic", "qname" : "mongo:count-nondeterministic", "signature" : "($db as xs:anyURI, $coll as xs:string) as xs:integer external", "description" : "

    Counts the number of documents in the given collection.

    \n

    This function has the same semantics as count#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Counts the number of documents in the given collection.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " } ], "returns" : { "type" : "xs:integer", "description" : "the said count" }, "errors" : [ "mongo:MONGO005 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 3, "name" : "count-nondeterministic", "qname" : "mongo:count-nondeterministic", "signature" : "($db as xs:anyURI, $coll as xs:string, $query as object()) as xs:integer external", "description" : "

    Counts the number of documents satisfying the query in the given collection.

    \n

    This function has the same semantics as count#3,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Counts the number of documents satisfying the query in the given collection.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "query", "type" : "object()", "occurrence" : null, "description" : "
    the query specifying which objects to count
    " } ], "returns" : { "type" : "xs:integer", "description" : "the said count" }, "errors" : [ "mongo:MONGO005 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 2, "name" : "count", "qname" : "mongo:count", "signature" : "($db as xs:anyURI, $coll as xs:string) as xs:integer external", "description" : "

    Counts the number of documents in the given collection.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Counts the number of documents in the given collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " } ], "returns" : { "type" : "xs:integer", "description" : "the said count" }, "errors" : [ "mongo:MONGO005 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 3, "name" : "count", "qname" : "mongo:count", "signature" : "($db as xs:anyURI, $coll as xs:string, $query as object()) as xs:integer external", "description" : "

    Counts the number of documents satisfying the query in the given collection.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Counts the number of documents satisfying the query in the given collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "query", "type" : "object()", "occurrence" : null, "description" : "
    the query specifying which objects to count
    " } ], "returns" : { "type" : "xs:integer", "description" : "the said count" }, "errors" : [ "mongo:MONGO005 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 1, "name" : "disconnect", "qname" : "mongo:disconnect", "signature" : "($db as xs:anyURI) as empty-sequence() external", "description" : "

    Disconnect from a MongoDB database.

    \n", "summary" : "

    Disconnect from a MongoDB database.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function has side-effects and returns the empty sequence." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 2, "name" : "drop-collection", "qname" : "mongo:drop-collection", "signature" : "($db as xs:anyURI, $coll as xs:string) as empty-sequence() external", "description" : "

    Drop a collection.

    \n", "summary" : "

    Drop a collection.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function has side-effects and returns the empty sequence." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 2, "name" : "find-nondeterministic", "qname" : "mongo:find-nondeterministic", "signature" : "($db as xs:anyURI, $coll as xs:string) as object()*", "description" : "

    Returns all objects of the given collection.

    \n

    This function has the same semantics as find#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Returns all objects of the given collection.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " } ], "returns" : { "type" : "object()*", "description" : "all objects of the given collection" }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 3, "name" : "find-nondeterministic", "qname" : "mongo:find-nondeterministic", "signature" : "($db as xs:anyURI, $coll as xs:string, $query as object()) as object()*", "description" : "

    Performs a query operation on the given collection and\n returns all matches.

    \n

    This function has the same semantics as find#3,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Performs a query operation on the given collection and\n returns all matches.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "query", "type" : "object()", "occurrence" : null, "description" : "
    the query operation to perform
    " } ], "returns" : { "type" : "object()*", "description" : "all matches returned by the given query operation" }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens", "mongo:MONGO006 if the given query could not be converted to BSON" ] }, { "isDocumented" : true, "arity" : 4, "name" : "find-nondeterministic", "qname" : "mongo:find-nondeterministic", "signature" : "($db as xs:anyURI, $coll as xs:string, $query as object(), $options as object()) as object()*", "description" : "

    Performs a query operation on the given collection and\n returns all matches.

    \n

    This function has the same semantics as find#4,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Performs a query operation on the given collection and\n returns all matches.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "query", "type" : "object()", "occurrence" : null, "description" : "
    the query operation to perform
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    the options for this operation (see find#5 for available options)
    " } ], "returns" : { "type" : "object()*", "description" : "all matches returned by the given query operation" }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens", "mongo:MONGO006 if the given query could not be converted to BSON" ] }, { "isDocumented" : true, "arity" : 5, "name" : "find-nondeterministic", "qname" : "mongo:find-nondeterministic", "signature" : "($db as xs:anyURI, $coll as xs:string, $query as object(), $projection as object(), $options as object()) as object()* external", "description" : "

    Performs a query operation on the given collection and\n returns all matches.

    \n

    This function has the same semantics as find#5,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Performs a query operation on the given collection and\n returns all matches.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "query", "type" : "object()", "occurrence" : null, "description" : "
    the query operation to perform
    " }, { "name" : "projection", "type" : "object()", "occurrence" : null, "description" : "" }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    the options for this operation
    " } ], "returns" : { "type" : "object()*", "description" : "all matches returned by the given query operation" }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens", "mongo:MONGO006 if the given query or projection could not be converted to BSON" ] }, { "isDocumented" : true, "arity" : 2, "name" : "find", "qname" : "mongo:find", "signature" : "($db as xs:anyURI, $coll as xs:string) as object()*", "description" : "

    Returns all objects of the given collection.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Returns all objects of the given collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " } ], "returns" : { "type" : "object()*", "description" : "all objects of the given collection" }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 3, "name" : "find", "qname" : "mongo:find", "signature" : "($db as xs:anyURI, $coll as xs:string, $query as object()) as object()*", "description" : "

    Performs a query operation on the given collection and\n returns all matches.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Performs a query operation on the given collection and\n returns all matches.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "query", "type" : "object()", "occurrence" : null, "description" : "
    the query operation to perform
    " } ], "returns" : { "type" : "object()*", "description" : "all matches returned by the given query operation" }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens", "mongo:MONGO006 if the given query could not be converted to BSON" ] }, { "isDocumented" : true, "arity" : 4, "name" : "find", "qname" : "mongo:find", "signature" : "($db as xs:anyURI, $coll as xs:string, $query as object(), $options as object()) as object()*", "description" : "

    Performs a query operation on the given collection and\n returns all matches.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Performs a query operation on the given collection and\n returns all matches.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "query", "type" : "object()", "occurrence" : null, "description" : "
    the query operation to perform
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    the options for this operation (see find#5 for available options)
    " } ], "returns" : { "type" : "object()*", "description" : "all matches returned by the given query operation" }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens", "mongo:MONGO006 if the given query could not be converted to BSON" ] }, { "isDocumented" : true, "arity" : 5, "name" : "find", "qname" : "mongo:find", "signature" : "($db as xs:anyURI, $coll as xs:string, $query as object(), $projection as object(), $options as object()) as object()* external", "description" : "

    Performs a query operation on the given collection and\n returns all matches.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Available options:\n

      \n
    • to-return: the maximum number of objects to return (0 = unlimited)
    • \n
    • to-skip: start with the n-th object
    • \n
    • batch-size: the number of objects to return in one batch
    • \n
    • slave-ok: allow this query to be run against a replica secondary
    • \n
    • await-data: the server will block for some extra time before returning,\n waiting for more data to return
    • \n
    • partial-results: return partial results if some shards are down instead\n of returning an error
    • \n
    \n

    \n", "summary" : "

    Performs a query operation on the given collection and\n returns all matches.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "query", "type" : "object()", "occurrence" : null, "description" : "
    the query operation to perform
    " }, { "name" : "projection", "type" : "object()", "occurrence" : null, "description" : "" }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    the options for this operation
    " } ], "returns" : { "type" : "object()*", "description" : "all matches returned by the given query operation" }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens", "mongo:MONGO006 if the given query or projection could not be converted to BSON" ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-connected", "qname" : "mongo:is-connected", "signature" : "($db as xs:anyURI) as xs:boolean external", "description" : "

    Checks if the given identifiers is valid and the corresponding\n connection is open.

    \n", "summary" : "

    Checks if the given identifiers is valid and the corresponding\n connection is open.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given connection identifier is valid and the corresponding connection is open, false otherwise." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 3, "name" : "remove", "qname" : "mongo:remove", "signature" : "($db as xs:anyURI, $coll as xs:string, $remove as object()) as empty-sequence()", "description" : "

    Performs a remove operation on the given collection.

    \n

    The operation will be checked and an error is raised if\n one of them fails.

    \n", "summary" : "

    Performs a remove operation on the given collection.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "remove", "type" : "object()", "occurrence" : null, "description" : "
    the remove command to be performed
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function has side-effects and returns the empty sequence." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens", "mongo:MONGO006 if the given document could not be converted to BSON" ] }, { "isDocumented" : true, "arity" : 4, "name" : "remove", "qname" : "mongo:remove", "signature" : "($db as xs:anyURI, $coll as xs:string, $remove as object(), $options as object()) as empty-sequence() external", "description" : "

    Performs a remove operation on the given collection.

    \n

    \n

      \n
    • safe: If to true, the operation will wait for a response from\n the database and an error is raised if the operation fails.\n Otherwise, the operation will not wait for a response.
    • \n
    • just-one: true if the operation should stop after a single match\n has been found and deleted
    • \n
    \n

    \n", "summary" : "

    Performs a remove operation on the given collection.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "remove", "type" : "object()", "occurrence" : null, "description" : "
    the remove command to be performed
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    the options for this operation
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function has side-effects and returns the empty sequence." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens", "mongo:MONGO006 if the given document could not be converted to BSON" ] }, { "isDocumented" : true, "arity" : 2, "name" : "run-cmd-deterministic", "qname" : "mongo:run-cmd-deterministic", "signature" : "($db as xs:anyURI, $cmd as object()) as object() external", "description" : "

    Executes a\n database command.

    \n

    This function is marked as deterministic and should be used whenever the\n specified command has no side-effects and result caching is desired.

    \n", "summary" : "

    Executes a\n database command .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "cmd", "type" : "object()", "occurrence" : null, "description" : "
    the database command to execute
    " } ], "returns" : { "type" : "object()", "description" : "The result object. Typically has { ok : ..., errmsg : ... } fields set." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO006 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 2, "name" : "run-cmd-nondeterministic", "qname" : "mongo:run-cmd-nondeterministic", "signature" : "($db as xs:anyURI, $cmd as object()) as object() external", "description" : "

    Executes a\n database command.

    \n

    This function is marked as non-deterministic and should be used whenever the\n specified command has no side-effects and result caching is undesired.

    \n", "summary" : "

    Executes a\n database command .

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "cmd", "type" : "object()", "occurrence" : null, "description" : "
    the database command to execute
    " } ], "returns" : { "type" : "object()", "description" : "The result object. Typically has { ok : ..., errmsg : ... } fields set." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO006 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 2, "name" : "run-cmd", "qname" : "mongo:run-cmd", "signature" : "($db as xs:anyURI, $cmd as object()) as object() external", "description" : "

    Executes a\n database command.

    \n

    This function is marked as sequential and should be used whenever the\n specified command has side-effects.

    \n", "summary" : "

    Executes a\n database command .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "cmd", "type" : "object()", "occurrence" : null, "description" : "
    the database command to execute
    " } ], "returns" : { "type" : "object()", "description" : "The result object. Typically has { ok : ..., errmsg : ... } fields set." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO006 if any mongodb error happens" ] }, { "isDocumented" : true, "arity" : 3, "name" : "save", "qname" : "mongo:save", "signature" : "($db as xs:anyURI, $coll as xs:string, $doc as object()) as empty-sequence()", "description" : "

    Save a sequence of documents in the given collection.

    \n

    If a document to be save already has an \"_id\" field, then an\n upsert operation is performed an any existing document with that\n id will be overwritten. Otherwise, an insert operation is performed\n and the \"_id\" generated for each document will be returned.

    \n

    Each safe operation will be checked and an error is raised if\n one of them fails.

    \n", "summary" : "

    Save a sequence of documents in the given collection.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "doc", "type" : "object()", "occurrence" : null, "description" : "
    the document to be saved or upserted
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the documents that have been inserted with \"_id\" fields." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens", "mongo:MONGO006 if the given document could not be converted to BSON" ] }, { "isDocumented" : true, "arity" : 4, "name" : "save", "qname" : "mongo:save", "signature" : "($db as xs:anyURI, $coll as xs:string, $doc as object(), $options as object()) as m-schema:oid? external", "description" : "

    Save a sequence of documents in the given collection.

    \n

    If a document to be saved already has an \"_id\" field, then an\n upsert operation is performed and any existing document with that\n id will be overwritten. Otherwise, an insert operation is performed.

    \n

    If the manipulate option is set to true, an \"_id\" field will be\n added to the document. The new id will be returned. Otherwise,\n the \"_id\" field will be added by the server.

    \n

    If the safe options is set to true, each operation will wait for a\n response from the database and an error is raised if the operation\n fails. Otherwise, the operation will not wait for a response.

    \n", "summary" : "

    Save a sequence of documents in the given collection.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "doc", "type" : "object()", "occurrence" : null, "description" : "
    the document to be saved or upserted
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    the options for this operation
    " } ], "returns" : { "type" : "m-schema:oid?", "description" : "a generated OID if the manipulate option was set to true, the empty sequence otherwise." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens", "mongo:MONGO006 if the given document could not be converted to BSON" ] }, { "isDocumented" : true, "arity" : 4, "name" : "update", "qname" : "mongo:update", "signature" : "($db as xs:anyURI, $coll as xs:string, $query as object(), $update as object()) as empty-sequence()", "description" : "

    Performs an update command on the given collection.

    \n

    The operation will be checked and an error is raised if\n one of them fails. Also, this function only modifies one\n document matching the query and does not do any upserts.

    \n", "summary" : "

    Performs an update command on the given collection.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "query", "type" : "object()", "occurrence" : null, "description" : "
    the query to select the objects that are updated
    " }, { "name" : "update", "type" : "object()", "occurrence" : null, "description" : "
    the update specification to be performed
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function has side-effects and returns the empty sequence." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens", "mongo:MONGO006 if the given objects could not be converted to BSON" ] }, { "isDocumented" : true, "arity" : 5, "name" : "update", "qname" : "mongo:update", "signature" : "($db as xs:anyURI, $coll as xs:string, $query as object(), $update as object(), $options as object()) as empty-sequence() external", "description" : "

    Performs an update operation on the given collection.

    \n

    \n

      \n
    • safe: If to true, the operation will wait for a response from\n the database and an error is raised if the operation fails.\n Otherwise, the operation will not wait for a response.
    • \n
    • multi: indicates if all documents matching criteria should be updated\n rather than just one.
    • \n
    • upsert: if this should be an \"upsert\" operation; that is,\n if the record(s) do not exist, insert one. Upsert only inserts a single document.
    • \n
    \n

    \n", "summary" : "

    Performs an update operation on the given collection.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a database connection identifier
    " }, { "name" : "coll", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "query", "type" : "object()", "occurrence" : null, "description" : "
    the query to select the objects that are updated
    " }, { "name" : "update", "type" : "object()", "occurrence" : null, "description" : "
    the update specification to be performed
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    the options for this operation
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function has side-effects and returns the empty sequence." }, "errors" : [ "mongo:MONGO004 invalid database identifier", "mongo:MONGO005 if any mongodb error happens", "mongo:MONGO006 if the given objects could not be converted to BSON" ] } ], "variables" : [ ] }, "http://jsoniq.org/function-library" : { "ns" : "http://jsoniq.org/function-library", "description" : "

    This module provides extensions to the JSONiq core function library.

    \n

    The module is always imported so you do not need to import it explicitly.\n Also, you do not need to fully qualify a function to invoke it.

    \n", "sees" : [ "http://jsoniq.org/" ], "authors" : [ "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://jsoniq.org/functions", "prefix" : "jn" }, { "uri" : "http://jsoniq.org/function-library", "prefix" : "libjn" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "accumulate", "qname" : "libjn:accumulate", "signature" : "($items as item()*) as object()", "description" : " This function dynamically builds an object, like the {||} syntax, except that\n it does not throw an error upon pair collision. Instead, it accumulates them\n into an array, if more than one.\n", "summary" : "

    This function dynamically builds an object, like the {||} syntax, except that\n it does not throw an error upon pair collision.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    A sequence of items, the objects of which are going to be accumulated into a single object.
    " } ], "returns" : { "type" : "object()", "description" : "The accumulated object." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "descendant-arrays", "qname" : "libjn:descendant-arrays", "signature" : "($items as item()*) as array()*", "description" : " This function returns all arrays contained at any depth within a sequence of items.\n", "summary" : "

    This function returns all arrays contained at any depth within a sequence of items.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    A sequence of items.
    " } ], "returns" : { "type" : "array()*", "description" : "The descendant arrays of the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "descendant-objects", "qname" : "libjn:descendant-objects", "signature" : "($items as item()*) as object()*", "description" : " This function returns all objects contained at any depth within a sequence of items.\n", "summary" : "

    This function returns all objects contained at any depth within a sequence of items.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    A sequence of items.
    " } ], "returns" : { "type" : "object()*", "description" : "The descendant objects of the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "descendant-pairs-priv", "qname" : "libjn:descendant-pairs-priv", "signature" : "($i as item()) as object()*", "description" : " Helper function for libjn:descendant-pairs()\n", "summary" : "

    Helper function for libjn:descendant-pairs()\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "i", "type" : "item()", "occurrence" : null, "description" : "
    An item
    " } ], "returns" : { "type" : "object()*", "description" : "The descendant pairs of the item" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "descendant-pairs", "qname" : "libjn:descendant-pairs", "signature" : "($items as item()*) as object()*", "description" : " This function returns all pairs contained at any depth within an sequence of items.\n", "summary" : "

    This function returns all pairs contained at any depth within an sequence of items.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "All direct and indirect descendant pairs." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "intersect", "qname" : "libjn:intersect", "signature" : "($items as item()*) as object()", "description" : " This function returns the intersection of the objects contained in the\n given sequence of items, aggregating values corresponding to the same key\n into an array.\n", "summary" : "

    This function returns the intersection of the objects contained in the\n given sequence of items, aggregating values corresponding to the same key\n into an array.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    A sequence of items.
    " } ], "returns" : { "type" : "object()", "description" : "The insersection of the objects contained in $items." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "values", "qname" : "libjn:values", "signature" : "($items as item()*) as item()*", "description" : " This functions returns all values of all objects contained in a sequence of items.\n", "summary" : "

    This functions returns all values of all objects contained in a sequence of items.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    A sequence of items.
    " } ], "returns" : { "type" : "item()*", "description" : "The values inside the objects of the sequence." }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/node-position" : { "ns" : "http://zorba.io/modules/node-position", "description" : "

    This module provides a function (np:node-position) that, given a node,\n returns positional information about the node in the form of an xs:anyURI\n item. The module also defines functions that use such positional information\n to determine: (1) positional relationships between two nodes (e.g. if one\n is the ancestor of another) and (2) positional properties of a single node\n (e.g. its level in the tree).

    \n

    \n

    Within this module, the term \"node position\" will be used to refer to an\n xs:anyURI item that is returned by the np:node-position function.

    \n", "sees" : [ ], "authors" : [ "Federico Cavalieri, Markos Zaharioudakis" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/node-position", "prefix" : "np" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "ancestor-of", "qname" : "np:ancestor-of", "signature" : "($pos1 as xs:anyURI, $pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether the node position given as second argument is\n an ancestor of the node position given as first argument.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the second node is an ancestor of the first.

    \n

    Otherwise, the result of the function does not imply anything about the\n positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether the node position given as second argument is\n an ancestor of the node position given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "" }, { "name" : "pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos2 is an ancestor of the node position $n-pos1; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 2, "name" : "attribute-of", "qname" : "np:attribute-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether the node position given as second argument is\n an attribute of the node position given as first argument.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the second node is an attribute of the first.

    \n

    Otherwise, the result of the function does not imply anything about the\n positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether the node position given as second argument is\n an attribute of the node position given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential parent node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential attribute node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos2 is an attribute of the node position $n-pos1; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 2, "name" : "child-of", "qname" : "np:child-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether the node position given as second argument is\n a child of the node position given as first argument.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the second node is a child of the first.

    \n

    Otherwise, the result of the function does not imply anything about the\n positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether the node position given as second argument is\n a child of the node position given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential parent node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential child node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos2 is a child of the node position $n-pos1; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 2, "name" : "descendant-of", "qname" : "np:descendant-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether the node position given as second argument is\n a descendant of the node position given as first argument.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the second node is a descendant of the first.

    \n

    Otherwise, the result of the function does not imply anything about the\n positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether the node position given as second argument is\n a descendant of the node position given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential ancestor node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential descendant node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos2 is a descendant of the node position $n-pos1; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 2, "name" : "following-in-document-order-of", "qname" : "np:following-in-document-order-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether the node position given as second argument is\n following in document order the node position given as first argument.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the second node is following in document order the\n first.

    \n

    Otherwise, the result of the function does not imply anything about\n the positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether the node position given as second argument is\n following in document order the node position given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential preceding node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential following node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos2 is following in document order the node position $n-pos1; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 2, "name" : "following-of", "qname" : "np:following-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether the node position given as second argument is\n following the node position given as first argument.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the second node is following the first.

    \n

    Otherwise, the result of the function does not imply anything about the\n positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether the node position given as second argument is\n following the node position given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential preceding node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential following node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if node positions $n-pos1 and $n-pos2 belong to the same XML tree and $n-pos2 is following the node position $n-pos1; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 2, "name" : "following-sibling-of", "qname" : "np:following-sibling-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether the node position given as second argument is\n a following-sibling of the node position given as first argument.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the second node is a following-sibling of the first.

    \n

    Otherwise, the result of the function does not imply anything about the\n positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether the node position given as second argument is\n a following-sibling of the node position given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential preceding-sibling node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential following-sibling node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos2 is a following-sibling of the node position $n-pos1; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 1, "name" : "in-collection", "qname" : "np:in-collection", "signature" : "($n-pos as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether a node position belongs to a collection.

    \n", "summary" : "

    Determines whether a node position belongs to a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos belongs to a collection; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 2, "name" : "in-same-collection-of", "qname" : "np:in-same-collection-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether two node positions belong to the same collection.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the two nodes belong to the same collection.

    \n

    Otherwise, the result of the function does not imply anything about\n the positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether two node positions belong to the same collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the two nodes whose node positions are $n-pos1 and $n-pos2 belong to the same collection." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 2, "name" : "in-same-tree-of", "qname" : "np:in-same-tree-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether two node positions belong to the same tree.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the two nodes belong to the same tree.

    \n

    Otherwise, the result of the function does not imply anything about\n the positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether two node positions belong to the same tree.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the two nodes whose node positions are $n-pos1 and $n-pos2 belong to the same tree." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 2, "name" : "in-subtree-of", "qname" : "np:in-subtree-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether the node position given as second argument belongs\n to the subtree rooted at the node position given as first argument.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the second node belongs to the subtree rooted at the\n first. Otherwise, the result of the function does not imply anything about\n the positional relationship of the two nodes.

    \n

    \n

    This function differs from np:descendant-of in the way it treats attribute\n nodes. np:descendant-of follows the XQuery/XPath specification for the\n descendant axis, and as a result, it does not consider attributes as\n descendants of any nodes; it will always return false if $n-pos2 was\n obtained from an attribute node.In contrast, np:in-subtree-of will return\n true if $n-pos2 was obtained from an attribute node that appeared in the\n subtree of the node that $n-pos1 was obtained from.

    \n", "summary" : "

    Determines whether the node position given as second argument belongs\n to the subtree rooted at the node position given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential subtree root node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential node in the subtree node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos2 belongs to the subtree rooted at the node position $n-pos1; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-attribute", "qname" : "np:is-attribute", "signature" : "($n-pos1 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether a node position corresponds to an attribute node.

    \n", "summary" : "

    Determines whether a node position corresponds to an attribute node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos corresponds to an attribute; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-comment", "qname" : "np:is-comment", "signature" : "($n-pos1 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether a node position corresponds to a comment node.

    \n", "summary" : "

    Determines whether a node position corresponds to a comment node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos corresponds to an comment; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-document", "qname" : "np:is-document", "signature" : "($n-pos1 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether a node position corresponds to a document node.

    \n", "summary" : "

    Determines whether a node position corresponds to a document node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos corresponds to a document; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-element", "qname" : "np:is-element", "signature" : "($n-pos1 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether a node position corresponds to an element node.

    \n", "summary" : "

    Determines whether a node position corresponds to an element node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos corresponds to an element; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-processing-instruction", "qname" : "np:is-processing-instruction", "signature" : "($n-pos1 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether a node position corresponds to an processing-instruction\n node.

    \n", "summary" : "

    Determines whether a node position corresponds to an processing-instruction\n node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos corresponds to a processing instruction; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-text", "qname" : "np:is-text", "signature" : "($n-pos1 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether a node position corresponds to a text node.

    \n", "summary" : "

    Determines whether a node position corresponds to a text node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos corresponds to a text; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 1, "name" : "level", "qname" : "np:level", "signature" : "($n-pos as xs:anyURI) as xs:integer external", "description" : "

    Computes the level of a node position in its tree.

    \n

    \n

    Note: The root node of a tree is at level one.

    \n

    \n

    The result of the function applies to the corresponding node as well,\n that is, within the snapshot in which the position was computed, the node\n level is the returned one.

    \n

    The result of the function does not imply anything about the\n node level in other snapshots.

    \n", "summary" : "

    Computes the level of a node position in its tree.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the node position of the node whose level should be determined.
    " } ], "returns" : { "type" : "xs:integer", "description" : "the level in the tree of the node position $n-pos as xs:integer." }, "errors" : [ "zerr:ZAPI0028 if the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 1, "name" : "node-position", "qname" : "np:node-position", "signature" : "($arg as node()) as xs:anyURI external", "description" : "

    Return a URI item containing positional information for a given node.

    \n

    \n

    Within a snapshot, each has a different positional URI. However,\n different nodes in different snapshots might have the same URI.

    \n", "summary" : "

    Return a URI item containing positional information for a given node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "node()", "occurrence" : null, "description" : "
    the node for which the positional information URI should be computed
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "the opaque positional information URI of the node." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "parent-of", "qname" : "np:parent-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether the node position given as second argument is\n the parent of the node position given as first argument.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the second node is the parent of the first.

    \n

    Otherwise, the result of the function does not imply anything about the\n positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether the node position given as second argument is\n the parent of the node position given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential child node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential parent node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos2 is the parent of the node position $n-pos1; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 2, "name" : "preceding-in-document-order-of", "qname" : "np:preceding-in-document-order-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether the node position given as second argument is\n preceding in document order the node position given as first argument.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the second node is preceding in document order the\n first.

    \n

    Otherwise, the result of the function does not imply anything about\n the positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether the node position given as second argument is\n preceding in document order the node position given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential following node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential preceding node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos2 is preceding in document order the node position $n-pos1; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 2, "name" : "preceding-of", "qname" : "np:preceding-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether the node position given as second argument is\n preceding the node position given as first argument.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the second node is preceding the first.

    \n

    Otherwise, the result of the function does not imply anything about the\n positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether the node position given as second argument is\n preceding the node position given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential following node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential preceding node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if node positions $n-pos1 and $n-pos2 belong to the same XML tree and $n-pos2 is preceding the node position $n-pos1; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 2, "name" : "preceding-sibling-of", "qname" : "np:preceding-sibling-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether the node position given as second argument is\n a preceding-sibling of the node position given as first argument.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the second node is a preceding-sibling of the first.

    \n

    Otherwise, the result of the function does not imply anything about the\n positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether the node position given as second argument is\n a preceding-sibling of the node position given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential following-sibling node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the potential preceding-sibling node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the node position $n-pos2 is a preceding-sibling of the node position $n-pos1; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] }, { "isDocumented" : true, "arity" : 2, "name" : "sibling-of", "qname" : "np:sibling-of", "signature" : "($n-pos1 as xs:anyURI, $n-pos2 as xs:anyURI) as xs:boolean external", "description" : "

    Determines whether two node positions are siblings.

    \n

    \n

    If the two positions were obtained within the same snapshot S, then the\n result of the function applies to the corresponding nodes as well, that\n is, within snapshot S, the second node is a sibling of the first.

    \n

    Otherwise, the result of the function does not imply anything about the\n positional relationship of the two nodes.

    \n", "summary" : "

    Determines whether two node positions are siblings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "n-pos1", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a node position
    " }, { "name" : "n-pos2", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    a node position
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the two node positions $n-pos1 and $n-pos2 are siblings; false otherwise." }, "errors" : [ "zerr:ZAPI0028 if one of the given URI is not a valid node position computed by the np:node-position function." ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/cryptography/hash" : { "ns" : "http://www.zorba-xquery.com/modules/cryptography/hash", "description" : " This module provides functions that perform different hash operations.\n", "sees" : [ ], "authors" : [ "Gabriel Petrovay, Markus Pilman" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.zorba-xquery.com/modules/cryptography/hash", "prefix" : "hash" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "hash-impl", "qname" : "hash:hash-impl", "signature" : "($value as xs:string, $alg as xs:string) as xs:string external", "description" : " This function computes a hash value of the string provided as parameter.\n The function expects the hash algorithm to be used as parameter.\n", "summary" : "

    This function computes a hash value of the string provided as parameter.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to be hashed.
    " }, { "name" : "alg", "type" : "xs:string", "occurrence" : null, "description" : "
    The algorithm to use for this hashing operation. Currently only \"md5\" and \"sha1\" algorithms are available. If no valid algorithm name is given, md5 will be used.
    " } ], "returns" : { "type" : "xs:string", "description" : "The hash of the provided string. In case SHA1 is used, the resulting hash value is base64 encoded." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "md5", "qname" : "hash:md5", "signature" : "($value as xs:string) as xs:string", "description" : " Computes the MD5 hash of the string provided as parameter.\n", "summary" : "

    Computes the MD5 hash of the string provided as parameter.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to hash.
    " } ], "returns" : { "type" : "xs:string", "description" : "The MD5 hash of the provided string." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sha1", "qname" : "hash:sha1", "signature" : "($value as xs:string) as xs:string", "description" : " Computes the SHA1 hash of the string provided as parameter.\n", "summary" : "

    Computes the SHA1 hash of the string provided as parameter.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to hash.
    " } ], "returns" : { "type" : "xs:string", "description" : "The base64 encoded SHA1 hash of the provided string." }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/excel/lookup" : { "ns" : "http://zorba.io/modules/excel/lookup", "description" : " This module implements some Excel 2003 lookup functions.\n", "sees" : [ "Excel 2003 Documentation: Lookup Functions" ], "authors" : [ "Daniel Turcanu" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/excel/lookup", "prefix" : "excel" }, { "uri" : "http://zorba.io/modules/excel/errors", "prefix" : "excel-err" }, { "uri" : "http://zorba.io/modules/excel/math", "prefix" : "excel-math" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "choose", "qname" : "excel:choose", "signature" : "($index_num as xs:integer, $values as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Uses index_num to return a value from the sequence of value arguments.\n", "summary" : "

    Uses index_num to return a value from the sequence of value arguments.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "index_num", "type" : "xs:integer", "occurrence" : null, "description" : "
    The position in the sequence, 1 based.
    " }, { "name" : "values", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The sequence of values.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The value at the index position." }, "errors" : [ "excel-err:Value if index is smaller than 1 or bigger than the size of sequence." ] }, { "isDocumented" : true, "arity" : 30, "name" : "choose", "qname" : "excel:choose", "signature" : "($index_num as xs:integer, $value_sequence1 as xs:anyAtomicType*, $value_sequence2 as xs:anyAtomicType*, $value_sequence3 as xs:anyAtomicType*, $value_sequence4 as xs:anyAtomicType*, $value_sequence5 as xs:anyAtomicType*, $value_sequence6 as xs:anyAtomicType*, $value_sequence7 as xs:anyAtomicType*, $value_sequence8 as xs:anyAtomicType*, $value_sequence9 as xs:anyAtomicType*, $value_sequence10 as xs:anyAtomicType*, $value_sequence11 as xs:anyAtomicType*, $value_sequence12 as xs:anyAtomicType*, $value_sequence13 as xs:anyAtomicType*, $value_sequence14 as xs:anyAtomicType*, $value_sequence15 as xs:anyAtomicType*, $value_sequence16 as xs:anyAtomicType*, $value_sequence17 as xs:anyAtomicType*, $value_sequence18 as xs:anyAtomicType*, $value_sequence19 as xs:anyAtomicType*, $value_sequence20 as xs:anyAtomicType*, $value_sequence21 as xs:anyAtomicType*, $value_sequence22 as xs:anyAtomicType*, $value_sequence23 as xs:anyAtomicType*, $value_sequence24 as xs:anyAtomicType*, $value_sequence25 as xs:anyAtomicType*, $value_sequence26 as xs:anyAtomicType*, $value_sequence27 as xs:anyAtomicType*, $value_sequence28 as xs:anyAtomicType*, $value_sequence29 as xs:anyAtomicType*) as xs:anyAtomicType*", "description" : " Uses index_num to return a sequence from the list of sequences.\n Use CHOOSE to select one of up to 29 sequences based on the index number.\n", "summary" : "

    Uses index_num to return a sequence from the list of sequences.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "index_num", "type" : "xs:integer", "occurrence" : null, "description" : "
    the position in the sequence, 1 based
    " }, { "name" : "value_sequence1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence19", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence20", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence21", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence22", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence23", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence24", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence25", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence26", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence27", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence28", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " }, { "name" : "value_sequence29", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of values. Specify the empty sequence () if you don't need it.
    " } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "The value at the index position" }, "errors" : [ "excel-err:Value if index is smaller than 1 or bigger than 29" ] }, { "isDocumented" : true, "arity" : 5, "name" : "hlookup", "qname" : "excel:hlookup", "signature" : "($lookup_value as xs:anyAtomicType, $table_array as xs:anyAtomicType+, $table_width as xs:integer, $table_height as xs:integer, $row_index_num as xs:integer) as xs:anyAtomicType", "description" : " Same as above, only that range_lookup is defaulted to true.\n That is, this Hlookup looks for the approximate value\n and the first row must be ordered ascending.\n", "summary" : "

    Same as above, only that range_lookup is defaulted to true.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lookup_value", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the value to be searched. Allowed types are numeric, string, boolean.

    Boolean values are compared only with booleans. Numbers are compared only with numbers, if range_lookup is not zero. The other types are converted to string and compared to string value of all values.

    " }, { "name" : "table_array", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of values, row after row
    " }, { "name" : "table_width", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of values in a row
    " }, { "name" : "table_height", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of rows
    " }, { "name" : "row_index_num", "type" : "xs:integer", "occurrence" : null, "description" : "
    the row index, 1 based
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The value found, with original type" }, "errors" : [ "excel-err:Value if the array contains less elements than specified by table_height and table_width", "excel-err:Value if row_index_num is outside the range 1 .. table_height", "excel-err:Value if range_lookup is true and the value searched is smaller than the first value in the header", "excel-err:Value if range_lookup=false and the value cannot be found" ] }, { "isDocumented" : true, "arity" : 6, "name" : "hlookup", "qname" : "excel:hlookup", "signature" : "($lookup_value as xs:anyAtomicType, $table_array as xs:anyAtomicType+, $table_width as xs:integer, $table_height as xs:integer, $row_index_num as xs:integer, $range_lookup as xs:boolean) as xs:anyAtomicType", "description" : " Searches for a value in the top row of an array of values,\n and then returns a value in the same column from a row you specify in the array.\n
    Array is specified with 3 parameters:\n
    table_array
    is a sequence of elements, first row first, then second row and so on
    \n
    table_width
    specifies the number of elements in a row
    \n
    table_height
    specifies the number of rows
    \n The number of elements in table_array must be equal or more than table_width * table_height.

    \n For wildchar matching, the XQuery regex matcher is used.\n", "summary" : "

    Searches for a value in the top row of an array of values,\n and then returns a value in the same column from a row you specify in the array.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lookup_value", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the value to be searched. Allowed types are numeric, string, boolean.

    Boolean values are compared only with booleans. Numbers are compared only with numbers, if range_lookup is not zero. The other types are converted to string and compared to string value of all values.

    " }, { "name" : "table_array", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of values, row after row
    " }, { "name" : "table_width", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of values in a row
    " }, { "name" : "table_height", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of rows
    " }, { "name" : "row_index_num", "type" : "xs:integer", "occurrence" : null, "description" : "
    the row index, 1 based
    " }, { "name" : "range_lookup", "type" : "xs:boolean", "occurrence" : null, "description" : "
    specifies the algorithm to use:
    true
    find approximative match. First row of array must be sorted in ascending order.
    false
    find exact match, using xquery regex First row of array can be in any order.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The value found, with original type" }, "errors" : [ "excel-err:Value if the array contains less elements than specified by table_height and table_width", "excel-err:Value if row_index_num is outside the range 1 .. table_height", "excel-err:Value if range_lookup is true and the value searched is smaller than the first value in the header", "excel-err:Value if range_lookup=false and the value cannot be found" ] }, { "isDocumented" : true, "arity" : 5, "name" : "index", "qname" : "excel:index", "signature" : "($array as xs:anyAtomicType+, $array_height as xs:integer, $array_width as xs:integer, $row_num as xs:integer, $column_num as xs:integer) as xs:anyAtomicType+", "description" : " Returns a value from within an array.

    \n This is the Array form of the Excel Index function.

    \n

    Array is specified with 3 parameters:\n
    array
    is a sequence of elements, first row first, then second row and so on
    \n
    array_height
    specifies the number of rows
    \n
    array_width
    specifies the number of elements in a row
    \n The number of elements in array must be equal or more than array_width * array_height.\n", "summary" : "

    Returns a value from within an array.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of values, row after row
    " }, { "name" : "array_height", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of rows
    " }, { "name" : "array_width", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of values in a row
    " }, { "name" : "row_num", "type" : "xs:integer", "occurrence" : null, "description" : "
    the row position of the value, 1 based
    " }, { "name" : "column_num", "type" : "xs:integer", "occurrence" : null, "description" : "
    the column position of the value, 1 based
    " } ], "returns" : { "type" : "xs:anyAtomicType+", "description" : "The value from x-y in the array" }, "errors" : [ "excel-err:Value if the array contains less elements than specified by table_height and table_width", "excel-err:Ref if row_num is outside the range" ] }, { "isDocumented" : true, "arity" : 3, "name" : "lookup", "qname" : "excel:lookup", "signature" : "($lookup_value as xs:anyAtomicType, $lookup_vector as xs:anyAtomicType+, $result_vector as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " The Vector form.

    \n Looks in a sequence for a value\n and return a value from the same position in a second sequence.\n If the value is not found, then it matches the largest value in lookup_vector\n that is less than or equal to lookup_value.\n", "summary" : "

    The Vector form.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lookup_value", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the value to be searched
    " }, { "name" : "lookup_vector", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence to be searched, in ascending order.
    " }, { "name" : "result_vector", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence containing the result values
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "a value from $result_vector" }, "errors" : [ "excel-err:NA if lookup value is smaller than the first value in lookup_vector", "excel-err:NA if position found is outside the result range" ] }, { "isDocumented" : true, "arity" : 4, "name" : "lookup", "qname" : "excel:lookup", "signature" : "($lookup_value as xs:anyAtomicType, $array as xs:anyAtomicType+, $array_width as xs:integer, $array_height as xs:integer) as xs:anyAtomicType", "description" : " The Array form.

    \n It looks in the first row or column of an array for the specified value\n and returns a value from the same position in the last row or column of the array.

    \n If array covers an area that is wider than it is tall (more columns than rows),\n LOOKUP searches for lookup_value in the first row.

    \n If array is square or is taller than it is wide (more rows than columns),\n LOOKUP searches in the first column.

    \n The values in the first row or first column must be in ascending order.\n", "summary" : "

    The Array form.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lookup_value", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the value to be searched. If the value is not found, then it matches the largest value in lookup_vector that is less than or equal to lookup_value.
    " }, { "name" : "array", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the array sequence, row after row
    " }, { "name" : "array_width", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of values in a row
    " }, { "name" : "array_height", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of rows in the array
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The corresponding value in the last row or column" }, "errors" : [ "excel-err:Value if array contains less values than specified by array_width and array_height or array_width = 0 or array_height = 0", "excel-err:NA if the lookup_value is smaller than the first value in the row or column" ] }, { "isDocumented" : true, "arity" : 2, "name" : "match", "qname" : "excel:match", "signature" : "($lookup_value as xs:anyAtomicType, $sequence as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " Same as above, but match_type is defaulted to 1.\n It finds the largest value that is less than or equal to lookup_value.\n", "summary" : "

    Same as above, but match_type is defaulted to 1.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lookup_value", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    value to be searched.
    " }, { "name" : "sequence", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the vector where to search the value
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The position of found value" }, "errors" : [ "excel-err:NA for match_type 1 or -1, the lookup_value is smaller or larger than the first value in sequence", "excel-err:Value if range_lookup=0 and the value cannot be found" ] }, { "isDocumented" : true, "arity" : 3, "name" : "match", "qname" : "excel:match", "signature" : "($lookup_value as xs:anyAtomicType, $sequence as xs:anyAtomicType+, $match_type as xs:integer) as xs:anyAtomicType", "description" : " Returns the relative position of an item in a sequence that\n matches a specified value in a specified order.\n Only for one dimensional vector.\n", "summary" : "

    Returns the relative position of an item in a sequence that\n matches a specified value in a specified order.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lookup_value", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    value to be searched.
    " }, { "name" : "sequence", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the vector where to search the value
    " }, { "name" : "match_type", "type" : "xs:integer", "occurrence" : null, "description" : "
    specifies the algorithm used for searching. Possible values:
    1
    finds the largest value that is less than or equal to lookup_value. Sequence must be in ascending order.
    0
    finds the first value that is exactly equal to lookup_value.

    Sequence can be in any order.

    If lookup_value is boolean, then only booleans are compared.

    For other types, they are casted to string and then compared using xquery regular expressions. Lookup_value can be a xquery regular expression.

    -1
    finds the smallest value that is greater than or equal to lookup_value.

    Sequence must be in descending order.

    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The position of found value" }, "errors" : [ "excel-err:NA for match_type 1 or -1, the lookup_value is smaller or larger than the first value in sequence", "excel-err:Value if range_lookup=0 and the value cannot be found" ] }, { "isDocumented" : true, "arity" : 5, "name" : "offset", "qname" : "excel:offset", "signature" : "($reference as xs:anyAtomicType+, $reference_height as xs:integer, $reference_width as xs:integer, $rows as xs:integer, $cols as xs:integer) as xs:anyAtomicType*", "description" : " Same as above, only that the sub-array is specified only by rows and cols relative position.\n The sub-array height and width is computed to contain the remaining elements of the array.\n", "summary" : "

    Same as above, only that the sub-array is specified only by rows and cols relative position.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "reference", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the reference array
    " }, { "name" : "reference_height", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of rows in the reference array
    " }, { "name" : "reference_width", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of elements in the reference array row
    " }, { "name" : "rows", "type" : "xs:integer", "occurrence" : null, "description" : "
    the relative row position where the sub-array starts. It must be a positive value, zero relative.
    " }, { "name" : "cols", "type" : "xs:integer", "occurrence" : null, "description" : "
    the relative column position where the sub-array starts. It must be a positive value, zero relative.
    " } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "The sequence specifying the sub-array, row after row" }, "errors" : [ "excel-err:NA rows or cols are negative", "excel-err:NA height or width are smaller than 1", "excel-err:Value reference array contains less elements than specified by reference_height and reference_width", "excel-err:NA the resulted sub-array is not completely contained inside reference array" ] }, { "isDocumented" : true, "arity" : 7, "name" : "offset", "qname" : "excel:offset", "signature" : "($reference as xs:anyAtomicType+, $reference_height as xs:integer, $reference_width as xs:integer, $rows as xs:integer, $cols as xs:integer, $height as xs:integer, $width as xs:integer) as xs:anyAtomicType*", "description" : " Returns a sub-array from an array.\n The inner array must be within the reference array\n", "summary" : "

    Returns a sub-array from an array.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "reference", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the reference array
    " }, { "name" : "reference_height", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of rows in the reference array
    " }, { "name" : "reference_width", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of elements in the reference array row
    " }, { "name" : "rows", "type" : "xs:integer", "occurrence" : null, "description" : "
    the relative row position where the sub-array starts. It must be a positive value, zero relative.
    " }, { "name" : "cols", "type" : "xs:integer", "occurrence" : null, "description" : "
    the relative column position where the sub-array starts. It must be a positive value, zero relative.
    " }, { "name" : "height", "type" : "xs:integer", "occurrence" : null, "description" : "
    the desired height of sub-array. The sub-array must be inside the reference array.
    " }, { "name" : "width", "type" : "xs:integer", "occurrence" : null, "description" : "
    the desired width of sub-array. The sub-array must be inside the reference array.
    " } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "The sequence specifying the sub-array, row after row" }, "errors" : [ "excel-err:NA rows or cols are negative", "excel-err:NA height or width are smaller than 1", "excel-err:Value reference array contains less elements than specified by reference_height and reference_width", "excel-err:NA the resulted sub-array is not completely contained inside reference array" ] }, { "isDocumented" : true, "arity" : 3, "name" : "transpose", "qname" : "excel:transpose", "signature" : "($array as xs:anyAtomicType+, $array_width as xs:integer, $array_height as xs:integer) as xs:anyAtomicType+", "description" : " Transposes an array. The rows become columns and vice versa.\n", "summary" : "

    Transposes an array.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence specifying the array, row after row
    " }, { "name" : "array_width", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of elements in a row
    " }, { "name" : "array_height", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of rows in the array
    " } ], "returns" : { "type" : "xs:anyAtomicType+", "description" : "The transposed array. It will be a sequence specifying an array, row after row. The result width is the input height. The result height is the input width." }, "errors" : [ "excel-err:Value the array contains less elements than specified by array_width and array_height" ] }, { "isDocumented" : true, "arity" : 5, "name" : "vlookup", "qname" : "excel:vlookup", "signature" : "($lookup_value as xs:anyAtomicType, $table_array as xs:anyAtomicType+, $table_width as xs:integer, $table_height as xs:integer, $col_index_num as xs:integer) as xs:anyAtomicType", "description" : " Same as above, with range_lookup defaulted to true.\n It finds the largest value that is less than or equal to lookup_value.\n First column must be in ascending order.\n", "summary" : "

    Same as above, with range_lookup defaulted to true.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lookup_value", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the value to be searched. Allowed types are numeric, string, boolean.

    Boolean values are compared only with booleans. Numbers are compared only with numbers, if range_lookup is not zero. The other types are converted to string and compared to string value of all values.

    " }, { "name" : "table_array", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of values, row after row
    " }, { "name" : "table_width", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of values in a row
    " }, { "name" : "table_height", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of rows
    " }, { "name" : "col_index_num", "type" : "xs:integer", "occurrence" : null, "description" : "
    the row index, 1 based
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The value found, with original type" }, "errors" : [ "excel-err:Value if the array contains less elements than specified by table_height and table_width", "excel-err:Value if col_index_num is outside the range 1 .. table_height", "excel-err:Value if range_lookup is true and the value searched is smaller than the first value in the first column", "excel-err:Value if range_lookup=false and the value cannot be found" ] }, { "isDocumented" : true, "arity" : 6, "name" : "vlookup", "qname" : "excel:vlookup", "signature" : "($lookup_value as xs:anyAtomicType, $table_array as xs:anyAtomicType+, $table_width as xs:integer, $table_height as xs:integer, $col_index_num as xs:integer, $range_lookup as xs:boolean) as xs:anyAtomicType", "description" : " Searches for a value in the first column of a table array\n and returns a value in the same row from another column in the table array.\n
    Array is specified with 3 parameters:\n
    table_array
    is a sequence of elements, first row first, then second row and so on
    \n
    table_width
    specifies the number of elements in a row
    \n
    table_height
    specifies the number of rows
    \n For wildchar matching, the XQuery regex matcher is used.\n", "summary" : "

    Searches for a value in the first column of a table array\n and returns a value in the same row from another column in the table array.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lookup_value", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the value to be searched. Allowed types are numeric, string, boolean.

    Boolean values are compared only with booleans. Numbers are compared only with numbers, if range_lookup is not zero. The other types are converted to string and compared to string value of all values.

    " }, { "name" : "table_array", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of values, row after row
    " }, { "name" : "table_width", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of values in a row
    " }, { "name" : "table_height", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of rows
    " }, { "name" : "col_index_num", "type" : "xs:integer", "occurrence" : null, "description" : "
    the row index, 1 based
    " }, { "name" : "range_lookup", "type" : "xs:boolean", "occurrence" : null, "description" : "
    specified the algorithm to use:
    true
    find approximative match. First column of array must be sorted in ascending order.
    false
    find exact match, using xquery regex. First column of array can be in any order.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The value found, with original type" }, "errors" : [ "excel-err:Value if the array contains less elements than specified by table_height and table_width", "excel-err:Value if col_index_num is outside the range 1 .. table_height", "excel-err:Value if range_lookup is true and the value searched is smaller than the first value in the first column", "excel-err:Value if range_lookup=false and the value cannot be found" ] } ], "variables" : [ ] }, "http://zorba.io/modules/datetime" : { "ns" : "http://zorba.io/modules/datetime", "description" : "

    This module provides functions to retrieve the current dateTime and to\n parse dates and times.

    \n

    \n

    In contrast to the current-dateTime functions specified in\n XQuery Functions and\n Operators, the functions in this module are nondeterministic, that is,\n they do not return the current dateTime from the dynamic context, but return\n the actual value.

    \n

    \n

    Dates and times are parsed according to the format given by\n strptime.

    \n

    However, date and time values must be \"complete.\"

    \n

    For a date, the year and either month and day or day of the year must have\n been parsed.

    \n

    For a time, the hour must have been parsed.\n (If either the minute, second, or timezone has not been parsed, they default\n to 0.)

    \n

    For a dateTime, the parsing requirements of both date and time must be met.

    \n

    \n

    When a locale is given,\n it must be of the form {lang}[{sep}{country}[{encoding}]] where\n {lang} is an ISO 639-1 2-letter or 639-2 3-letter language code,\n {sep} is either '-' or '_',\n {country} is an ISO 3166-1 2-letter country code,\n and {encoding} is any string that begins with a '.'.

    \n

    The {sep}, {country}, and {encoding} are optional;\n {encoding} is always ignored.

    \n

    Examples include: de, en-US, fr_CA, ru_RU.UTF-8.

    \n", "sees" : [ "http://www.w3.org/TR/xpath-functions/#context" ], "authors" : [ "Matthias Brantner", "Paul J. Lucas" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://zorba.io/modules/datetime", "prefix" : "datetime" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "current-date", "qname" : "datetime:current-date", "signature" : "() as xs:date external", "description" : "

    Gets the current date value in Universal time.

    \n

    Note that this function is not stable: it returns the value of the date when\n the function is invoked.

    \n", "summary" : "

    Gets the current date value in Universal time.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:date", "description" : "the non-stable date value" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "current-dateTime", "qname" : "datetime:current-dateTime", "signature" : "() as xs:dateTimeStamp external", "description" : "

    Gets the current dateTime value in Universal time.

    \n

    Note that this function is not stable: it returns the value of the date and\n time when the function is invoked.

    \n", "summary" : "

    Gets the current dateTime value in Universal time.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:dateTimeStamp", "description" : "the non-stable datetime value" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "current-time", "qname" : "datetime:current-time", "signature" : "() as xs:time external", "description" : "

    Return the current time value in Universal time.

    \n

    Note that this function is not stable: it returns the value of the time when\n the function is invoked.

    \n", "summary" : "

    Return the current time value in Universal time.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:time", "description" : "the non-stable time value" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "millis-to-dateTime", "qname" : "datetime:millis-to-dateTime", "signature" : "($millis as xs:long) as xs:dateTime external", "description" : "

    Converts the given number of milliseconds since epoch into its corresponding\n xs:dateTime.

    \n", "summary" : "

    Converts the given number of milliseconds since epoch into its corresponding\n xs:dateTime.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "millis", "type" : "xs:long", "occurrence" : null, "description" : "
    The number of milliseconds since epoch.
    " } ], "returns" : { "type" : "xs:dateTime", "description" : "Returns an xs:dateTime." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "parse-date", "qname" : "datetime:parse-date", "signature" : "($input as xs:string, $format as xs:string) as xs:date external", "description" : "

    Parses a date from a string in the current locale.

    \n", "summary" : "

    Parses a date from a string in the current locale.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to parse.
    " }, { "name" : "format", "type" : "xs:string", "occurrence" : null, "description" : "
    The format string containing zero or more conversion specifications and ordinary characters. All ordinary characters are matched exactly with the buffer; all whitespace characters match any amount of whitespace in the buffer.
    " } ], "returns" : { "type" : "xs:date", "description" : "Returns an xs:date." }, "errors" : [ "datetime:INVALID_SPECIFICATION if $format contains an invalid conversion specification.", "datetime:INSUFFICIENT_BUFFER if $input is insufficient for $format.", "datetime:INVALID_VALUE if $input contains an invalid value for a conversion specification.", "datetime:LITERAL_MISMATCH if there is a literal characer mismatch between $input and $format.", "datetime:INCOMPLETE_DATE_OR_TIME if the date is incomplete." ] }, { "isDocumented" : true, "arity" : 3, "name" : "parse-date", "qname" : "datetime:parse-date", "signature" : "($input as xs:string, $format as xs:string, $locale as xs:string) as xs:date external", "description" : "

    Parses a date from a string in the given locale.

    \n", "summary" : "

    Parses a date from a string in the given locale.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to parse.
    " }, { "name" : "format", "type" : "xs:string", "occurrence" : null, "description" : "
    The format string containing zero or more conversion specifications and ordinary characters. All ordinary characters are matched exactly with the buffer; all whitespace characters match any amount of whitespace in the buffer.
    " }, { "name" : "locale", "type" : "xs:string", "occurrence" : null, "description" : "
    The locale to use.
    " } ], "returns" : { "type" : "xs:date", "description" : "Returns an xs:date." }, "errors" : [ "datetime:INVALID_SPECIFICATION if $format contains an invalid conversion specification.", "datetime:INSUFFICIENT_BUFFER if $input is insufficient for $format.", "datetime:INVALID_VALUE if $input contains an invalid value for a conversion specification.", "datetime:LITERAL_MISMATCH if there is a literal characer mismatch between $input and $format.", "datetime:INCOMPLETE_DATE_OR_TIME if the date is incomplete.", "datetime:INVALID_LOCALE if $locale is in an invalid format.", "datetime:UNKNOWN_LOCALE if $locale is unknown.", "datetime:UNSUPPORTED_LOCALE if $locale is unsupported by the operating system." ] }, { "isDocumented" : true, "arity" : 2, "name" : "parse-dateTime", "qname" : "datetime:parse-dateTime", "signature" : "($input as xs:string, $format as xs:string) as xs:dateTime external", "description" : "

    Parses a dateTime from a string in the current locale.

    \n", "summary" : "

    Parses a dateTime from a string in the current locale.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to parse.
    " }, { "name" : "format", "type" : "xs:string", "occurrence" : null, "description" : "
    The format string containing zero or more conversion specifications and ordinary characters. All ordinary characters are matched exactly with the buffer; all whitespace characters match any amount of whitespace in the buffer.
    " } ], "returns" : { "type" : "xs:dateTime", "description" : "Returns an xs:dateTime." }, "errors" : [ "datetime:INVALID_SPECIFICATION if $format contains an invalid conversion specification.", "datetime:INSUFFICIENT_BUFFER if $input is insufficient for $format.", "datetime:INVALID_VALUE if $input contains an invalid value for a conversion specification.", "datetime:LITERAL_MISMATCH if there is a literal characer mismatch between $input and $format.", "datetime:INCOMPLETE_DATE_OR_TIME if either the date or time is incomplete." ] }, { "isDocumented" : true, "arity" : 3, "name" : "parse-dateTime", "qname" : "datetime:parse-dateTime", "signature" : "($input as xs:string, $format as xs:string, $locale as xs:string) as xs:dateTime external", "description" : "

    Parses a dateTime from a string in the given locale.

    \n", "summary" : "

    Parses a dateTime from a string in the given locale.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to parse.
    " }, { "name" : "format", "type" : "xs:string", "occurrence" : null, "description" : "
    The format string containing zero or more conversion specifications and ordinary characters. All ordinary characters are matched exactly with the buffer; all whitespace characters match any amount of whitespace in the buffer.
    " }, { "name" : "locale", "type" : "xs:string", "occurrence" : null, "description" : "
    The locale to use.
    " } ], "returns" : { "type" : "xs:dateTime", "description" : "Returns an xs:dateTime." }, "errors" : [ "datetime:INVALID_SPECIFICATION if $format contains an invalid conversion specification.", "datetime:INSUFFICIENT_BUFFER if $input is insufficient for $format.", "datetime:INVALID_VALUE if $input contains an invalid value for a conversion specification.", "datetime:LITERAL_MISMATCH if there is a literal characer mismatch between $input and $format.", "datetime:INCOMPLETE_DATE_OR_TIME if either the date or time is incomplete.", "datetime:INVALID_LOCALE if $locale is in an invalid format.", "datetime:UNKNOWN_LOCALE if $locale is unknown.", "datetime:UNSUPPORTED_LOCALE if $locale is unsupported by the operating system." ] }, { "isDocumented" : true, "arity" : 2, "name" : "parse-time", "qname" : "datetime:parse-time", "signature" : "($input as xs:string, $format as xs:string) as xs:time external", "description" : "

    Parses a time from a string in the current locale.

    \n", "summary" : "

    Parses a time from a string in the current locale.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to parse.
    " }, { "name" : "format", "type" : "xs:string", "occurrence" : null, "description" : "
    The format string containing zero or more conversion specifications and ordinary characters. All ordinary characters are matched exactly with the buffer; all whitespace characters match any amount of whitespace in the buffer.
    " } ], "returns" : { "type" : "xs:time", "description" : "Returns an xs:time." }, "errors" : [ "datetime:INVALID_SPECIFICATION if $format contains an invalid conversion specification.", "datetime:INSUFFICIENT_BUFFER if $input is insufficient for $format.", "datetime:INVALID_VALUE if $input contains an invalid value for a conversion specification.", "datetime:LITERAL_MISMATCH if there is a literal characer mismatch between $input and $format.", "datetime:INCOMPLETE_DATE_OR_TIME if the hour has not been parsed." ] }, { "isDocumented" : true, "arity" : 3, "name" : "parse-time", "qname" : "datetime:parse-time", "signature" : "($input as xs:string, $format as xs:string, $locale as xs:string) as xs:time external", "description" : "

    Parses a time from a string in the given locale.

    \n", "summary" : "

    Parses a time from a string in the given locale.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to parse.
    " }, { "name" : "format", "type" : "xs:string", "occurrence" : null, "description" : "
    The format string containing zero or more conversion specifications and ordinary characters. All ordinary characters are matched exactly with the buffer; all whitespace characters match any amount of whitespace in the buffer.
    " }, { "name" : "locale", "type" : "xs:string", "occurrence" : null, "description" : "
    The locale to use.
    " } ], "returns" : { "type" : "xs:time", "description" : "Returns an xs:time." }, "errors" : [ "datetime:INVALID_SPECIFICATION if $format contains an invalid conversion specification.", "datetime:INSUFFICIENT_BUFFER if $input is insufficient for $format.", "datetime:INVALID_VALUE if $input contains an invalid value for a conversion specification.", "datetime:LITERAL_MISMATCH if there is a literal characer mismatch between $input and $format.", "datetime:INCOMPLETE_DATE_OR_TIME if the hour has not been parsed.", "datetime:INVALID_LOCALE if $locale is in an invalid format.", "datetime:UNKNOWN_LOCALE if $locale is unknown.", "datetime:UNSUPPORTED_LOCALE if $locale is unsupported by the operating system." ] }, { "isDocumented" : true, "arity" : 0, "name" : "timestamp", "qname" : "datetime:timestamp", "signature" : "() as xs:long external", "description" : "

    Gets the the number of milliseconds since epoch.

    \n", "summary" : "

    Gets the the number of milliseconds since epoch.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:long", "description" : "the said number of milliseconds." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "utc-offset", "qname" : "datetime:utc-offset", "signature" : "() as xs:long external", "description" : "

    Gets the offset of the current timezone from Universal time.

    \n", "summary" : "

    Gets the offset of the current timezone from Universal time.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:long", "description" : "the offset in seconds with positive values being east of the prime meridian." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/http/util/diagnostic" : { "ns" : "http://www.28msec.com/modules/http/util/diagnostic", "description" : " This module provides utility functions to help with diagnostic analysis\n / debugging of RESTful Apps or webapps.\n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/base64", "prefix" : "base64" }, { "uri" : "http://www.28msec.com/modules/http/util/diagnostic", "prefix" : "diagnostic" }, { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://www.28msec.com/modules/http/util/multipart", "prefix" : "multipart" }, { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "request" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "serialize-request-as-html", "qname" : "diagnostic:serialize-request-as-html", "signature" : "() as element(*)*", "description" : "

    Returns a sequence of html elements listing all request\n characteristics.

    \n

    This function is helpful for debugging purposes. It can be used\n to output request information within an HTML page.

    \n", "summary" : "

    Returns a sequence of html elements listing all request\n characteristics.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "element(*)*", "description" : "HTML elements describing the request" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "serialize-request-as-txt", "qname" : "diagnostic:serialize-request-as-txt", "signature" : "() as xs:string*", "description" : "

    Returns a sequence of xs:string listing all request\n characteristics.

    \n

    This function is helpful for debugging purposes. It can be used\n to output request information as plan text.

    \n", "summary" : "

    Returns a sequence of xs:string listing all request\n characteristics.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string*", "description" : "sequence of strings describing each characteristic of a request" }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/credentials" : { "ns" : "http://www.28msec.com/modules/credentials", "description" : "

    This module provides functionality for storing credentials\n using an AES-encrypted file the project configuration folder.

    \n

    Specifically, the credentials will be stored in the credentials\n file in the config folder in the project root folder.\n The credentials file is encrypted using 256bit AES encryption. The AES\n key is computed using the project seed. If the project seed is changed the\n credential store is re-encrypted transparently.

    \n

    Each credential has an associated name and category.\n Credentials can be retrieved specifying their name and category.

    \n

    For each category, it is possible to specify the default credentials.\n A category default credentials can then be easily retrieved.

    \n

    The name of credentials and categories can contain lowercase or\n uppercase letters, digits, and the following special characters: \"_\" , \"-\",\n \".\". Additionally it must not be empty and must start with a lowercase\n or uppercase letter.

    \n", "sees" : [ ], "authors" : [ "Federico Cavalieri" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://jsoniq.org/errors", "prefix" : "jerr" }, { "uri" : "http://www.28msec.com/modules/mongodb", "prefix" : "mongo" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 3, "name" : "add-credentials", "qname" : "credentials:add-credentials", "signature" : "($category as string, $name as string, $credentials as object()) as object()", "description" : "

    Adds the given credentials to the credential store.\n The credentials are not set as default.

    \n

    If credentials with the given name and category are already present an\n error is raised.

    \n

    Example:\n

    \n import module namespace credentials = \"http://www.28msec.com/modules/credentials\";\n credentials:add-credentials(\"S3\", \"DataBucket\", { ... });\n 
    \n

    \n", "summary" : "

    Adds the given credentials to the credential store.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "category", "type" : "string", "occurrence" : null, "description" : "
    The credentials category name.
    " }, { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The credentials name.
    " }, { "name" : "credentials", "type" : "object()", "occurrence" : null, "description" : "
    An object containing the credentials data.
    " } ], "returns" : { "type" : "object()", "description" : "the credential object" }, "errors" : [ "credentials:EXIST if credentials with the given name and category are already present.", "credentials:NAME if the credentials or category name is invalid", "credentials:MONGO-DEFAULT if the specified credentials and category name correspond with the default MongoDB credentials", "credentials:TEST if a connection cannot be established using the specified credentials", "credentials:CREDENTIALS-STORE if an internal error arises accessing the crendentials store" ] }, { "isDocumented" : true, "arity" : 4, "name" : "add-credentials", "qname" : "credentials:add-credentials", "signature" : "($category as string, $name as string, $credentials as object(), $default as boolean) as object()", "description" : "

    Adds the given credentials to the credential store,\n either as default or not.

    \n

    If credentials with the given name and category are already present an\n error is raised.

    \n

    Example:\n

    \n import module namespace credentials = \"http://www.28msec.com/modules/credentials\";\n credentials:add-credentials(\"S3\", \"DataBucket\", { ... }, true);\n 
    \n

    \n", "summary" : "

    Adds the given credentials to the credential store,\n either as default or not.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "category", "type" : "string", "occurrence" : null, "description" : "
    The credentials category name.
    " }, { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The credentials name.
    " }, { "name" : "credentials", "type" : "object()", "occurrence" : null, "description" : "
    An object containing the credentials data.
    " }, { "name" : "default", "type" : "boolean", "occurrence" : null, "description" : "
    Whether the credentials will be default or not.
    " } ], "returns" : { "type" : "object()", "description" : "the credential object" }, "errors" : [ "credentials:EXIST if credentials with the given name and category are already present.", "credentials:NAME if the credentials or category name is invalid", "credentials:MONGO-DEFAULT if trying to add the default MongoDB credentials", "credentials:TEST if a connection cannot be established using the specified credentials", "credentials:CREDENTIALS-STORE if an internal error arises accessing the crendentials store" ] }, { "isDocumented" : true, "arity" : 1, "name" : "credentials", "qname" : "credentials:credentials", "signature" : "($category as string) as object()?", "description" : "

    Returns the given category's default credentials, if any.

    \n

    If no default credentials are present for the given category\n the empty sequence is returned.

    \n

    Example:\n

    \n import module namespace credentials = \"http://www.28msec.com/modules/credentials\";\n credentials:credentials(\"S3\")\n 
    \n

    \n", "summary" : "

    Returns the given category's default credentials, if any.

    ", "annotation_str" : " %an:strictlydeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "strictlydeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "category", "type" : "string", "occurrence" : null, "description" : "
    The category name.
    " } ], "returns" : { "type" : "object()?", "description" : "The specified category default credentials, if any." }, "errors" : [ "credentials:NAME if the credentials or category name is invalid", "credentials:MONGO-DEFAULT if the specified category is MongoDB", "credentials:CREDENTIALS-STORE if an internal error arises accessing the crendentials store" ] }, { "isDocumented" : true, "arity" : 2, "name" : "credentials", "qname" : "credentials:credentials", "signature" : "($category as string, $name as string) as object()?", "description" : "

    Returns the specified credentials, if present in the credential store.

    \n

    If the specified credentials are not present the empty sequence is returned.

    \n

    Example:\n

    \n import module namespace credentials = \"http://www.28msec.com/modules/credentials\";\n credentials:credentials(\"S3\", \"DataBucket\")\n 
    \n

    \n", "summary" : "

    Returns the specified credentials, if present in the credential store.

    ", "annotation_str" : " %an:strictlydeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "strictlydeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "category", "type" : "string", "occurrence" : null, "description" : "
    The credentials category name.
    " }, { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The credentials name.
    " } ], "returns" : { "type" : "object()?", "description" : "The specified credentials, if present." }, "errors" : [ "credentials:NAME if the credentials or category name is invalid", "credentials:MONGO-DEFAULT if the credentials or category name is invalid", "credentials:CREDENTIALS-STORE if an internal error arises accessing the crendentials store" ] }, { "isDocumented" : true, "arity" : 0, "name" : "list-categories", "qname" : "credentials:list-categories", "signature" : "() as array()", "description" : "

    Lists all the credentials categories in the credentials store.

    \n

    If no credentials are stored the empty sequence is returned.

    \n

    Example:\n

    \n import module namespace credentials = \"http://www.28msec.com/modules/credentials\";\n credentials:list-categories()\n 
    \n

    \n

    The returned array contains the name of each distinct credential category.

    \n", "summary" : "

    Lists all the credentials categories in the credentials store.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "array()", "description" : "An array of all the distinct credentials categories in the credentials store." }, "errors" : [ "credentials:CREDENTIALS-STORE if an internal error arises accessing the crendentials store" ] }, { "isDocumented" : true, "arity" : 1, "name" : "list-category-credentials", "qname" : "credentials:list-category-credentials", "signature" : "($category-name as string) as array()", "description" : "

    Lists all the credentials of the specified category in the\n credentials store.

    \n

    If no credentials for the given category are stored the empty\n sequence is returned.

    \n

    Example:\n

    \n import module namespace credentials = \"http://www.28msec.com/modules/credentials\";\n credentials:list-category-credentials(\"category-name\")\n 
    \n

    \n

    The returned array contains one object for each credential. Each object has\n the following structure:\n

    \n {\n   \"category\": \"category-name\",\n   \"name\": \"credential-name\",\n   \"default\": true\n }\n 
    \n Specifically the fields of each object have the following meaning:\n
      \n
    • category: the name of the credentials category (string)
    • \n
    • name: the name of the credentials (string)
    • \n
    • default: whether the credentials are the default credentials in\n their category (boolean)
    • \n
    \n

    \n", "summary" : "

    Lists all the credentials of the specified category in the\n credentials store.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "category-name", "type" : "string", "occurrence" : null, "description" : "
    The credentials category name.
    " } ], "returns" : { "type" : "array()", "description" : "An array of all the credentials of the specified category in the credentials store." }, "errors" : [ "credentials:NAME if the credentials or category name is invalid", "credentials:CREDENTIALS-STORE if an internal error arises accessing the crendentials store" ] }, { "isDocumented" : true, "arity" : 0, "name" : "list-credentials", "qname" : "credentials:list-credentials", "signature" : "() as array()", "description" : "

    Lists all the credentials in the credentials store.

    \n

    If no credentials are stored the empty sequence is returned.

    \n

    Example:\n

    \n import module namespace credentials = \"http://www.28msec.com/modules/credentials\";\n credentials:list-credentials()\n 
    \n

    \n

    The returned array contains one object for each credential. Each object has\n the following structure:\n

    \n {\n   \"category\": \"category-name\",\n   \"name\": \"credential-name\",\n   \"default\": true\n }\n 
    \n Specifically the fields of each object have the following meaning:\n
      \n
    • category: the name of the credentials category (string)
    • \n
    • name: the name of the credentials (string)
    • \n
    • default: whether the credentials are the default credentials in\n their category (boolean)
    • \n
    \n

    \n", "summary" : "

    Lists all the credentials in the credentials store.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "array()", "description" : "An array of all credentials in the credentials store." }, "errors" : [ "credentials:CREDENTIALS-STORE if an internal error arises accessing the crendentials store" ] }, { "isDocumented" : true, "arity" : 2, "name" : "make-default", "qname" : "credentials:make-default", "signature" : "($category as string, $name as string) as empty-sequence()", "description" : "

    Makes the specified credentials the default for their category.

    \n

    It is not allowed to call this method on credentials in the \"MongoDB\" category.

    \n

    If the specified credentials are not present an error is raised.

    \n

    Example:\n

    \n import module namespace credentials = \"http://www.28msec.com/modules/credentials\";\n credentials:make-default(\"S3\", \"DataBucket\");\n 
    \n

    \n", "summary" : "

    Makes the specified credentials the default for their category.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "category", "type" : "string", "occurrence" : null, "description" : "
    The credentials category name.
    " }, { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The credentials name.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The empty sequence." }, "errors" : [ "credentials:NOT-EXIST if no credentials with the given name and category are present.", "credentials:NAME if the credentials or category name is invalid", "credentials:MONGO-DEFAULT if the specified category is MongoDB", "credentials:CREDENTIALS-STORE if an internal error arises accessing the crendentials store" ] }, { "isDocumented" : true, "arity" : 2, "name" : "remove-credentials", "qname" : "credentials:remove-credentials", "signature" : "($category as string, $name as string) as empty-sequence()", "description" : "

    Removes the specified credentials from the credential store.

    \n

    If no credentials with the given name and category are present\n in the category store an error is raised.

    \n

    Example:\n

    \n import module namespace credentials = \"http://www.28msec.com/modules/credentials\";\n credentials:remove-credentials(\"S3\", \"DataBucket\");\n 
    \n

    \n", "summary" : "

    Removes the specified credentials from the credential store.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "category", "type" : "string", "occurrence" : null, "description" : "
    The credentials category name.
    " }, { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The credentials name.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The empty sequence." }, "errors" : [ "credentials:NOT-EXIST if no credentials with the given name and category exist.", "credentials:NAME if the credentials or category name is invalid", "credentials:MONGO-DEFAULT if the specified credentials and category name correspond with the default MongoDB credentials", "credentials:CREDENTIALS-STORE if an internal error arises accessing the crendentials store" ] }, { "isDocumented" : true, "arity" : 5, "name" : "update-credentials", "qname" : "credentials:update-credentials", "signature" : "($category as string, $name as string, $new-default as boolean?, $new-name as string?, $new-credentials as object()?) as empty-sequence()", "description" : "

    Updates the specified credentials in the credential store.

    \n

    It is possible to specify whether the credentials should become or stop being the\n default credentials in their category, rename the credentials or change the credentials\n object. These three changes are specified by means of the $new-default, $new-name and\n $new-credentials parameter. If the corresponding parameter is the empty sequence the\n corresponding property will not be changed.

    \n

    For example the following query renames the \"DataBucket\" credentials in the \"S3\"\n category as \"Bucket\":\n

    \n import module namespace credentials = \"http://www.28msec.com/modules/credentials\";\n credentials:update-credentials(\"S3\", \"DataBucket\", (), \"Bucket\", () );\n 
    \n

    \n", "summary" : "

    Updates the specified credentials in the credential store.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "category", "type" : "string", "occurrence" : null, "description" : "
    The credentials category name.
    " }, { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    The credentials name.
    " }, { "name" : "new-default", "type" : "boolean", "occurrence" : "?", "description" : "
    Whether the credentials should become/stop being the default credentials in their category. If it is an empty sequence the current default property will not be changed.
    " }, { "name" : "new-name", "type" : "string", "occurrence" : "?", "description" : "" }, { "name" : "new-credentials", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty sequence" }, "errors" : [ "credentials:NOT-EXIST if credentials with the given name and category do not exist.", "credentials:EXIST if credentials with the given new name and category are already present.", "credentials:NAME if the credentials or category name is invalid", "credentials:MONGO-DEFAULT if the specified credentials or category name correspond with the default MongoDB credentials", "credentials:TEST if a connection cannot be established using the specified credentials", "credentials:CREDENTIALS-STORE if an internal error arises accessing the crendentials store" ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/parallelism" : { "ns" : "http://www.28msec.com/modules/parallelism", "description" : "

    This module provides functionality for executing FLWOR queries in parallel.

    \n

    There are two kinds of parallel jobs: map jobs and shuffle jobs.

    \n

    A map job runs a mapping function on the items of an input collection. The input\n collection is chunked and the mapping function is called on each chunk in parallel.\n The results are either inserted in a single collection, or on one ouptut collection\n for each chunk.

    \n

    A shuffle job shuffles the items of an input collection to several output collections.\n The input collection is chunked and each chunk is processed in parallel.\n The selection of the output collection for each item is done with a shuffling function.

    \n

    It is also possible to run a map or shuffle job on the output of another map or shuffle\n job (piping).\n Keep in mind though that if an intermediate output is in a\n single collection, no chunking can be done: only the first job of the pipeline can chunk\n its input.\n Hence, for performance, it makes sense that all intermediate jobs\n in the pipeline (except the last one, although not compulsory) output to automatically\n generated temporary collections rather than a single collection. That way, the next job\n can be executed on these collections in parallel.

    \n

    Map jobs allow the parallel execution of \"simple\" FLWORs: a for on a big collection, let clauses,\n small for clauses, where clauses.\n Map-shuffle-map piping allows the parallel execution of FLWORs containing a group by clause.\n Jobs can be composed in many ways, for example map-map-shuffle-map-shuffle-map. This way,\n FLWORs with several group by clauses can be parallelized.\n In some circumstances, FLWORs with order by clauses (using bucket sort) can also be\n parallelized, but one should keep in mind that collections are not ordered so that\n any ordering within a map job is susceptible to be lost in the output.

    \n", "sees" : [ ], "authors" : [ "Ghislain Fourny", "Julien Ribon" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/asynchronous-jobs", "prefix" : "job" }, { "uri" : "http://www.28msec.com/modules/parallelism", "prefix" : "parallel" }, { "uri" : "http://zorba.io/modules/random", "prefix" : "rand" }, { "uri" : "http://www.28msec.com/modules/store", "prefix" : "store" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "job-statuses", "qname" : "parallel:job-statuses", "signature" : "($id as xs:string) as object()?", "description" : "

    Returns the statuses of the underlying asynchronous jobs, as an object\n indicating the number of chunks in each status.

    \n", "summary" : "

    Returns the statuses of the underlying asynchronous jobs, as an object\n indicating the number of chunks in each status.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    The id of the parallel job to query, as it was returned by map or shuffle.
    " } ], "returns" : { "type" : "object()?", "description" : "The statuses of the underlying jobs. The empty sequence if the parallel job does not exist." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "map", "qname" : "parallel:map", "signature" : "($input as xs:string, $function as function (item()*) as item()*) as xs:string", "description" : "

    Schedules a parallel map job on a collection or on the output of another\n parallel job.

    \n

    The name of the output collections are randomly generated (one for\n each chunk and start with _28.temporary.

    \n

    Example of usage:

    \n parallel:map(\"input\", my:function#1)\n", "summary" : "

    Schedules a parallel map job on a collection or on the output of another\n parallel job.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the collection to process, or the id of a parallel job of which the output will be taken.
    " }, { "name" : "function", "type" : "function (item()*) as item()*", "occurrence" : null, "description" : "
    the function which is run in parallel on the collection's contents.
    " } ], "returns" : { "type" : "xs:string", "description" : "A parallel job id that can be used to query the parallel job's properties." }, "errors" : [ "job:JBDY0005 if the supplied function does not have a name.", "job:JBDY0006 if the supplied function is in the local namespace.", "job:JPDY0001 if the input is not an available collection or a parallel job id." ] }, { "isDocumented" : true, "arity" : 3, "name" : "map", "qname" : "parallel:map", "signature" : "($input as xs:string, $function as function (item()*) as item()*, $options as object()?) as xs:string", "description" : "

    Schedules a parallel map job on a collection or on the output of another\n parallel job.

    \n

    The $options parameter allows for the specification of properties for\n the parallel job. Allowed options are:\n

      \n
    • output-collection as string: the name of the collection in\n which the output of the executed query is stored. If not specified,\n the result of the query will be stored in a collection withing the\n MongoDB database associated with the project. The name of the\n collection is randomly generated and starts with _28.temporary\n
    • \n
    • chunk-size: the size of the chunks the collection must be split\n into, if it is not already sharded (default: MongoDB sharding, or 1000).\n
    • \n
    \n

    \n

    Example of usage:

    \n parallel:map(\"input\", my:function#1, { \"chunk-size\" : xs:int(1000) })\n parallel:map(\"input\",\n my:function#1,\n {\n \"chunk-size\" : xs:int(1000),\n \"output-collection\" : output\"\n }\n )\n", "summary" : "

    Schedules a parallel map job on a collection or on the output of another\n parallel job.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the collection to process, or the id of a parallel job of which the output will be taken.
    " }, { "name" : "function", "type" : "function (item()*) as item()*", "occurrence" : null, "description" : "
    The function which is run in parallel on the collection's contents.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An object specifying above options for the parallel job.
    " } ], "returns" : { "type" : "xs:string", "description" : "A parallel job id that can be used to query the parallel job's properties." }, "errors" : [ "err:XPTY0004 if the type of a supplied option is incorrect.", "job:JBDY0005 if the supplied function does not have a name.", "job:JBDY0006 if the supplied function is in the local namespace.", "job:JPDY0001 if the input is not an available collection or a parallel job id." ] }, { "isDocumented" : true, "arity" : 1, "name" : "output-collections", "qname" : "parallel:output-collections", "signature" : "($id as xs:string) as xs:string*", "description" : "

    Returns the output collections of the specified parallel job.

    \n", "summary" : "

    Returns the output collections of the specified parallel job.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    The id of the parallel job to query, as it was returned by map or shuffle.
    " } ], "returns" : { "type" : "xs:string*", "description" : "The names of the output collections to which the corresponding parallel job writes. The empty sequence if the job does not exist." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "results", "qname" : "parallel:results", "signature" : "($id as xs:string) as item()*", "description" : "

    Returns the results of the specified parallel job.

    \n", "summary" : "

    Returns the results of the specified parallel job.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    The id of the parallel job to query, as it was returned by map or shuffle.
    " } ], "returns" : { "type" : "item()*", "description" : "The structured items output by the corresponding parallel job. The empty sequence if the job does not exist." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "shuffle", "qname" : "parallel:shuffle", "signature" : "($input as xs:string, $function as function (item()) as xs:integer) as xs:string", "description" : "

    Schedules a parallel shuffle job on a collection or on the output of another\n parallel job.

    \n

    The output collection for each item is determined by calling the shuffle function,\n which gives an integer i. The i-th output collection\n is then taken. If necessary, a modulo operation is done\n to make sure that the integer is comprised between 1 and the number of output collections.

    \n

    The name of the output collections are randomly generated (10 of them) and\n start with _28.temporary.

    \n

    Example of usage:

    \n parallel:shuffle(\"input\", my:function#1)\n", "summary" : "

    Schedules a parallel shuffle job on a collection or on the output of another\n parallel job.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the collection to process, or the id of a parallel job of which the output will be taken.
    " }, { "name" : "function", "type" : "function (item()) as xs:integer", "occurrence" : null, "description" : "
    the function which is run on each item to determine where it is shuffled to.
    " } ], "returns" : { "type" : "xs:string", "description" : "A parallel job id that can be used to query the parallel job's properties." }, "errors" : [ "job:JBDY0005 if the supplied function does not have a name.", "job:JBDY0006 if the supplied function is in the local namespace.", "job:JPDY0001 if the input is not an available collection or a parallel job id." ] }, { "isDocumented" : true, "arity" : 3, "name" : "shuffle", "qname" : "parallel:shuffle", "signature" : "($input as item(), $function as function (item()) as xs:integer, $options as object()?) as xs:string", "description" : "

    Schedules a parallel shuffle job on a collection or on the output of another\n parallel job.

    \n

    The output collection for each item is determined by calling the shuffle function,\n which gives an integer i. The i-th output collection\n is then taken. If necessary, a modulo operation is done\n to make sure that the integer is comprised between 1 and the number of output collections.

    \n

    The $options parameter allows for the specification of properties for\n the parallel shuffle job. Allowed options are:\n

      \n
    • number-of-output-collections as integer: the number of output collections\n to automatically generate if none are provided. The default value is 10. An error is raised\n if the provided value is not positive.\n
    • \n
    • output-collections as array: an array with the names of the collections in\n which the items of the input collections are shuffled. If not specified,\n these collections will be automatically generated (as many as specified in the\n number-of-output-collections option) in the\n MongoDB database associated with the project. The name of the\n collections are randomly generated and start with _28.temporary\n
    • \n
    • chunk-size: the size of the chunks the collection must be split\n into, if it is not already sharded (default: MongoDB sharding, or 1000).\n
    • \n
    \n

    \n

    Example of usage:

    \n parallel:shuffle(\"input\", my:function#1, { \"chunk-size\" : xs:int(1000) })\n parallel:shuffle(\"input\",\n my:function#1,\n {\n \"chunk-size\" : xs:int(1000),\n \"output-collections\" : [ \"output1\", \"output2\" ]\n }\n )\n parallel:shuffle(\"input\",\n my:function#1,\n {\n \"number-of-output-collections\" : 20\n }\n )\n", "summary" : "

    Schedules a parallel shuffle job on a collection or on the output of another\n parallel job.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "item()", "occurrence" : null, "description" : "
    The name of the collection to process, or the id of a parallel job of which the output will be taken.
    " }, { "name" : "function", "type" : "function (item()) as xs:integer", "occurrence" : null, "description" : "
    the function which is run on each item to determine where it is shuffled to.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An object specifying above options for the parallel shuffle job.
    " } ], "returns" : { "type" : "xs:string", "description" : "A parallel job id that can be used to query the parallel job's properties." }, "errors" : [ "err:XPTY0004 if the type of a supplied option is incorrect.", "job:JBDY0005 if the supplied function does not have a name.", "job:JBDY0006 if the supplied function is in the local namespace.", "job:JPDY0001 if the input is not an available collection or a parallel job id.", "err:FOCA0002 if number-of-output-collections is not a positive integer." ] }, { "isDocumented" : true, "arity" : 1, "name" : "status", "qname" : "parallel:status", "signature" : "($id as xs:string) as xs:string?", "description" : "

    Returns the general status of the parallel job.

    \n", "summary" : "

    Returns the general status of the parallel job.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    id of the parallel job to query, as it was returned by map or shuffle.
    " } ], "returns" : { "type" : "xs:string?", "description" : "The status of the corresponding parallel job. The empty sequence if the job does not exist." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/image/graphviz" : { "ns" : "http://www.zorba-xquery.com/modules/image/graphviz", "description" : "

    Module that provides functions for generating SVG graphs.

    \n

    The module provides two function for generating graphs given in the :\n

    \n Both functions use the Graphviz Visualization Library in order to\n layout and render the graphs. As a result, both return a sequence\n of (document)-nodes (one for each input graph).\n These nodes are instances of the Scalable Vector Graphics (SVG) format.\n SVG is a language for describing two-dimensional graphics and\n graphical applications in XML. More information about SVG can\n be found at http://www.w3.org/Graphics/SVG/.\n As second parameters, both functions take a sequence of strings that\n are parameters for the graph generation and rendering algorithms.\n Currently, only the empty-sequence is allowed here.\n These parameters exist for future use.

    \n

    Please note that this feature is only available on Unix-based\n platforms (i.e. not on Windows).

    \n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.zorba-xquery.com/modules/image/graphviz", "prefix" : "gr" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "dot", "qname" : "gr:dot", "signature" : "($dot as xs:string*, $params as xs:string*) as node()* external", "description" : " Layout one ore more graphs given in the DOT language and render\n them as SVG. For example,\n

    \n dot(\"digraph mygraph { p -> q }\", ())\n

    \n", "summary" : "

    Layout one ore more graphs given in the DOT language and render\n them as SVG.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "dot", "type" : "xs:string", "occurrence" : "*", "description" : "
    A dot description of the graph to render.
    " }, { "name" : "params", "type" : "xs:string", "occurrence" : "*", "description" : "
    Parameters to configure the layout and rendering process. Currently, only the empty-sequence is allowed here.
    " } ], "returns" : { "type" : "node()*", "description" : "A graph for each item in the sequence given using the first parameter. The result sequence consists of items which are instance of the SVG data model." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "gxl", "qname" : "gr:gxl", "signature" : "($gxl as node()*, $params as xs:string*) as node()* external", "description" : " Layout one ore more graphs given in the GXL language and render\n them as SVG.\n", "summary" : "

    Layout one ore more graphs given in the GXL language and render\n them as SVG.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "gxl", "type" : "node()", "occurrence" : "*", "description" : "
    A GXL description of the graph to render.
    " }, { "name" : "params", "type" : "xs:string", "occurrence" : "*", "description" : "
    Parameters to configure the layout and rendering process. Currently, only the empty-sequence is allowed here.
    " } ], "returns" : { "type" : "node()*", "description" : "A graph for each item in the sequence given using the first parameter. The result sequence consists of items which are instance of the SVG data model." }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/data-cleaning/token-based-string-similarity" : { "ns" : "http://zorba.io/modules/data-cleaning/token-based-string-similarity", "description" : "

    This library module provides token-based string similarity functions that view strings\n as sets or multi-sets of tokens and use set-related properties to compute similarity scores.

    \n

    The tokens correspond to groups of characters extracted from the strings being compared, such as\n individual words or character n-grams.

    \n

    \n

    These functions are particularly useful for matching near duplicate strings in cases where\n typographical conventions often lead to rearrangement of words (e.g., \"John Smith\" versus \"Smith, John\").

    \n

    \n

    The logic contained in this module is not specific to any particular XQuery implementation,\n although the module requires the trigonometic functions of XQuery 3.0 or a math extension\n function such as sqrt($x as numeric) for computing the square root.

    \n", "sees" : [ ], "authors" : [ "Bruno Martins" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xpath-functions/math", "prefix" : "math" }, { "uri" : "http://zorba.io/modules/data-cleaning/set-similarity", "prefix" : "set" }, { "uri" : "http://zorba.io/modules/data-cleaning/token-based-string-similarity", "prefix" : "simt" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 3, "name" : "cosine-ngrams", "qname" : "simt:cosine-ngrams", "signature" : "($s1 as xs:string, $s2 as xs:string, $n as xs:integer) as xs:double", "description" : "

    Returns the cosine similarity coefficient between sets of character n-grams extracted from two strings.

    \n

    The n-grams from each string are weighted according to their occurence frequency (i.e., weighted according to\n the term-frequency heuristic from Information Retrieval).

    \n

    \n

    Example usage :

     cosine-ngrams(\"DWAYNE\", \"DUANE\", 2 ) 

    \n

    \n

    The function invocation in the example above returns :

     0.2401922307076307 

    \n", "summary" : "

    Returns the cosine similarity coefficient between sets of character n-grams extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "n", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of characters to consider when extracting n-grams.
    " } ], "returns" : { "type" : "xs:double", "description" : "The cosine similarity coefficient between the sets n-grams extracted from the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "cosine-tokens", "qname" : "simt:cosine-tokens", "signature" : "($s1 as xs:string, $s2 as xs:string, $r as xs:string) as xs:double", "description" : "

    Returns the cosine similarity coefficient between sets of tokens extracted from two strings. The tokens\n from each string are weighted according to their occurence frequency (i.e., weighted according to the\n term-frequency heuristic from Information Retrieval).

    \n

    \n

    Example usage :

     cosine-tokens(\"The FLWOR Foundation\", \"FLWOR Found.\", \" +\" ) 

    \n

    \n

    The function invocation in the example above returns :

     0.408248290463863 

    \n", "summary" : "

    Returns the cosine similarity coefficient between sets of tokens extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "r", "type" : "xs:string", "occurrence" : null, "description" : "
    A regular expression forming the delimiter character(s) which mark the boundaries between adjacent tokens.
    " } ], "returns" : { "type" : "xs:double", "description" : "The cosine similarity coefficient between the sets tokens extracted from the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "cosine", "qname" : "simt:cosine", "signature" : "($desc1 as xs:string*, $desc2 as xs:string*) as xs:double", "description" : "

    Auxiliary function for computing the cosine similarity coefficient between strings,\n using stringdescriptors based on sets of character n-grams or sets of tokens extracted from two strings.

    \n

    \n

    Example usage :

     cosine( (\"aa\",\"bb\") , (\"bb\",\"aa\")) 

    \n

    \n

    The function invocation in the example above returns :

     1.0 

    \n", "summary" : "

    Auxiliary function for computing the cosine similarity coefficient between strings,\n using stringdescriptors based on sets of character n-grams or sets of tokens extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "desc1", "type" : "xs:string", "occurrence" : "*", "description" : "
    The descriptor for the first string.
    " }, { "name" : "desc2", "type" : "xs:string", "occurrence" : "*", "description" : "
    The descriptor for the second string.
    " } ], "returns" : { "type" : "xs:double", "description" : "The cosine similarity coefficient between the descriptors for the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "dice-ngrams", "qname" : "simt:dice-ngrams", "signature" : "($s1 as xs:string, $s2 as xs:string, $n as xs:integer) as xs:double", "description" : "

    Returns the Dice similarity coefficient between sets of character n-grams extracted from two strings.

    \n

    \n

    Example usage :

     dice-ngrams(\"DWAYNE\", \"DUANE\", 2 ) 

    \n

    \n

    The function invocation in the example above returns :

     0.4615384615384616 

    \n", "summary" : "

    Returns the Dice similarity coefficient between sets of character n-grams extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "n", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of characters to consider when extracting n-grams.
    " } ], "returns" : { "type" : "xs:double", "description" : "The Dice similarity coefficient between the sets of character n-grams extracted from the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "dice-tokens", "qname" : "simt:dice-tokens", "signature" : "($s1 as xs:string, $s2 as xs:string, $r as xs:string) as xs:double", "description" : "

    Returns the Dice similarity coefficient between sets of tokens extracted from two strings.

    \n

    \n

    Example usage :

     dice-tokens(\"The FLWOR Foundation\", \"FLWOR Found.\", \" +\" ) 

    \n

    \n

    The function invocation in the example above returns :

     0.4 

    \n", "summary" : "

    Returns the Dice similarity coefficient between sets of tokens extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "r", "type" : "xs:string", "occurrence" : null, "description" : "
    A regular expression forming the delimiter character(s) which mark the boundaries between adjacent tokens.
    " } ], "returns" : { "type" : "xs:double", "description" : "The Dice similarity coefficient between the sets tokens extracted from the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "jaccard-ngrams", "qname" : "simt:jaccard-ngrams", "signature" : "($s1 as xs:string, $s2 as xs:string, $n as xs:integer) as xs:double", "description" : "

    Returns the Jaccard similarity coefficient between sets of character n-grams extracted from two strings.

    \n

    \n

    Example usage :

     jaccard-ngrams(\"DWAYNE\", \"DUANE\", 2 ) 

    \n

    \n

    The function invocation in the example above returns :

     0.3 

    \n", "summary" : "

    Returns the Jaccard similarity coefficient between sets of character n-grams extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "n", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of characters to consider when extracting n-grams.
    " } ], "returns" : { "type" : "xs:double", "description" : "The Jaccard similarity coefficient between the sets of character n-grams extracted from the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "jaccard-tokens", "qname" : "simt:jaccard-tokens", "signature" : "($s1 as xs:string, $s2 as xs:string, $r as xs:string) as xs:double", "description" : "

    Returns the Jaccard similarity coefficient between sets of tokens extracted from two strings.

    \n

    \n

    Example usage :

     jaccard-tokens(\"The FLWOR Foundation\", \"FLWOR Found.\", \" +\" ) 

    \n

    \n

    The function invocation in the example above returns :

     0.25 

    \n", "summary" : "

    Returns the Jaccard similarity coefficient between sets of tokens extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "r", "type" : "xs:string", "occurrence" : null, "description" : "
    A regular expression forming the delimiter character(s) which mark the boundaries between adjacent tokens.
    " } ], "returns" : { "type" : "xs:double", "description" : "The Jaccard similarity coefficient between the sets tokens extracted from the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "ngrams", "qname" : "simt:ngrams", "signature" : "($s as xs:string, $n as xs:integer) as xs:string*", "description" : "

    Returns the individual character n-grams forming a string.

    \n

    \n

    Example usage :

     ngrams(\"FLWOR\", 2 ) 

    \n

    \n

    The function invocation in the example above returns :

     (\"_F\" , \"FL\" , \"LW\" , \"WO\" , \"LW\" , \"WO\" , \"OR\" , \"R_\") 

    \n", "summary" : "

    Returns the individual character n-grams forming a string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "xs:string", "occurrence" : null, "description" : "
    The input string.
    " }, { "name" : "n", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of characters to consider when extracting n-grams.
    " } ], "returns" : { "type" : "xs:string*", "description" : "The sequence of strings with the extracted n-grams." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "overlap-ngrams", "qname" : "simt:overlap-ngrams", "signature" : "($s1 as xs:string, $s2 as xs:string, $n as xs:integer) as xs:double", "description" : "

    Returns the overlap similarity coefficient between sets of character n-grams extracted from two strings.

    \n

    \n

    Example usage :

     overlap-ngrams(\"DWAYNE\", \"DUANE\", 2 ) 

    \n

    \n

    The function invocation in the example above returns :

     0.5 

    \n", "summary" : "

    Returns the overlap similarity coefficient between sets of character n-grams extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "n", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of characters to consider when extracting n-grams.
    " } ], "returns" : { "type" : "xs:double", "description" : "The overlap similarity coefficient between the sets of character n-grams extracted from the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "overlap-tokens", "qname" : "simt:overlap-tokens", "signature" : "($s1 as xs:string, $s2 as xs:string, $r as xs:string) as xs:double", "description" : "

    Returns the overlap similarity coefficient between sets of tokens extracted from two strings.

    \n

    \n

    Example usage :

     overlap-tokens(\"The FLWOR Foundation\", \"FLWOR Found.\", \" +\" ) 

    \n

    \n

    The function invocation in the example above returns :

     0.5 

    \n", "summary" : "

    Returns the overlap similarity coefficient between sets of tokens extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "r", "type" : "xs:string", "occurrence" : null, "description" : "
    A regular expression forming the delimiter character(s) which mark the boundaries between adjacent tokens.
    " } ], "returns" : { "type" : "xs:double", "description" : "The overlap similarity coefficient between the sets tokens extracted from the two strings." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/image/paint" : { "ns" : "http://www.zorba-xquery.com/modules/image/paint", "description" : " This module provides a function to extend an image with additional shapes.\n Fully supported image formats are:\n
      \n
    • GIF
    • \n
    • JPEG
    • \n
    • PNG
    • \n
    • TIFF
    • \n
    • BMP
    • \n
    \n

    The errors raised by functions of this module have the namespace\n http://www.zorba-xquery.com/modules/image/error (associated with prefix ierr).

    \n", "sees" : [ ], "authors" : [ "Daniel Thomas" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://www.zorba-xquery.com/modules/image/error", "prefix" : "ierr" }, { "uri" : "http://www.zorba-xquery.com/modules/image/image", "prefix" : "img" }, { "uri" : "http://www.zorba-xquery.com/modules/image/paint", "prefix" : "paint" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "paint", "qname" : "paint:paint", "signature" : "($image as xs:base64Binary, $shapes as element(*)*) as xs:base64Binary", "description" : " Extends the passed image with a sequence of shapes.\n The shapes are passed as a sequence of elements.\n The possibilities for shape elements are:\n
      \n
    • line:\n
      \n          <img:line>\n            <img:start><img:x>-20</img:x><img:y>-20</img:y></img:start>\n            <img:end><img:x>80</img:x><img:y>80</img:y></img:end>\n          </img:line>
      \n
    • \n
    • polyline:\n
      \n           <img:polyLine>\n             <img:point><img:x>10</img:x><img:y>10</img:y></img:point>\n             <img:point><img:x>40</img:x><img:y>80</img:y></point>\n             <img:point><img:x>50</img:x><img:y>30</img:y></point>\n             <img:point><img:x>200</img:x><img:y>200</img:y></point>\n           </img:polyLine>\n         
      \n
    • \n
    • stroked polyline:\n
      \n           <img:strokedPolyLine>\n             <img:point><img:x>10</img:x><img:y>10</img:y></img:point>\n             <img:point><img:x>40</img:x><img:y>80</img:y></img:point>\n             <img:point><img:x>50</img:x><img:y>30</img:y></img:point>\n             <img:strokeLength>5</img:strokeLength><img:gapLength>2</img:gapLength>\n           </img:strokedPolyLine>\n         
      \n
    • \n
    • rectangle:\n
      \n           <img:rectangle>\n             <img:upperLeft><img:x>20</img:x><img:y>20</img:y></img:upperLeft>\n             <img:lowerRight><img:x>50</img:x><img:y>50</img:y></img:lowerRight>\n           </img:rectangle>\n         
      \n
    • \n
    • rounded rectangle:\n
      \n           <img:roundedRectangle>\n             <img:upperLeft><img:x>20</img:x><img:y>20</img:y></img:upperLeft>\n             <img:lowerRight><img:x>50</img:x><img:y>50</img:y></img:lowerRight>\n             <img:cornerWidth>10</img:cornerWidth><img:cornerHeight>10</img:cornerHeight>\n           </img:roundedRectangle>\n         
      \n
    • \n
    • circle:\n
      \n           <img:circle>\n             <img:origin><img:x>20</img:x><img:y>20</img:y></img:origin>\n             <img:perimeter>5</img:perimeter>\n           </img:circle>\n         
      \n
    • \n
    • ellipse:\n
      \n           <img:ellipse>\n             <img:origin><img:x>50</img:x><img:y>50</img:y></img:origin>\n             <img:perimeterX>30</img:perimeterX><img:perimeterY>20</img:perimeterY>\n           </img:ellipse>\n         
      \n
    • \n
    • arc:\n
      \n           <img:arc>\n             <img:origin><img:x>50</img:x><img:y>50</img:y></img:origin>\n             <img:perimeterX>10</img:perimeterX><img:perimeterY>20</img:perimeterY>\n             <img:startDegrees>180</img:startDegrees><img:endDegrees>270</img:endDegrees>\n           </img:arc>\n         
      \n
    • \n
    • polygon:\n
      \n           <img:polygon>\n             <img:point><img:x>10</img:x><img:y>10</img:y></img:point>\n             <img:point><img:x>40</img:x><img:y>80</img:y></img:point>\n             <img:point><img:x>50</img:x><img:y>30</img:y></img:point>\n           </img:polygon>\n         
      \n
    • \n
    • text:\n
      \n           <img:text>\n             <img:origin><img:x>20</img:x><img:y>20</img:y></img:origin>\n             <img:text>Hello Zorba</img:text><img:font></img:font><img:font-size>12</img:font-size>\n           </img:text>\n         
      \n
    • \n
    \n Optionally, each of the shape elements can contain elements to define the stroke with, stroke color, fill color, and anti-aliasing.\n E.g.:\n

    \n

    \n     <img:rectangle>\n       <img:strokeWidth>5</img:strokeWidth>\n       <img:strokeColor>#00AF00</img:strokeColor>\n       <img:fillColor>#A10000</img:fillColor>\n       <img:antiAliasing>true</img:antiAliasing>\n       <img:upperLeft><img:x>20</img:x><img:y>20</img:y></img:upperLeft>\n       <img:lowerRight><img:x>50</img:x><img:y>50</img:y></img:lowerRight>\n     </img:rectangle>\n   
    \n

    \n", "summary" : "

    Extends the passed image with a sequence of shapes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the passed image
    " }, { "name" : "shapes", "type" : "element(*)", "occurrence" : "*", "description" : "
    the shapes
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "image with additional shapes" }, "errors" : [ "ierr:IM001 the passed image is invalid.", "err:FORG0001 one of the passed shape elements is invalid." ] } ], "variables" : [ ] }, "http://zorba.io/modules/fetch" : { "ns" : "http://zorba.io/modules/fetch", "description" : "

    This module provides functions to fetch the content of a resource identified\n by a URI. For example, it fetches the content of file or http resources.

    \n

    In order to retrieve such content, the functions use the\n URI resolution and URL resolver process as documented at\n \n URI Resolvers.

    \n", "sees" : [ ], "authors" : [ "Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://zorba.io/modules/fetch", "prefix" : "fetch" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "content-binary", "qname" : "fetch:content-binary", "signature" : "($uri as xs:string) as xs:base64Binary", "description" : "

    Tries to fetch the resource referred to by the given URI and\n returning it as base64Binary.

    \n

    It queries all URI mappers and resolvers with kind\n EntityData::SOME_CONTENT.

    \n", "summary" : "

    Tries to fetch the resource referred to by the given URI and\n returning it as base64Binary.

    ", "annotation_str" : " %an:streamable", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "streamable", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    the resource to fetch.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the resource referred to by the given URI as streamble base64Binary." }, "errors" : [ "uri:URI_UNRESOLVED_OR_NOSTREAM if the URI could not be resolved or did not resolve to a StreamResource." ] }, { "isDocumented" : true, "arity" : 2, "name" : "content-binary", "qname" : "fetch:content-binary", "signature" : "($uri as xs:string, $entity-kind as xs:string) as xs:base64Binary external", "description" : "

    Tries to fetch the resource referred to by the given URI and\n returning it as base64Binary.

    \n

    It queries all URI mappers and resolvers with kind the specified\n entity kind.

    \n", "summary" : "

    Tries to fetch the resource referred to by the given URI and\n returning it as base64Binary.

    ", "annotation_str" : " %an:streamable", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "streamable", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    the resource to fetch.
    " }, { "name" : "entity-kind", "type" : "xs:string", "occurrence" : null, "description" : "
    the kind of resource to fetch.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the resource referred to by the given URI as streamble base64Binary." }, "errors" : [ "uri:URI_UNRESOLVED_OR_NOSTREAM if the URI could not be resolved or did not resolve to a StreamResource." ] }, { "isDocumented" : true, "arity" : 1, "name" : "content", "qname" : "fetch:content", "signature" : "($uri as xs:string) as xs:string", "description" : "

    Tries to fetch the resource referred to by the given URI.

    \n

    It queries all URI mappers and resolvers with kind\n EntityData::SOME_CONTENT.

    \n

    The content is assumed to be UTF-8 encoded.

    \n", "summary" : "

    Tries to fetch the resource referred to by the given URI.

    ", "annotation_str" : " %an:streamable", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "streamable", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    the resource to fetch.
    " } ], "returns" : { "type" : "xs:string", "description" : "the resource referred to by the given URI as streamble string." }, "errors" : [ "uri:URI_UNRESOLVED_OR_NOSTREAM if the URI could not be resolved or did not resolve to a StreamResource." ] }, { "isDocumented" : true, "arity" : 2, "name" : "content", "qname" : "fetch:content", "signature" : "($uri as xs:string, $entity-kind as xs:string) as xs:string", "description" : "

    Tries to fetch the resource referred to by the given URI.

    \n

    It queries all URI mappers and resolvers with kind the specified\n entity kind.

    \n

    The content is assumed to be UTF-8 encoded.

    \n", "summary" : "

    Tries to fetch the resource referred to by the given URI.

    ", "annotation_str" : " %an:streamable", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "streamable", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    the resource to fetch.
    " }, { "name" : "entity-kind", "type" : "xs:string", "occurrence" : null, "description" : "
    the kind of resource to fetch.
    " } ], "returns" : { "type" : "xs:string", "description" : "the resource referred to by the given URI as streamble string." }, "errors" : [ "uri:URI_NOT_RESOLVED_OR_NOSTREAM if the URI could not be resolved or did not resolve to a StreamResource." ] }, { "isDocumented" : true, "arity" : 3, "name" : "content", "qname" : "fetch:content", "signature" : "($uri as xs:string, $entity-kind as xs:string, $encoding as xs:string) as xs:string external", "description" : "

    Tries to fetch the resource referred to by the given URI.

    \n

    It queries all URI mappers and resolvers with kind the specified\n entity kind.

    \n", "summary" : "

    Tries to fetch the resource referred to by the given URI.

    ", "annotation_str" : " %an:streamable", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "streamable", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    the resource to fetch.
    " }, { "name" : "entity-kind", "type" : "xs:string", "occurrence" : null, "description" : "
    the kind of resource to fetch.
    " }, { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "
    the encoding of the content
    " } ], "returns" : { "type" : "xs:string", "description" : "the resource referred to by the given URI as streamble string." }, "errors" : [ "uri:URI_UNRESOLVED_OR_NOSTREAM if the URI could not be resolved or did not resolve to a StreamResource.", "uri:CHARSET_UNKNOWN if the given encoding is invalid or not supported." ] } ], "variables" : [ ] }, "http://xbrl.io/modules/bizql/concept-maps" : { "ns" : "http://xbrl.io/modules/bizql/concept-maps", "description" : "

    This module provides functions for storing, retrieving, and modifying\n concept maps. Concept maps can be used in BizQL queries.

    \n

    A concept map is a network of concepts that can be contained in a report schema.\n It maps \"virtual\" concepts to reported concepts, which allows comparison across\n archives that use different vocabularies (so-called extension facts).

    \n

    With this module, you can retrieve the concept map associated with each report\n schema. You can also query for facts by making implicitly use of the mapping.

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/archives", "prefix" : "archives" }, { "uri" : "http://xbrl.io/modules/bizql/concept-maps", "prefix" : "concept-maps" }, { "uri" : "http://xbrl.io/modules/bizql/facts", "prefix" : "facts" }, { "uri" : "http://xbrl.io/modules/bizql/networks", "prefix" : "networks" }, { "uri" : "http://xbrl.io/modules/bizql/report-schemas", "prefix" : "report-schemas" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "concept-maps", "qname" : "concept-maps:concept-maps", "signature" : "() as object()*", "description" : "

    Retrieves all concept maps.

    \n", "summary" : "

    Retrieves all concept maps.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()*", "description" : "all concept maps." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "concept-maps", "qname" : "concept-maps:concept-maps", "signature" : "($report-schemas-or-ids as item()*) as object()*", "description" : "

    Return the concept maps from the given report schemas.

    \n", "summary" : "

    Return the concept maps from the given report schemas.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "report-schemas-or-ids", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "the concept maps from the report schemas." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "facts-for-archives-and-concepts", "qname" : "concept-maps:facts-for-archives-and-concepts", "signature" : "($archive-or-ids as item()*, $concepts as string*, $concept-maps as object()*) as object()*", "description" : "

    Resolves the supplied concepts according to the supplied concept map.

    \n", "summary" : "

    Resolves the supplied concepts according to the supplied concept map.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or AIDs (or $concept-maps:ALL_OF_THEM to do no filter on archives).
    " }, { "name" : "concepts", "type" : "string", "occurrence" : "*", "description" : "
    a sequence of concept names (or $concept-maps:ALL_OF_THEM to do no filter on concepts).
    " }, { "name" : "concept-maps", "type" : "object()", "occurrence" : "*", "description" : "
    a sequence of concept maps.
    " } ], "returns" : { "type" : "object()*", "description" : "the resolved facts, with the concept name overriden with the new name." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "facts-for-archives-and-concepts", "qname" : "concept-maps:facts-for-archives-and-concepts", "signature" : "($archive-or-ids as item()*, $concepts as string*, $concept-maps as object()+, $options as object()?) as object()*", "description" : "

    Resolves the supplied concepts according to the supplied concept map.

    \n", "summary" : "

    Resolves the supplied concepts according to the supplied concept map.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or AIDs (or $concept-maps:ALL_OF_THEM to do no filter on archives).
    " }, { "name" : "concepts", "type" : "string", "occurrence" : "*", "description" : "
    a sequence of concept names (or $concept-maps:ALL_OF_THEM to do no filter on concepts).
    " }, { "name" : "concept-maps", "type" : "object()", "occurrence" : "+", "description" : "
    a sequence of concept maps.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "the resolved facts, with the concept name overriden with the new name." }, "errors" : [ ] } ], "variables" : [ { "name" : "concept-maps:ALL_OF_THEM", "type" : "boolean", "description" : " Joker for all archives or all concepts.\n" } ] }, "http://www.28msec.com/modules/http/cookie" : { "ns" : "http://www.28msec.com/modules/http/cookie", "description" : " The Sausalito Cookie module provides function to manipulate\n HTTP-Cookies.\n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/http/cookie", "prefix" : "cookie" }, { "uri" : "http://www.28msec.com/modules/http/cookie", "prefix" : "cookie-schema" }, { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "req" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "resp" }, { "uri" : "http://zorba.io/modules/schema", "prefix" : "schema" }, { "uri" : "http://www.zorba-xquery.com/modules/cryptography/hmac", "prefix" : "sec" }, { "uri" : "http://zorba.io/modules/uri", "prefix" : "uri" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "create-session", "qname" : "cookie:create-session", "signature" : "($sessionData as node()) as empty-sequence()", "description" : " Creates a client-side cookie named \"_session\", containing the\n $sessionData node value together with its signature.\n The signature is generated with the server's private key.\n", "summary" : "

    Creates a client-side cookie named \"_session\", containing the\n $sessionData node value together with its signature.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "sessionData", "type" : "node()", "occurrence" : null, "description" : "
    The data to be used for the session.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The empty-sequence is returned." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "create-session", "qname" : "cookie:create-session", "signature" : "($sessionData as node(), $expires as xs:dateTime) as empty-sequence()", "description" : " Creates a client-side cookie named \"_session\", containing the\n $sessionData node value together with its signature.\n The signature is generated with the server's private key.\n The cookie is also set to expire on the date specified by\n $expires.\n", "summary" : "

    Creates a client-side cookie named \"_session\", containing the\n $sessionData node value together with its signature.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "sessionData", "type" : "node()", "occurrence" : null, "description" : "
    The data to be used for the session.
    " }, { "name" : "expires", "type" : "xs:dateTime", "occurrence" : null, "description" : "
    The expiration time of the cookie.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The empty-sequence is returned." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "create-session", "qname" : "cookie:create-session", "signature" : "($sessionData as node(), $expires as xs:dateTime?, $path as xs:string?) as empty-sequence()", "description" : " Creates a client-side cookie named \"_session\", containing the\n $sessionData node value together with its signature.\n The signature is generated with the server's private key.\n The cookie is also set to expire on the date specified by\n $expires. The cookie is only valid for the specified path.\n", "summary" : "

    Creates a client-side cookie named \"_session\", containing the\n $sessionData node value together with its signature.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "sessionData", "type" : "node()", "occurrence" : null, "description" : "
    The data to be used for the session.
    " }, { "name" : "expires", "type" : "xs:dateTime", "occurrence" : "?", "description" : "
    The expiration time of the cookie.
    " }, { "name" : "path", "type" : "xs:string", "occurrence" : "?", "description" : "
    The path of the URL for which the cookie is valid.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The empty-sequence is returned." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "delete-session", "qname" : "cookie:delete-session", "signature" : "() as empty-sequence()", "description" : " Delete the \"_session\" cookie from the client. The next\n user request will not receive a valid session cookie\n anymore\n", "summary" : "

    Delete the \"_session\" cookie from the client.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "empty-sequence()", "description" : "The empty-sequence is returned." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "delete-session", "qname" : "cookie:delete-session", "signature" : "($path as xs:string?) as empty-sequence()", "description" : " Delete the \"_session\" cookie from the client. The next\n user request will not receive a valid session cookie\n anymore\n", "summary" : "

    Delete the \"_session\" cookie from the client.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "path", "type" : "xs:string", "occurrence" : "?", "description" : "
    The path of the URL for which the cookie is valid.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The empty-sequence is returned." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "get", "qname" : "cookie:get", "signature" : "($name as xs:string?) as element(cookie:cookie)*", "description" : " Returns the cookie in the request having the given name or the empty sequence\n if no such cookie exists. The cookie format returned is:\n \n <cookie:cookie\n name=\"..\">...</cookie:cookie>.\n The content of the cookie element is the value of the cookie.\n", "summary" : "

    Returns the cookie in the request having the given name or the empty sequence\n if no such cookie exists.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : "?", "description" : "
    The name of the cookie that should be retrieved.
    " } ], "returns" : { "type" : "element(cookie:cookie)*", "description" : "The cookie with the given name or the empty sequence if no cookie with the given name exist" }, "errors" : [ "cookie:S003 if $decode evaluates to fn:true() and the value of the cookie cannot be parsed." ] }, { "isDocumented" : true, "arity" : 2, "name" : "get", "qname" : "cookie:get", "signature" : "($name as xs:string?, $decode as xs:boolean) as element(cookie:cookie)*", "description" : " Returns the cookies in the request having the given name. If no name is given,\n it returns all available cookies. If no cookie value decoding is wanted,\n the user must specify a second argument that evaluates to fn:false().\n", "summary" : "

    Returns the cookies in the request having the given name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : "?", "description" : "
    The name of the cookie that should be retrieved
    " }, { "name" : "decode", "type" : "xs:boolean", "occurrence" : null, "description" : "
    Boolean to specify if cookie value decoding id needed
    " } ], "returns" : { "type" : "element(cookie:cookie)*", "description" : "The cookie with the given name or the empty sequence if no cookie with the given name exist" }, "errors" : [ "cookie:S003 if $decode evaluates to fn:true() and the value of the cookie cannot be parsed." ] }, { "isDocumented" : true, "arity" : 0, "name" : "session-data", "qname" : "cookie:session-data", "signature" : "() as node()", "description" : " Reads the \"_session\" cookie in the request and verifies if the signature\n matches the ad-hoc computed signature of the content of the session. If the\n verification is successful, the function returns the session data. Otherwise,\n an error is raised.\n", "summary" : "

    Reads the \"_session\" cookie in the request and verifies if the signature\n matches the ad-hoc computed signature of the content of the session.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "node()", "description" : "The session data is returned if verification succesful." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "set", "qname" : "cookie:set", "signature" : "($cookie as element(cookie:cookie)) as empty-sequence()", "description" : " Adds a Set-Cookie header to the response. This function is equivalent to\n cookie:set($cookie, fn:true()).\n", "summary" : "

    Adds a Set-Cookie header to the response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "cookie", "type" : "element(cookie:cookie)", "occurrence" : null, "description" : "
    The XML representation of the cookie to be sent to the client.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The empty-sequence is returned." }, "errors" : [ "cookie:S002 if the cookie is bigger than 4096 bytes." ] }, { "isDocumented" : true, "arity" : 2, "name" : "set", "qname" : "cookie:set", "signature" : "($cookie as element(cookie:cookie), $encode as xs:boolean) as empty-sequence()", "description" : " Adds a Set-Cookie header to the response.\n The cookie parameter needs to adhere to the cookie schema. For example,\n \n <cookie:cookie\n name=\"xs:string\"\n expires=\"xs:datetime\"\n domain=\"xs:string\"\n path=\"xs:string\"\n secure=\"xs:boolean\">value</cookie:cookie>\n .\n If the cookie parameter is not valid according to the schema, err:XQDY0027 is raised.\n If $encode evaluates to fn:true(), then the child nodes of the cookie element will be\n serialized using XML serialization (omitting the XML declaration). In order not to\n break the cookie syntax, any occurence of whitespace or column in the value will be\n encoded on the client using the URL encoding format. For this reason also the '%'\n character will be encoded using the same format.\n If $encode evaluates to fn:false(), the children nodes of the cookie element will be\n serialized as text and no encoding will be performed whatsoever. It is the\n responsibility of the caller to make sure the text serialization will not produce an\n invalid cookie.\n", "summary" : "

    Adds a Set-Cookie header to the response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "cookie", "type" : "element(cookie:cookie)", "occurrence" : null, "description" : "
    The cookie to send to the client
    " }, { "name" : "encode", "type" : "xs:boolean", "occurrence" : null, "description" : "
    if encoding should be performed on the value or not
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The empty-sequence is returned." }, "errors" : [ "cookie:S002 if the cookie is bigger than 4096 bytes." ] }, { "isDocumented" : true, "arity" : 0, "name" : "validate-session", "qname" : "cookie:validate-session", "signature" : "() as xs:boolean", "description" : " Reads the \"_session\" cookie in the request and verifies if\n the signature matches the ad-hoc computed signature of the\n content of the session. The signature is generated with a\n server private key. If no cookie named \"_session\" exists,\n this function returns false.\n", "summary" : "

    Reads the \"_session\" cookie in the request and verifies if\n the signature matches the ad-hoc computed signature of the\n content of the session.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "Returns true if the session is valid, and and false otherwise." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/couchbase" : { "ns" : "http://www.28msec.com/modules/couchbase", "description" : " This module provides functionality to interact with the\n Couchbase NoSQL database.

    \n The module is built using the libcouchbase 2.0 C client library and\n exposes most of its functionality in JSONiq.\n Beyond just allowing for basic key-value store operations (e.g.\n put-/get-text or put-/get-binary, this module also allows to work\n with Couchbase views in order to allow for complex JSON query\n operations.\n", "sees" : [ ], "authors" : [ "Cristi Dumitru" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/couchbase", "prefix" : "cb" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://www.zorba-xquery.com/modules/couchbase", "prefix" : "zcb" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "connect", "qname" : "cb:connect", "signature" : "($options as object()) as anyURI", "description" : " Connect to the Couchbase server.

    \n

    The input to the function is an object that contains the connection\n information. Specifically, it allows for the following options:\n

      \n
    • host: the endpoint of the Couchbase server (mandatory)
    • \n
    • user: the user used for connecting (optional)
    • \n
    • password: the password used for connecting (optional)
    • \n
    • bucket: name of an existing bucket (mandatory)
    • \n

    \n

    Example:\n

    • \n $conn := cb:connect({\n   \"host\" : \"192.168.1.56:8091\",\n   \"username\" : (),\n   \"password\" : (),\n   \"bucket\" : \"default\"\n });\n 

    \n

    The function returns an opaque URI that represents the connection.\n This URI has to be passed to other functions of this module that require\n the $conn parameter as a first argument.

    \n", "summary" : "

    Connect to the Couchbase server.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    a object that contains the host, bucket, and authentication information.
    " } ], "returns" : { "type" : "anyURI", "description" : "an identifier for the established connection." }, "errors" : [ "LCB0001 if the connection to the given host/bucket could not be established.", "CB0001 if mandatory connection information is missing.", "CB0007 if a given option is not supported." ] }, { "isDocumented" : true, "arity" : 4, "name" : "connect", "qname" : "cb:connect", "signature" : "($host as string, $username as string?, $password as string?, $bucket as string) as anyURI", "description" : " Connect to the Couchbase server.

    \n

    The function returns an opaque URI that represents the connection.\n This URI has to be passed to other functions of this module that require\n the $conn parameter as a first argument.

    \n

    Example:\n

    • \n $conn := cb:connect(\"192.168.1.56:8091\", (), (), \"default\");\n 

    \n", "summary" : "

    Connect to the Couchbase server.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host", "type" : "string", "occurrence" : null, "description" : "
    address of the couchbase server (mandatory) \"192.168.1.56:8091\"
    " }, { "name" : "username", "type" : "string", "occurrence" : "?", "description" : "
    username used for the connection
    " }, { "name" : "password", "type" : "string", "occurrence" : "?", "description" : "
    password used for the connection
    " }, { "name" : "bucket", "type" : "string", "occurrence" : null, "description" : "
    name of the bucket to use (mandatory) \"default\"
    " } ], "returns" : { "type" : "anyURI", "description" : "an identifier that represents the connection to the server." }, "errors" : [ "LCB0001 if the connection to the given host/bucket could not be established." ] }, { "isDocumented" : true, "arity" : 3, "name" : "create-view", "qname" : "cb:create-view", "signature" : "($conn as anyURI, $doc-name as string, $view-names as string*) as string*", "description" : " Create a document and views.

    \n If the document already exists, it is replaced.\n A document can hold several views that must be specified in the same call.\n

    Example:\n

    • \n $views := cb:create-view($conn, \"zip\", (\"bystate\", \"bycity\"));\n 

    \n", "summary" : "

    Create a document and views.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "doc-name", "type" : "string", "occurrence" : null, "description" : "
    The name of the document to create
    " }, { "name" : "view-names", "type" : "string", "occurrence" : "*", "description" : "
    The names of the views to create in the document
    " } ], "returns" : { "type" : "string*", "description" : "The paths for the views that have been created." }, "errors" : [ "LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 4, "name" : "create-view", "qname" : "cb:create-view", "signature" : "($conn as anyURI, $doc-name as string, $view-names as string*, $options as object()*) as string*", "description" : " Create a document and views.

    \n If the document already exists, it is replaced.\n A document can hold several views that must be specified in the same call.\n

    In addition, the function allows to specify several options:\n

      \n
    • key: string name of the value that will be used\n as key in the view
    • \n
    • values: string/array name of the value(s) that\n will be used as values in the view
    • \n
    • function: javascript function the map function\n that will create the connection between key and value.
      \n If function is specified, the key and\n values options are ignored.
    • \n

    \n

    Example:\n

    • \n $views := cb:create-view($conn, \"zip\", \"bystate\", { \"key\": \"doc.state\", \"values\" : [\"doc.pop\", \"doc.city\"] });\n 
    • \n
    • \n $views := cb:create-view($conn, \"zip\", \"bycity\", { \"function\": \"function(doc, meta) {  emit(doc.state, null); }\"});\n 

    \n", "summary" : "

    Create a document and views.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "doc-name", "type" : "string", "occurrence" : null, "description" : "
    The name of the document to create
    " }, { "name" : "view-names", "type" : "string", "occurrence" : "*", "description" : "
    The names of the views to create in the document
    " }, { "name" : "options", "type" : "object()", "occurrence" : "*", "description" : "
    An object with additional options
    " } ], "returns" : { "type" : "string*", "description" : "The paths for the views that have been created." }, "errors" : [ "LCB0002 if any error occurs in the communication with the server.", "CB0005 if the number of options doesn't match the number of view-names.", "CB0007 if any of the options is not supported.", "CB0010 if any of the given options has an invalid type." ] }, { "isDocumented" : true, "arity" : 2, "name" : "delete-view", "qname" : "cb:delete-view", "signature" : "($conn as anyURI, $doc as string*) as string*", "description" : " Delete a document and its views.

    \n If the document doesn't exists, the function does nothing.\n All the views hold in the document are deleted.\n

    Example:\n

    • \n cb:delete-view($conn, \"zip\");\n 

    \n", "summary" : "

    Delete a document and its views.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "doc", "type" : "string", "occurrence" : "*", "description" : "
    -name The name of the document to delete
    " } ], "returns" : { "type" : "string*", "description" : "a empty sequence." }, "errors" : [ "LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 1, "name" : "flush", "qname" : "cb:flush", "signature" : "($conn as anyURI) as empty-sequence()", "description" : " Remove all values and their keys.

    \n

    Example:\n

    • \n cb:flush($conn);\n 

    \n", "summary" : "

    Remove all values and their keys.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 2, "name" : "get-binary", "qname" : "cb:get-binary", "signature" : "($conn as anyURI, $key as string*) as base64Binary*", "description" : " Retrieve the values matching the given string keys, as base64Binary.

    \n

    Example:\n

    • \n $result := cb:get-binary($conn, \"image\");\n 

    \n", "summary" : "

    Retrieve the values matching the given string keys, as base64Binary.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "key", "type" : "string", "occurrence" : "*", "description" : "
    The requested keys
    " } ], "returns" : { "type" : "base64Binary*", "description" : "A sequence of base64Binary values corresponding to the keys" }, "errors" : [ "LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 3, "name" : "get-binary", "qname" : "cb:get-binary", "signature" : "($conn as anyURI, $key as string*, $options as object()) as base64Binary*", "description" : " Retrieve the values matching the given string keys, as base64Binary.

    \n

    In addition, the function allows to specify several options:\n

      \n
    • expiration-time: integer value for refreshing the\n expiration time in seconds\n (default 0, which means values are kept indefinitely)
    • \n

    \n

    Example:\n

    • \n $result := cb:get-binary($conn, \"image\",{ \"expiration-time\" : 60 * 60 });\n 

    \n", "summary" : "

    Retrieve the values matching the given string keys, as base64Binary.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "key", "type" : "string", "occurrence" : "*", "description" : "
    The requested keys
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object with additional options
    " } ], "returns" : { "type" : "base64Binary*", "description" : "A sequence of base64Binary values corresponding to the keys" }, "errors" : [ "LCB0002 if any error occurs in the communication with the server.", "CB0007 if any of the options is not supported.", "CB0009 if the given expiration time is not an integer." ] }, { "isDocumented" : true, "arity" : 2, "name" : "get-text", "qname" : "cb:get-text", "signature" : "($conn as anyURI, $key as string*) as string*", "description" : " Retrieve the values matching the given string keys, as string.

    \n

    Example:\n

    • \n $result := cb:get-text($conn, \"35040\");\n 

    \n", "summary" : "

    Retrieve the values matching the given string keys, as string.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "key", "type" : "string", "occurrence" : "*", "description" : "
    The requested keys
    " } ], "returns" : { "type" : "string*", "description" : "A sequence of string values corresponding to the keys" }, "errors" : [ "LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 3, "name" : "get-text", "qname" : "cb:get-text", "signature" : "($conn as anyURI, $key as string*, $options as object()) as string*", "description" : " Retrieve the values matching the given string keys, as string.

    \n

    In addition, the function allows to specify several options:\n

      \n
    • expiration-time: integer value for refreshing the\n expiration time in seconds\n (default 0, which means values are kept indefinitely)
    • \n
    • encoding: string name of the encoding of the\n returned string (default UTF-8)
    • \n

    \n

    Example:\n

    • \n $result := cb:get-text($conn, \"35040\", { \"encoding\" : \"ASCII\" } );\n 

    \n", "summary" : "

    Retrieve the values matching the given string keys, as string.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "key", "type" : "string", "occurrence" : "*", "description" : "
    The requested key
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object with additional options
    " } ], "returns" : { "type" : "string*", "description" : "A sequence of string values corresponding to the keys" }, "errors" : [ "LCB0002 if any error occurs in the communication with the server.", "CB0006 if the given encoding is not supported.", "CB0007 if any of the options is not supported.", "CB0009 if the given expiration time is not an integer." ] }, { "isDocumented" : true, "arity" : 3, "name" : "put-binary", "qname" : "cb:put-binary", "signature" : "($conn as anyURI, $key as string*, $value as base64Binary*) as empty-sequence()", "description" : " Store base64binary values along with their string keys.

    \n

    Example:\n

    • \n cb:put-binary($conn, \"image\",\n   http:get-binary(\"http://localhost:8091/images/couchbase_logo.png\")[2]);\n 

    \n", "summary" : "

    Store base64binary values along with their string keys.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "key", "type" : "string", "occurrence" : "*", "description" : "
    The keys to store
    " }, { "name" : "value", "type" : "base64Binary", "occurrence" : "*", "description" : "
    The base64 binary values to be stored
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "LCB0002 if any error occurs in the communication with the server.", "CB0005 if the number of keys doesn't match the number of values." ] }, { "isDocumented" : true, "arity" : 4, "name" : "put-binary", "qname" : "cb:put-binary", "signature" : "($conn as anyURI, $key as string*, $value as base64Binary*, $options as object()) as empty-sequence()", "description" : " Store base64Binary values along with their string keys.

    \n

    In addition, the function allows to specify several options:\n

      \n
    • expiration-time: integer value for refreshing the\n expiration time in seconds\n (default 0, which means values are kept indefinitely)
    • \n
    • operation: add/replace/set/append/prepend type of\n operation
    • \n
    • wait: persist/false if the system should wait for\n persistence of the keys
    • \n

    \n

    Example:\n

    • \n cb:put-binary($conn, \"image\",\n   http:get-binary(\"http://localhost:8091/images/couchbase_logo.png\")[2],\n   { \"expiration-time\" : 60 * 60 * 24 });\n 

    \n", "summary" : "

    Store base64Binary values along with their string keys.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "key", "type" : "string", "occurrence" : "*", "description" : "
    The keys to store
    " }, { "name" : "value", "type" : "base64Binary", "occurrence" : "*", "description" : "
    The base64Binary values to be stored
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object with additional options
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "LCB0002 if any error occurs in the communication with the server.", "CB0005 if the number of keys doesn't match the number of values.", "CB0007 if any of the options is not supported.", "CB0009 if the given expiration time is not an integer.", "CB0011 if the stored Variable was not stored" ] }, { "isDocumented" : true, "arity" : 3, "name" : "put-text", "qname" : "cb:put-text", "signature" : "($conn as anyURI, $key as string*, $value as string*) as empty-sequence()", "description" : " Store string values along with their string keys.

    \n The values are stored with the UTF-8 encoding and a default\n expiration time 0.\n

    Example:\n

    • \n cb:put-text($conn, \"35040\", fn:serialize({\n                      \"city\" : \"CALERA\",\n                      \"loc\" : [ -86.755987, 33.1098 ],\n                      \"pop\" : 4675,\n                      \"state\" : \"AL\",\n                      \"_id\" : \"35040\"\n                    }));\n 

    \n", "summary" : "

    Store string values along with their string keys.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "key", "type" : "string", "occurrence" : "*", "description" : "
    The keys to store
    " }, { "name" : "value", "type" : "string", "occurrence" : "*", "description" : "
    The string values to be stored.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "LCB0002 if any error occurs in the communication with the server.", "CB0005 if the number of keys doesn't match the number of values." ] }, { "isDocumented" : true, "arity" : 4, "name" : "put-text", "qname" : "cb:put-text", "signature" : "($conn as anyURI, $key as string*, $value as string*, $options as object()) as empty-sequence()", "description" : " Store string values along with their string keys.

    \n

    In addition, the function allows to specify several options:\n

      \n
    • expiration-time: integer value for refreshing the\n expiration time in seconds\n (default 0, which means values are kept indefinitely)
    • \n
    • encoding: string name of the encoding of the\n returned string (default UTF-8)
    • \n
    • operation: add/replace/set/append/prepend type\n of operation
    • \n
    • wait: persist/false if the system should wait for\n persistence of the keys
    • \n

    \n

    Example:\n

    • \n cb:put-text($conn, \"35040\", fn:serialize({\n                      \"city\" : \"CALERA\",\n                      \"loc\" : [ -86.755987, 33.1098 ],\n                      \"pop\" : 4675,\n                      \"state\" : \"AL\",\n                      \"_id\" : \"35040\"\n                    }), { \"expiration-time\" : 60 * 60 * 24 });\n 

    \n", "summary" : "

    Store string values along with their string keys.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "key", "type" : "string", "occurrence" : "*", "description" : "
    The keys to store
    " }, { "name" : "value", "type" : "string", "occurrence" : "*", "description" : "
    The string values to be stored
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object with additional options
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "LCB0002 if any error occurs in the communication with the server.", "CB0005 if the number of keys doesn't match the number of values.", "CB0006 if the given encoding is not supported.", "CB0007 if any of the options is not supported.", "CB0009 if the given expiration time is not an integer.", "CB0011 if the stored Variable was not stored" ] }, { "isDocumented" : true, "arity" : 2, "name" : "remove", "qname" : "cb:remove", "signature" : "($conn as anyURI, $key as string*) as empty-sequence()", "description" : " Remove the values matching the given string keys.

    \n

    Example:\n

    • \n cb:remove($conn, \"35040\");\n 

    \n", "summary" : "

    Remove the values matching the given string keys.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "key", "type" : "string", "occurrence" : "*", "description" : "
    The requested keys to have their values removed
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 3, "name" : "touch", "qname" : "cb:touch", "signature" : "($conn as anyURI, $key as string*, $exp-time as integer) as empty-sequence()", "description" : " Refresh the expiration time of the given string keys.

    \n

    Example:\n

    • \n cb:touch($conn, \"35040\", 60 * 60 * 24);\n 

    \n", "summary" : "

    Refresh the expiration time of the given string keys.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "key", "type" : "string", "occurrence" : "*", "description" : "
    The keys to touch
    " }, { "name" : "exp-time", "type" : "integer", "occurrence" : null, "description" : "
    New expiration time in seconds
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 2, "name" : "view", "qname" : "cb:view", "signature" : "($conn as anyURI, $path as string*) as object()*", "description" : " Retrieve the content of existing views.

    \n

    Example:\n

    • \n $results := cb:view($conn, \"_design/zip/_view/bystate\");\n 

    \n", "summary" : "

    Retrieve the content of existing views.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "path", "type" : "string", "occurrence" : "*", "description" : "
    The view path
    " } ], "returns" : { "type" : "object()*", "description" : "information about the view" }, "errors" : [ "LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 3, "name" : "view", "qname" : "cb:view", "signature" : "($conn as anyURI, $path as string*, $options as object()) as object()*", "description" : " Retrieve the content of existing views.

    \n

    Example:\n

    • \n $results := cb:view($conn, \"_design/zip/_view/bystate\", { \"limit\": 100 });\n 

    \n

    In addition, the function allows to specify several options:\n

      \n
    • encoding: string name of the encoding of the\n returned string (default UTF-8)
    • \n
    • stale: if the system should wait for persistence of the keys\n
        \n
      • ok the view is not updated
      • \n
      • false the view is updated before the function view is\n executed, this options needs the key to be on disk before the call of\n the function.
      • \n
      • update_after the view is updated after the call\n of the function.
      • \n
    • \n
    • limit: integer how many rows qill be shown\n (default all)
    • \n

    \n", "summary" : "

    Retrieve the content of existing views.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection
    " }, { "name" : "path", "type" : "string", "occurrence" : "*", "description" : "
    The view path \"_design/test/_view/vies\"
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object with additional options
    " } ], "returns" : { "type" : "object()*", "description" : "information about the view" }, "errors" : [ "LCB0002 if any error occurs in the communication with the server.", "CB0007 if any of the options is not supported." ] } ], "variables" : [ ] }, "http://zorba.io/modules/random" : { "ns" : "http://zorba.io/modules/random", "description" : " This module provides several functions for generating (pseudo-)random\n numbers and strings.\n", "sees" : [ ], "authors" : [ "Matthias Brantner, Sorin Nasoi" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://zorba.io/modules/random", "prefix" : "r" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "random-between", "qname" : "r:random-between", "signature" : "($lower as integer, $upper as integer) as integer", "description" : "

    This function generates one random number within a given range.\n The function is nondeterministic.

    \n

    The function is based on r:random-between#3.\n Specifically, it returns the value of invoking\n r:random-betwen($lower, $upper, 1).

    \n", "summary" : "

    This function generates one random number within a given range.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "lower", "type" : "integer", "occurrence" : null, "description" : "
    the lower bound for the random number
    " }, { "name" : "upper", "type" : "integer", "occurrence" : null, "description" : "
    the upper bound for the random number
    " } ], "returns" : { "type" : "integer", "description" : "a random integer within the given range" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "random-between", "qname" : "r:random-between", "signature" : "($lower as integer, $upper as integer, $num as integer) as integer*", "description" : "

    This function generates an arbitrary number of random numbers\n within a given range. The function is nondeterministic because\n the sequence is not repeatable.

    \n", "summary" : "

    This function generates an arbitrary number of random numbers\n within a given range.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "lower", "type" : "integer", "occurrence" : null, "description" : "
    the lower bound for every value within the sequence
    " }, { "name" : "upper", "type" : "integer", "occurrence" : null, "description" : "
    the upper bound for every value within the sequence
    " }, { "name" : "num", "type" : "integer", "occurrence" : null, "description" : "
    the length of the sequence returned
    " } ], "returns" : { "type" : "integer*", "description" : "$num pseudo-random integers within (and including) the range specified by $lower and $upper. It returns $num-times $lower if $lower is equal to $upper and the empty sequence if $num is negative." }, "errors" : [ "r:INVALID_ARGUMENT if $lower is greater than $upper" ] }, { "isDocumented" : true, "arity" : 0, "name" : "random", "qname" : "r:random", "signature" : "() as integer", "description" : "

    This function generates one random number.\n The function is nondeterministic.

    \n

    The function is based on r:random#1. Specifically, it\n returns the value of invoking r:random(1).

    \n", "summary" : "

    This function generates one random number.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "integer", "description" : "a random integer" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "random", "qname" : "r:random", "signature" : "($num as integer) as integer* external", "description" : "

    This function generates an arbitrary number of random numbers.\n The function is nondeterministic because the sequence is\n not repeatable.

    \n

    However, the function is based on posix function srand() and\n rand(). Specifically, it invokes srand()\n with some random number based on the current time\n and then returns the values returned by invoking\n rand() $num-times.

    \n", "summary" : "

    This function generates an arbitrary number of random numbers.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "num", "type" : "integer", "occurrence" : null, "description" : "
    the length of the sequence returned
    " } ], "returns" : { "type" : "integer*", "description" : "$num random integers, or the empty sequence if $num is negative." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "seeded-random-between", "qname" : "r:seeded-random-between", "signature" : "($seed as integer, $lower as integer, $upper as integer, $num as integer) as integer*", "description" : "

    This function generates an arbitrary number of pseudo-random numbers\n within a given range. The sequence is repeatable by calling the\n function with the same seed and boundaries.

    \n

    The function is based on the function r:seeded-random#2.\n Specifically, its result is repeatable if called with the\n same arguments.

    \n", "summary" : "

    This function generates an arbitrary number of pseudo-random numbers\n within a given range.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seed", "type" : "integer", "occurrence" : null, "description" : "
    the initial seed value for the sequence
    " }, { "name" : "lower", "type" : "integer", "occurrence" : null, "description" : "
    the lower bound for every value within the sequence
    " }, { "name" : "upper", "type" : "integer", "occurrence" : null, "description" : "
    the upper bound for every value within the sequence
    " }, { "name" : "num", "type" : "integer", "occurrence" : null, "description" : "
    the length of the sequence returned
    " } ], "returns" : { "type" : "integer*", "description" : "$num pseudo-random integers within (and including) the range specified by $lower and $upper. It returns $num-times $lower if $lower is equal to $upper and the empty sequence if $num is negative." }, "errors" : [ "zerr:ZQXD0004 if the given seed is negative or great than the max value of unsigned int on the given platform.", "r:INVALID_ARGUMENT if $lower is greater than $upper" ] }, { "isDocumented" : true, "arity" : 2, "name" : "seeded-random", "qname" : "r:seeded-random", "signature" : "($seed as integer, $num as integer) as integer* external", "description" : "

    This function generates an arbitrary number of pseudo-random numbers.\n The sequence is repeatable by calling the function with the same\n seed.

    \n

    The function is based on posix function srand() and\n rand(). Specifically, it invokes srand($seed)\n and then returns the values returned by invoking rand()\n $num-times.

    \n

    Sequences returned by this function are not thread-safe (i.e.\n if multiple XQuery programs invoking this function are executed\n concurrently in several threads). This is because the function is\n based on srand() and rand().

    \n", "summary" : "

    This function generates an arbitrary number of pseudo-random numbers.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seed", "type" : "integer", "occurrence" : null, "description" : "
    the initial seed value for the sequence
    " }, { "name" : "num", "type" : "integer", "occurrence" : null, "description" : "
    the length of the sequence returned
    " } ], "returns" : { "type" : "integer*", "description" : "$num pseudo-random integers, or the empty sequence if $num is negative." }, "errors" : [ "zerr:ZQXD0004 if the given seed is negative or great than the max value of unsigned int on the given platform." ] }, { "isDocumented" : true, "arity" : 0, "name" : "uuid", "qname" : "r:uuid", "signature" : "() as string external", "description" : "

    This function returns a uuid.

    \n

    Note, that the function is not stable,\n that is, it returns a different UUID everytime the function is invoked.

    \n", "summary" : "

    This function returns a uuid.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "string", "description" : "the generated UUID as string" }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/http-client" : { "ns" : "http://www.zorba-xquery.com/modules/http-client", "description" : "

    Introduction

    \n

    \n This module provides provides simple functions for performing HTTP requests\n (GET, POST, DELETE etc.), as well as a more flexible general\n purpose function (send-request()).\n

    \n

    Examples of how to use this module

    \n

    Simple GET Request

    \n
    \n import module namespace http=\"http://www.zorba-xquery.com/modules/http-client\";\n declare namespace svg=\"http://www.w3.org/2000/svg\";\n http:get(\"http://www.w3.org/Graphics/SVG/svglogo.svg\")[2]/svg:svg/svg:title\n 
    \n

    \n This example downloads an XML resource from the web (in this case,\n an SVG file, which is an XML-based image format) and returns it as\n a document node. Since the XML is in a namespace, we declare that\n namespace; we can then perform a path expression directly on the\n return value of http:get().\n

    \n

    Simple GET Request (retrieving XHTML)

    \n
    \n   import module namespace http=\"http://www.zorba-xquery.com/modules/http-client\";\n   declare namespace xhtml=\"http://www.w3.org/1999/xhtml\";\n   http:get-node( \"http://www.w3.org\" )[2]//xhtml:body\n   
    \n

    \n This example shows how to retrieve an XHTML resource. XHTML is\n XML, so the http:get-node() function will return it as a document node\n and you can operate on it with the full power of XQuery. As above, since this\n XML is in a particular namespace, the above query defines that namespace\n with the prefix \"xhtml\" so it can easily perform path expressions, etc.\n

    \n

    \n Note: many webservers, include www.w3.org, return XHTML with the\n HTTP Content-Type \"text/html\". Zorba cannot assume that \"text/html\"\n is actually XHTML, and so http:get() would have returned raw text\n rather than a document node. That is why the example above uses\n http:get-node(), which overrides the server's Content-Type and tells\n Zorba to attempt to parse the result as XML.\n

    \n

    Simple GET Request (retrieving HTML as text)

    \n

    \n Note that XQuery does not understand plain HTML, and so if the URL\n you retrieve contains plain HTML data (not XHTML), it will be treated as\n plain text as shown in the next example. If you want to operate on the HTML\n with XQuery, you should use the HTML language module which can transform\n HTML to XHTML. The HTML module is supported by the Zorba team, but it is\n not a \"core module\", meaning that it is not shipped with every Zorba\n installation and may not be available. See\n the Zorba downloads\n page for information about obtaining this module if you do not\n have it.

    \n
    \n import module namespace http=\"http://www.zorba-xquery.com/modules/http-client\";\n http:get(\"http://www.example.com\")[2]\n 
    \n returns\n
    \n   <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n   <html>\n     <head>\n       <meta http-equiv=\"Content-Type\"\n       content=\"text/html; charset=utf-8\" />\n       <title>Example Web Page</title>\n     </head>\n     <body>\n       <p>You have reached this web page by typing \"example.com\",\n       \"example.net\", or \"example.org\" into your web browser.</p>\n       <p>These domain names are reserved for use in documentation and are\n       Not available for registration. See\n       <a href=\"http://www.rfc-editor.org/rfc/rfc2606.txt\">RFC 2606</a>,\n       Section 3.</p>\n     </body>\n   </html>\n   
    \n

    Note that the response data above is a simple\n xs:string value containing the HTML data, not actual XML data. If you\n executed the above query using the Zorba command-line client, you would\n have actually seen data like the following:

    \n
    \n   &lt;!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"&gt;\n   &lt;html&gt;\n      ...\n 
    \n

    because Zorba would attempt to serialize it as XML data, and would\n escape all the raw angle brackets in the original xs:string.

    \n

    Simple POST Request

    \n

    \n Here is a simple example which sends text content by making an HTTP POST\n request.\n

    \n
    \n import module namespace http=\"http://www.zorba-xquery.com/modules/http-client\";\n http:post( \"...\", \"Hello World\" )\n 
    \n

    Return Values

    \n

    Most functions in this module (all except\n options()) return one or more items.\n (head() returns exactly one.) For all of these,\n the first item returned will be a <http-schema:response>\n element, as seen in the examples above. This element has \"status\" and\n \"message\" attributes, representing the result of the HTTP call. It\n also has any number of <http-schema:header> child elements that\n encode the HTTP headers returned by the HTTP server. Finally, it\n will generally contain a <http-schema:body> child element with\n a \"media-type\" attribute that identifies the content-type of the\n result data.

    \n

    The full schema of this <http-schema:response> element is\n part of the EXPath\n HTTP Client module. You can see the schema\n here.

    \n

    Any items in function return values after the initial\n <http-schema:response> element are the body/bodies of the HTTP\n response from the server. (MIME Multi-part responses will have\n more than one body.) The type of these items depends on the\n Content-Type for each body. Each item will be:

    \n
      \n
    • \n an element node, if the returned content type is one of:\n
        \n
      • text/xml
      • \n
      • application/xml
      • \n
      • text/xml-external-parsed-entity
      • \n
      • application/xml-external-parsed-entity
      • \n
      • or if the Content-Type ends with \"+xml\".
      • \n
      \n
    • \n
    • \n an xs:string, if the returned content type starts with \"text/\"\n and does not match the above XML content types strings, or if\n it is one of:\n
        \n
      • \"application/json\"
      • \n
      • \"application/x-javascript\"
      • \n
      \n
    • \n
    • xs:base64Binary for all other content types.
    • \n
    \n

    This return value - a sequence of items comprising one\n <http-schema:response> element followed by zero or more\n response items - is referred to as the \"standard http-client\n return type\" in the function declarations below.

    \n

    $href Arguments to Functions

    \n All functions in this module accept a URL argument named $href. In\n all cases, the value passed to $href must be a valid xs:anyURI.\n However, all functions declare $href to be of type xs:string. This\n is for convenience, since you can pass a string literal value (that\n is, a URL in double-quotes spelled out explicitly in your query)\n to an xs:string parameter.\n

    Important Notice Regarding get() Functions

    \n All of the get() functions in this module -\n get(), get-node(),\n get-text(), and\n get-binary() - are declared to be\n nondeterministic, which means that Zorba will not cache\n their results. However, they are not declared to be\n sequential, which means that Zorba may re-order them\n as part of its query optimization. According to the HTTP RFC,\n GET requests should only return data, and should not have any\n side-effects. However, in practice it is not uncommon for GET\n requests to have side-effects. If your application depends on\n the ordering of side-effects from making GET requests, you should\n either use the more complex send-request()\n function (which is declared sequential), or alterately\n wrap each call to get() in your own sequential function, to ensure\n that Zorba does not place the GET requests out of order.\n

    Relation to the EXPath http-client module

    \n EXPath defines its own http-client\n module, which is available separately for Zorba as a non-core module.\n There are two primary differences between EXPath's http-client and\n Zorba's core http-client (this module):\n
      \n
    1. EXPath defines only the send-request() function, although it\n does include convenient 1- and 2-argument forms in addition to the\n full 3-argument form. EXPath does not include the simpler get(),\n post(), put(), delete(), head(), and options() functions defined by\n this module.
    2. \n
    3. EXPath specifies that all HTML content returned from the\n HTTP server will be tidied up into valid XML, and then parsed\n into an element. As this required an additional third-party library\n dependency, Zorba's http-client module does not perform this tidying.\n Instead, HTML content is returned as a string (with special XML\n characters replaced with XML entity references, as shown in the\n above examples).
    4. \n
    \n See the full spec\n of the EXPath http-client module for more information.\n", "sees" : [ "XQuery 1.1: Function Declaration" ], "authors" : [ "Markus Pilman, Federico Cavalieri" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://expath.org/ns/error", "prefix" : "error" }, { "uri" : "http://www.zorba-xquery.com/modules/http-client", "prefix" : "http" }, { "uri" : "http://expath.org/ns/http-client", "prefix" : "http-schema" }, { "uri" : "http://zorba.io/modules/http-client-wrapper", "prefix" : "http-wrapper" }, { "uri" : "http://jsoniq.org/functions", "prefix" : "jn" }, { "uri" : "http://zorba.io/modules/http-client", "prefix" : "json-http" }, { "uri" : "http://jsoniq.org/function-library", "prefix" : "libjn" }, { "uri" : "http://www.w3.org/2010/xslt-xquery-serialization", "prefix" : "ser" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "delete", "qname" : "http:delete", "signature" : "($href as xs:string) as item()+", "description" : " This function makes an HTTP DELETE request to a given URL.\n", "summary" : "

    This function makes an HTTP DELETE request to a given URL.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " } ], "returns" : { "type" : "item()+", "description" : "standard http-client return type." }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC002 Error parsing the response content as XML.", "error:HC006 A timeout occurred waiting for the response.", "error:HCV02 Trying to follow a redirect of a DELETE request." ] }, { "isDocumented" : true, "arity" : 1, "name" : "get-binary", "qname" : "http:get-binary", "signature" : "($href as xs:string) as item()+", "description" : " This function makes a GET request on a given URL. All returned bodies\n are forced to be interpreted as binary data, and will be returned\n as xs:base64Binary items.\n", "summary" : "

    This function makes a GET request on a given URL.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " } ], "returns" : { "type" : "item()+", "description" : "standard http-client return type." }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC002 Error parsing the response content as XML.", "error:HC006 A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 1, "name" : "get-node", "qname" : "http:get-node", "signature" : "($href as xs:string) as item()+", "description" : " This function makes a GET request to a given URL. All returned bodies\n are forced to be interpreted as XML and parsed into elements.\n", "summary" : "

    This function makes a GET request to a given URL.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " } ], "returns" : { "type" : "item()+", "description" : "standard http-client return type." }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC002 Error parsing the response content as XML.", "error:HC006 A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 1, "name" : "get-text", "qname" : "http:get-text", "signature" : "($href as xs:string) as item()+", "description" : " This function makes a GET request to a given URL. All returned bodies\n are forced to be interpreted as plain strings, and will be returned\n as xs:string items.\n", "summary" : "

    This function makes a GET request to a given URL.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " } ], "returns" : { "type" : "item()+", "description" : "standard http-client return type." }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC002 Error parsing the response content as XML.", "error:HC006 A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 1, "name" : "get", "qname" : "http:get", "signature" : "($href as xs:string) as item()+", "description" : " This function makes a GET request to a given URL.\n", "summary" : "

    This function makes a GET request to a given URL.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " } ], "returns" : { "type" : "item()+", "description" : "standard http-client return type." }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC002 Error parsing the response content as XML.", "error:HC006 A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 1, "name" : "head", "qname" : "http:head", "signature" : "($href as xs:string) as item()", "description" : " This function makes an HTTP HEAD request on a given URL.\n", "summary" : "

    This function makes an HTTP HEAD request on a given URL.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " } ], "returns" : { "type" : "item()", "description" : "standard http-client return type (since HEAD never returns any body data, only the <http-schema:response> element will be returned)." }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC006 A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 1, "name" : "options", "qname" : "http:options", "signature" : "($href as xs:string) as xs:string*", "description" : " This function makes an HTTP OPTIONS request, which asks the server\n which operations it supports.\n", "summary" : "

    This function makes an HTTP OPTIONS request, which asks the server\n which operations it supports.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of xs:string values of the allowed operations." }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC006 A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 2, "name" : "post", "qname" : "http:post", "signature" : "($href as xs:string, $body as item()) as item()+", "description" : " This function makes an HTTP POST request to a given URL. If the body\n passed to this function is an element, it will be serialized to XML\n to be sent to the server, and the Content-Type sent to the server will\n be \"text/xml\". Otherwise, the body will be converted to\n a plain string, and the Content-Type will be \"text/plain\".\n", "summary" : "

    This function makes an HTTP POST request to a given URL.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " }, { "name" : "body", "type" : "item()", "occurrence" : null, "description" : "
    The body which will be sent to the server.
    " } ], "returns" : { "type" : "item()+", "description" : "standard http-client return type." }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC002 Error parsing the response content as XML.", "error:HC006 A timeout occurred waiting for the response.", "error:HCV02 Trying to follow a redirect of a POST request." ] }, { "isDocumented" : true, "arity" : 3, "name" : "post", "qname" : "http:post", "signature" : "($href as xs:string, $body as item(), $content-type as xs:string) as item()+", "description" : " This function makes an HTTP POST request to a given URL. If the body\n passed to this function is an element, it will be serialized\n according to the $content-type parameter as follows:\n
      \n
    • If $content-type is \"text/xml\", \"application/xml\",\n \"text/xml-external-parsed-entity\", or\n \"application/xml-external-parsed-entity\", or if it ends with \"+xml\",\n $body will be serialized to XML.
    • \n
    • If $content-type starts with \"text/html\", $body will be\n serialized to HTML.
    • \n
    • Otherwise, $body will be serialized to text.
    • \n
    \n If $body is not an element, $body will be serialized to text\n regardless of $content-type.\n

    In any case, Content-Type of the request sent to the server will\n be $content-type.

    \n", "summary" : "

    This function makes an HTTP POST request to a given URL.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " }, { "name" : "body", "type" : "item()", "occurrence" : null, "description" : "
    The body which will be sent to the server
    " }, { "name" : "content-type", "type" : "xs:string", "occurrence" : null, "description" : "
    The content type of the body as described above.
    " } ], "returns" : { "type" : "item()+", "description" : "The first element of the result is the metadata (like headers, status etc), the next elements are the response" }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC002 Error parsing the response content as XML.", "error:HC006 A timeout occurred waiting for the response.", "error:HCV02 Trying to follow a redirect of a POST request." ] }, { "isDocumented" : true, "arity" : 2, "name" : "put", "qname" : "http:put", "signature" : "($href as xs:string, $body as item()) as item()+", "description" : " This function makes an HTTP PUT request to a given URL. If the body\n passed to this function is an element, it will be serialized to XML\n to be sent to the server, and the Content-Type sent to the server will\n be \"text/xml\". Otherwise, the body will be converted to\n a plain string, and the Content-Type will be \"text/plain\".\n", "summary" : "

    This function makes an HTTP PUT request to a given URL.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " }, { "name" : "body", "type" : "item()", "occurrence" : null, "description" : "
    The body which will be sent to the server.
    " } ], "returns" : { "type" : "item()+", "description" : "standard http-client return type." }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC002 Error parsing the response content as XML.", "error:HC006 A timeout occurred waiting for the response.", "error:HCV02 Trying to follow a redirect of a PUT request." ] }, { "isDocumented" : true, "arity" : 3, "name" : "put", "qname" : "http:put", "signature" : "($href as xs:string, $body as item(), $content-type as xs:string) as item()+", "description" : " This function makes an HTTP PUT request to a given URL. If the body\n passed to this function is an element, it will be serialized\n according to the $content-type parameter as follows:\n
      \n
    • If $content-type is \"text/xml\", \"application/xml\",\n \"text/xml-external-parsed-entity\", or\n \"application/xml-external-parsed-entity\", or if it ends with \"+xml\",\n $body will be serialized to XML.
    • \n
    • If $content-type starts with \"text/html\", $body will be\n serialized to HTML.
    • \n
    • Otherwise, $body will be serialized to text.
    • \n
    \n If $body is not an element, $body will be serialized to text\n regardless of $content-type.\n

    In any case, Content-Type of the request sent to the server will\n be $content-type.

    \n", "summary" : "

    This function makes an HTTP PUT request to a given URL.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " }, { "name" : "body", "type" : "item()", "occurrence" : null, "description" : "
    The body which will be sent to the server.
    " }, { "name" : "content-type", "type" : "xs:string", "occurrence" : null, "description" : "
    The content type of $body as described above.
    " } ], "returns" : { "type" : "item()+", "description" : "standard http-client return type." }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC002 Error parsing the response content as XML.", "error:HC006 A timeout occurred waiting for the response.", "error:HCV02 Trying to follow a redirect of a PUT request." ] }, { "isDocumented" : true, "arity" : 3, "name" : "send-request", "qname" : "http:send-request", "signature" : "($request as element(http-schema:request)?, $href as xs:string?, $bodies as item()*) as item()+", "description" : " This function sends an HTTP request and returns the corresponding response.\n Its inputs, outputs, and behavior are identical to the\n EXPath http-client's\n send-request() function (except that HTML responses are not tidied\n into XML - see the note above). It\n is provided here for use in Zorba installations that do not have\n the EXPath module available. If you have the option of using the\n EXPath module instead of this function, please do so, as it will\n allow your application to be more interoperable between different\n XQuery engines.\n Full documentation of the $request parameter can be found in\n the EXPath\n specification.\n", "summary" : "

    This function sends an HTTP request and returns the corresponding response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "request", "type" : "element(http-schema:request)", "occurrence" : "?", "description" : "
    Contains the various parameters of the request (see above).
    " }, { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "
    The URL to which the request will be made (see note above). If this parameter is specified, it will override the \"href\" attribute of $request.
    " }, { "name" : "bodies", "type" : "item()", "occurrence" : "*", "description" : "
    is the request body content, for HTTP methods that can contain a body in the request (i.e. POST and PUT). It is an error if this param is not the empty sequence for methods
    " } ], "returns" : { "type" : "item()+", "description" : "standard http-client return type." }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC002 Error parsing the response content as XML.", "error:HC003 With a multipart response, the override-media-type must be either a multipart media type or application/octet-stream.", "error:HC004 The src attribute on the body element is mutually exclusive with all other attribute (except the media-type).", "error:HC005 The input request element is not valid.", "error:HC006 A timeout occurred waiting for the response.", "error:HCV02 Trying to follow a redirect of a POST, PUT, or DELETE request" ] } ], "variables" : [ ] }, "http://xbrl.io/modules/bizql/profiles/sec/networks" : { "ns" : "http://xbrl.io/modules/bizql/profiles/sec/networks", "description" : "

    This module provides functionality for querying SEC networks in SEC filings.

    \n

    SEC Networks are actually XBRL Components. In the SEC profiles, all XBRL networks\n in an XBRL component must be consistent to each other. A way to look at it is that\n the SEC Network can be identified with the XBRL presentation network it contains.

    \n

    For XBRL-generic operations on XBRL components, use the\n generic components module.

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/archives", "prefix" : "archives" }, { "uri" : "http://xbrl.io/modules/bizql/components", "prefix" : "components" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://xbrl.io/modules/bizql/facts", "prefix" : "facts" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/filings", "prefix" : "filings" }, { "uri" : "http://xbrl.io/modules/bizql/hypercubes", "prefix" : "hypercubes" }, { "uri" : "http://www.28msec.com/modules/mongodb", "prefix" : "mongo" }, { "uri" : "http://xbrl.io/modules/bizql/networks", "prefix" : "networks" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/core", "prefix" : "sec" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/networks", "prefix" : "sec-networks" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "abstracts", "qname" : "sec-networks:abstracts", "signature" : "($networks-or-ids as item()*) as object()*", "description" : "

    Returns all SEC Abstracts contained in the supplied SEC Networks.

    \n

    SEC Abstracts are XBRL abstract primary items that may or may not be associated\n with a hypercube -- except those that are SEC LineItems (i.e., source of an all relation).

    \n", "summary" : "

    Returns all SEC Abstracts contained in the supplied SEC Networks.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "object()*", "description" : "the SEC Abstracts." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "axes", "qname" : "sec-networks:axes", "signature" : "($networks-or-ids as item()*) as object()*", "description" : "

    Returns all SEC Axes contained in the supplied SEC Networks.

    \n

    SEC Axes are XBRL dimensions.

    \n", "summary" : "

    Returns all SEC Axes contained in the supplied SEC Networks.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "object()*", "description" : "the SEC Axes." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "categories", "qname" : "sec-networks:categories", "signature" : "($networks-or-ids) as string*", "description" : "

    Return the categories of the supplied SEC networks (Statement, Disclosure, Document or Schedule).

    \n", "summary" : "

    Return the categories of the supplied SEC networks (Statement, Disclosure, Document or Schedule).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : null, "occurrence" : null, "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "string*", "description" : "the category of each network." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "concepts", "qname" : "sec-networks:concepts", "signature" : "($networks-or-ids as item()*) as object()*", "description" : "

    Returns all SEC Concepts contained in the supplied SEC Networks.

    \n

    SEC Concepts are XBRL concrete primary items that may or may not be associated\n with a hypercube.

    \n", "summary" : "

    Returns all SEC Concepts contained in the supplied SEC Networks.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "object()*", "description" : "the SEC Concepts." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "disclosures", "qname" : "sec-networks:disclosures", "signature" : "($networks-or-ids as item()*) as string+", "description" : "

    Returns the disclosures of the suplied networks.

    \n", "summary" : "

    Returns the disclosures of the suplied networks.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "string+", "description" : "the disclosure names, or \"UncategorizedInformation\" if none." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "fact-tables", "qname" : "sec-networks:fact-tables", "signature" : "($networks-or-ids as item()*) as array()", "description" : "

    Retrieves all facts belonging to the SEC Network.

    \n", "summary" : "

    Retrieves all facts belonging to the SEC Network.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "array()", "description" : "a array populated with fact values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "fact-tables", "qname" : "sec-networks:fact-tables", "signature" : "($networks-or-ids as item()*, $options as object()?) as array()", "description" : "

    Retrieves all facts belonging to the SEC Network.

    \n", "summary" : "

    Retrieves all facts belonging to the SEC Network.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "array()", "description" : "a array of arrays filled with fact values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "facts", "qname" : "sec-networks:facts", "signature" : "($networks-or-ids as item()*) as object()*", "description" : "

    Retrieves all facts belonging to the SEC Network.

    \n", "summary" : "

    Retrieves all facts belonging to the SEC Network.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "object()*", "description" : "a sequence of facts." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "facts", "qname" : "sec-networks:facts", "signature" : "($networks-or-ids as item()*, $options as object()?) as object()*", "description" : "

    Retrieves all facts belonging to the SEC Network.

    \n", "summary" : "

    Retrieves all facts belonging to the SEC Network.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "a sequence of facts." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "line-items-report-elements", "qname" : "sec-networks:line-items-report-elements", "signature" : "($networks-or-ids as item()*) as object()*", "description" : "

    Returns all SEC LineItems report elements contained in the supplied SEC Networks.

    \n

    This is not to be confused with the \"line items\" terminology, which includes all\n SEC Abstracts and SEC Concepts.

    \n

    SEC LineItems report elements are XBRL abstract primary items that are top-level in their\n association with an XBRL hypercube (source of an all relation).

    \n", "summary" : "

    Returns all SEC LineItems report elements contained in the supplied SEC Networks.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "object()*", "description" : "the SEC LineItems report elements." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "line-items", "qname" : "sec-networks:line-items", "signature" : "($networks-or-ids as item()*) as object()*", "description" : "

    Returns all SEC Line Items (Concepts and Abstracts) contained in the\n supplied SEC Networks. Not to be confused with the LineItems report element.

    \n", "summary" : "

    Returns all SEC Line Items (Concepts and Abstracts) contained in the\n supplied SEC Networks.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "object()*", "description" : "the SEC Line Items." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "members", "qname" : "sec-networks:members", "signature" : "($networks-or-ids as item()*) as object()*", "description" : "

    Returns all SEC Members contained in the supplied SEC Networks.

    \n

    SEC Members are XBRL members that are in the transitive closure of SEC Axes\n via the dimension-domain and domain-member relations.

    \n", "summary" : "

    Returns all SEC Members contained in the supplied SEC Networks.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "object()*", "description" : "the SEC Members." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "model-structures", "qname" : "sec-networks:model-structures", "signature" : "($networks-or-ids as item()*) as object()*", "description" : "

    Computes the model structure of the supplied SEC Network, which is a hierarchy\n of SEC Report Elements (Tables, Axes, Members, LineItems, Abstracts, Concepts).

    \n", "summary" : "

    Computes the model structure of the supplied SEC Network, which is a hierarchy\n of SEC Report Elements (Tables, Axes, Members, LineItems, Abstracts, Concepts).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "object()*", "description" : "the model structures of these SEC Networks." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "networks-for-disclosures", "qname" : "sec-networks:networks-for-disclosures", "signature" : "($disclosures as string*) as object()*", "description" : "

    Retrieves all SEC Networks that bear the supplied disclosures.

    \n", "summary" : "

    Retrieves all SEC Networks that bear the supplied disclosures.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "disclosures", "type" : "string", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "all models that match one of the disclosures." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "networks-for-filings-and-categories", "qname" : "sec-networks:networks-for-filings-and-categories", "signature" : "($archive-or-ids as item()*, $categories as string*) as object()*", "description" : "

    Retrieves all models that belong to the archives given as first\n parameter and that match the supplied category.

    \n

    A category can be any of \"Statement\", \"Disclosure\", \"Document\",\n \"Schedule\", or \"Unknown\".

    \n", "summary" : "

    Retrieves all models that belong to the archives given as first\n parameter and that match the supplied category.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    an arbitrary number of archive identifiers (AIDs) or archive objects.
    " }, { "name" : "categories", "type" : "string", "occurrence" : "*", "description" : "
    a list of categories.
    " } ], "returns" : { "type" : "object()*", "description" : "all said models" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "networks-for-filings-and-disclosures", "qname" : "sec-networks:networks-for-filings-and-disclosures", "signature" : "($archive-or-ids as item()*, $disclosures as string*) as object()*", "description" : "

    Retrieves all models that belong to the archives given as first\n parameter and that match the supplied disclosures.

    \n", "summary" : "

    Retrieves all models that belong to the archives given as first\n parameter and that match the supplied disclosures.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    an arbitrary number of archive identifiers (AIDs) or archive objects.
    " }, { "name" : "disclosures", "type" : "string", "occurrence" : "*", "description" : "
    a list of disclosures.
    " } ], "returns" : { "type" : "object()*", "description" : "all models in the archives and that match one of the disclosures." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "networks-for-filings", "qname" : "sec-networks:networks-for-filings", "signature" : "($archives-or-ids as item()*) as object()*", "description" : "

    Retrieves all SEC Networks in a given filing.

    \n", "summary" : "

    Retrieves all SEC Networks in a given filing.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "all networks in the supplied filings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-abstracts", "qname" : "sec-networks:num-abstracts", "signature" : "($networks-or-ids as item()*) as integer*", "description" : " Return the number of (distinct) SEC Abstracts in each of the given components.\n", "summary" : "

    Return the number of (distinct) SEC Abstracts in each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    list of components or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of abstracts" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-axes", "qname" : "sec-networks:num-axes", "signature" : "($networks-or-ids as item()*) as integer*", "description" : " Return the number of (distinct) SEC Axes in each of the given components.\n", "summary" : "

    Return the number of (distinct) SEC Axes in each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    list of components or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of axes" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-concepts", "qname" : "sec-networks:num-concepts", "signature" : "($networks-or-ids as item()*) as integer*", "description" : " Return the number of (distinct) SEC Concepts in each of the given components.\n", "summary" : "

    Return the number of (distinct) SEC Concepts in each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    list of components or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of concepts" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-line-items", "qname" : "sec-networks:num-line-items", "signature" : "($networks-or-ids as item()*) as integer*", "description" : " Return the number of (distinct) SEC LineItems report elements in each of the given components.\n", "summary" : "

    Return the number of (distinct) SEC LineItems report elements in each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    list of components or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of line items" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-members", "qname" : "sec-networks:num-members", "signature" : "($networks-or-ids as item()*) as integer*", "description" : " Return the number of (distinct) SEC Members in each of the given components.\n", "summary" : "

    Return the number of (distinct) SEC Members in each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    list of components or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of members" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-report-elements", "qname" : "sec-networks:num-report-elements", "signature" : "($networks-or-ids as item()*) as integer*", "description" : " Return the number of (distinct) SEC report elements in each of the given components.\n", "summary" : "

    Return the number of (distinct) SEC report elements in each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    list of components or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of report elements" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-tables", "qname" : "sec-networks:num-tables", "signature" : "($networks-or-ids as item()*) as integer*", "description" : " Return the number of SEC Tables in each of the given components.\n", "summary" : "

    Return the number of SEC Tables in each of the given components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    list of components or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of tables" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "populated-model-structures", "qname" : "sec-networks:populated-model-structures", "signature" : "($networks-or-ids as item()*) as object()*", "description" : "

    Retrieves all facts belonging to the SEC Networks and populates the model structures.

    \n", "summary" : "

    Retrieves all facts belonging to the SEC Networks and populates the model structures.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "object()*", "description" : "the populated model structures (Facts array fields)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "populated-model-structures", "qname" : "sec-networks:populated-model-structures", "signature" : "($networks-or-ids as item()*, $options as object()?) as object()*", "description" : "

    Retrieves all facts belonging to the SEC Networks and populates the model structures.

    \n", "summary" : "

    Retrieves all facts belonging to the SEC Networks and populates the model structures.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "the populated model structures (Facts array fields)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sub-categories", "qname" : "sec-networks:sub-categories", "signature" : "($networks-or-ids) as string*", "description" : "

    Return the sub-categories of the supplied SEC networks (Detail, TextBlockLevel4, TextBLockLevel1to3).

    \n", "summary" : "

    Return the sub-categories of the supplied SEC networks (Detail, TextBlockLevel4, TextBLockLevel1to3).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : null, "occurrence" : null, "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "string*", "description" : "the sub-category of each network." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "summaries", "qname" : "sec-networks:summaries", "signature" : "($networks-or-ids) as object()*", "description" : "

    Return summary information for the supplied SEC networks.

    \n", "summary" : "

    Return summary information for the supplied SEC networks.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : null, "occurrence" : null, "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "object()*", "description" : "one object per network, containing a summary." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "tables", "qname" : "sec-networks:tables", "signature" : "($networks-or-ids as item()*) as object()*", "description" : "

    Returns all SEC Tables contained in the supplied SEC Networks.

    \n

    SEC Tables are XBRL hypercubes.

    \n", "summary" : "

    Returns all SEC Tables contained in the supplied SEC Networks.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " } ], "returns" : { "type" : "object()*", "description" : "the SEC Tables." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "tables", "qname" : "sec-networks:tables", "signature" : "($networks-or-ids as item()*, $options as object()?) as object()*", "description" : "

    Returns all SEC Tables contained in the supplied SEC Networks.

    \n

    SEC Tables are XBRL hypercubes.

    \n", "summary" : "

    Returns all SEC Tables contained in the supplied SEC Networks.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of SEC Network objects, or their XBRL Component IDs.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "the SEC Tables." }, "errors" : [ ] } ], "variables" : [ { "name" : "sec-networks:BALANCE_SHEET", "type" : "xs:string", "description" : " Disclosure for the balance sheet.\n" }, { "name" : "sec-networks:BALANCE_SHEET_PARENTHETICAL", "type" : "xs:string", "description" : " Disclosure for the parenthetical balance sheet.\n" }, { "name" : "sec-networks:INCOME_STATEMENT", "type" : "xs:string", "description" : " Disclosure for the income statement.\n" }, { "name" : "sec-networks:INCOME_STATEMENT_PARENTHETICAL", "type" : "xs:string", "description" : " Disclosure for the parenthetical income statement.\n" }, { "name" : "sec-networks:STATEMENT_OF_COMPREHENSIVE_INCOME", "type" : "xs:string", "description" : " Disclosure for the statement of comprehensive income.\n" }, { "name" : "sec-networks:CASH_FLOW_STATEMENT", "type" : "xs:string", "description" : " Disclosure for the cash flow statement.\n" }, { "name" : "sec-networks:CASH_FLOW_STATEMENT_PARENTHETICAL", "type" : "xs:string", "description" : " Disclosure for the parenthetical cash flow statement.\n" }, { "name" : "sec-networks:DEFAULT_COMPONENT", "type" : "xs:string", "description" : " Disclosure for the default component.\n" }, { "name" : "sec-networks:DOCUMENT_AND_ENTITY_INFO", "type" : "xs:string", "description" : " Disclosure for the document and entity information\n" } ] }, "http://www.28msec.com/modules/http/request" : { "ns" : "http://www.28msec.com/modules/http/request", "description" : " The Sausalito request module provides functions for accessing\n information contained in the current HTTP request. For example,\n the parameter-names function can be used to retrieve all\n the names of the parameters contained in a request.\n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "request" }, { "uri" : "http://www.zorba-xquery.com/modules/cryptography/hmac", "prefix" : "sec" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "binary-content", "qname" : "request:binary-content", "signature" : "() as xs:base64Binary external", "description" : "

    Returns the content of the request as base64Binary.

    \n", "summary" : "

    Returns the content of the request as base64Binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:base64Binary", "description" : "The content of the request as base64Binary." }, "errors" : [ "request:no-binary-content if the content contained in the body of the request cannot be treated as binary because it is a request with multipart or url-encoded content." ] }, { "isDocumented" : true, "arity" : 1, "name" : "binary-part", "qname" : "request:binary-part", "signature" : "($ref as xs:string) as xs:base64Binary external", "description" : "

    Returns the value of a part as base64Binary.

    \n

    A part is identified by a reference that is the value of a\n src attribute returned by the request:parts function.

    \n", "summary" : "

    Returns the value of a part as base64Binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "ref", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the part
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the value of the part as base64Binary" }, "errors" : [ "request:invalid-part if the part with the given name ($ref) does not exist", "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 0, "name" : "content-length", "qname" : "request:content-length", "signature" : "() as xs:integer? external", "description" : "

    Returns the length of the content in bytes.

    \n

    The value returned corresponds to the value of the HTTP\n content-length header. The function returns an empty sequence\n if this header does not exist in the request or its value\n could not be converted to item of type xs:integer

    .\n", "summary" : "

    Returns the length of the content in bytes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:integer?", "description" : "The content-length in bytes of the content sent with this request or the empty sequence if the content-length header does not exist in the request." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "content-type", "qname" : "request:content-type", "signature" : "() as xs:string? external", "description" : "

    Returns the content-type of the data sent with this request.

    \n

    Note that the content-type is only set for PUT and POST requests.

    \n", "summary" : "

    Returns the content-type of the data sent with this request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string?", "description" : "The content-type of the request if it is a PUT or POST request. Otherwise, it returns the empty sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "header-accept", "qname" : "request:header-accept", "signature" : "() as element(request:accept)*", "description" : "

    Returns the values of the HTTP ACCEPT header.

    \n

    The data is returned as a sequence of elements with name\n request:accept as shown in the following example.

    \n \n <request:accept xmlns:request=\"http://www.28msec.com/modules/http/request\">\n <request:type>text</request:type>\n <request:subtype>html</request:subtype>\n <request:quality>1</request:quality>\n </request:accept>\n <request:accept xmlns=\"http://www.28msec.com/modules/http/request\">\n <request:type>application</request:type>\n <request:quality>0.9</request:quality>\n </request:accept>\n \n", "summary" : "

    Returns the values of the HTTP ACCEPT header.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "element(request:accept)*", "description" : "The header values of the header ACCEPT or the empty sequence if the header is not contained in the request. The order of the returned elements reflects the order of the components in the header." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "header-names", "qname" : "request:header-names", "signature" : "() as xs:string* external", "description" : "

    Returns the names of all the HTTP headers in this request.

    \n

    Header fields are colon-separated name-value pairs, terminated\n by a carriage return (CR) and line feed (LF) character sequence. The\n names and values of each header are allowed to consist of US-ASCII\n characters only.

    \n

    The names of the headers are returned using upper-case letters.\n If a header with the same name is contained multiple times in a request,\n its name is only returned once. The order of the names in the resulting\n sequence does not reflect the order of the headers in the request. If\n a header does not have a value, it is as if the header does not exist\n in the request.

    \n

    Note that the header names user-agent and content-type are not\n returned by this function. They are returned by the corresponding\n functions of this module module\n (e.g. user-agent).

    \n", "summary" : "

    Returns the names of all the HTTP headers in this request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string*", "description" : "The names of the headers of this request or the empty sequence if no headers are contained in the request." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "header-value", "qname" : "request:header-value", "signature" : "($name as xs:string) as xs:string? external", "description" : "

    Returns the value of the HTTP header with the given name.

    \n

    Header fields are colon-separated name-value pairs, terminated\n by a carriage return (CR) and line feed (LF) character sequence. The\n names and values of each header are allowed to consist of US-ASCII\n characters only.

    \n

    Please note that header names are considered case-insensitive.\n Also note, that only one value is returned if multiple headers with the\n same names exist in the request. This value is a comma-separated list\n of the values of the headers in the order in which the headers appeared\n in the request.

    \n

    All headers having a name that starts with SAUSALITO_ are reserved\n and will not be returned by this function.

    \n", "summary" : "

    Returns the value of the HTTP header with the given name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The header name for which the value should be returned.
    " } ], "returns" : { "type" : "xs:string?", "description" : "The header value of the header with the $name argument or the empty sequence if no header with that name is contained in the request." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method-delete", "qname" : "request:method-delete", "signature" : "() as xs:boolean external", "description" : " Returns true if the HTTP method of this request is DELETE.\n", "summary" : "

    Returns true if the HTTP method of this request is DELETE.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "true if the HTTP method of this request is DELETE, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method-get", "qname" : "request:method-get", "signature" : "() as xs:boolean external", "description" : " Returns true if the HTTP method of this request is GET.\n", "summary" : "

    Returns true if the HTTP method of this request is GET.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "true if the HTTP method of this request is GET, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method-head", "qname" : "request:method-head", "signature" : "() as xs:boolean external", "description" : " Returns true if the HTTP method of this request is HEAD.\n", "summary" : "

    Returns true if the HTTP method of this request is HEAD.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "true if the HTTP method of this request is HEAD, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method-options", "qname" : "request:method-options", "signature" : "() as xs:boolean external", "description" : " Returns true if the HTTP method of this request is OPTION.\n", "summary" : "

    Returns true if the HTTP method of this request is OPTION.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "true if the HTTP method of this request is OPTION, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method-patch", "qname" : "request:method-patch", "signature" : "() as xs:boolean external", "description" : " Returns true if the HTTP method of this request is PATCH.\n", "summary" : "

    Returns true if the HTTP method of this request is PATCH.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "true if the HTTP method of this request is PATCH, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method-post", "qname" : "request:method-post", "signature" : "() as xs:boolean external", "description" : " Returns true if the HTTP method of this request is POST.\n", "summary" : "

    Returns true if the HTTP method of this request is POST.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "true if the HTTP method of this request is POST, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method-put", "qname" : "request:method-put", "signature" : "() as xs:boolean external", "description" : " Returns true if the HTTP method of this request is PUT.\n", "summary" : "

    Returns true if the HTTP method of this request is PUT.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "true if the HTTP method of this request is PUT, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method", "qname" : "request:method", "signature" : "() as xs:string external", "description" : "

    Returns the name of the HTTP method used to make this request.

    \n", "summary" : "

    Returns the name of the HTTP method used to make this request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The request method used to make this request (i.e. GET, POST, PUT, DELETE or HEAD)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "parameter-names", "qname" : "request:parameter-names", "signature" : "() as xs:string*", "description" : "

    Returns the names of the parameters contained in the current request.

    \n

    Parameters are name-value pairs contained in the query string of the URL\n used to make this request. As defined in RFC 1738, the query string of a\n URL starts with a \"?\" character and ends with the character (if any).\n Additionally, such name-value pairs may be part of the request's body if\n it is a PUT or POST request and the content-type of the request is\n \"application/x-www-form-urlencoded\". Name-value pairs are separated\n using either the \"&\" or the \";\" character.

    \n

    In general, the names and the values are precent-encoded. This function\n does the decoding of the parameters, i.e. it returns the values being\n not percent-encoded.

    \n

    Also, the names of each parameter (after being precent-decoded) are\n treated as UTF-8. Please see the http:parameter-names#1 function\n for retrieving parameter names submitted using a encoding other than UTF-8.\n

    \n", "summary" : "

    Returns the names of the parameters contained in the current request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string*", "description" : "The names of all parameters in this request. The empty sequence is returned if there are none." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "parameter-names", "qname" : "request:parameter-names", "signature" : "($encoding as xs:string) as xs:string* external", "description" : "

    Returns the names of the parameters contained in the current request.

    \n

    This function is similar to the request:parameter-names#0 function.\n However, the names are treated (after precent-decoding) using the\n given encoding supplied as parameter. For example, parameters might\n be encoded using the ISO-8859-1 encoding.

    \n", "summary" : "

    Returns the names of the parameters contained in the current request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "
    The encoding of the parameters in the request (e.g. ISO-8859-1).
    " } ], "returns" : { "type" : "xs:string*", "description" : "The names of all parameters in this request. The empty sequence is returned if there are none." }, "errors" : [ "request:invalid-encoding if the given encoding is invalid or not supported." ] }, { "isDocumented" : true, "arity" : 1, "name" : "parameter-values", "qname" : "request:parameter-values", "signature" : "($name as xs:string) as xs:string*", "description" : "

    Returns a sequence of parameter values for the given parameter name\n which are contained in the URL's query string or the body of a POST or PUT\n request.

    \n

    Parameters are name-value pairs contained in the query string of the URL\n used to make this request. As defined in RFC 1738, the query string of a\n URL starts with a \"?\" character and ends with the character (if any).\n Additionally, such name-value pairs may be part of the request's body if\n it is a PUT or POST request and the content-type of the request is\n \"application/x-www-form-urlencoded\". Name-value pairs are separated\n using either the \"&\" or the \";\" character.

    \n

    In general, the names and the values are precent-encoded. This function\n does the decoding of the parameters, i.e. it returns the values being\n not percent-encoded.

    \n

    Also, the names and the values of each parameter (after being precent-decoded)\n are treated as UTF-8. Please see the http:parameter-values#3 function\n for retrieving parameters submitted using a encoding other than UTF-8.

    \n

    This function returns the empty-sequence if no parameter with the\n given name exists in this request. If you want the function to return\n a default value other than the empty sequence, use the\n http:parameter-values#2 function.

    \n

    A URL could contain the following query string:\n name1=value1&name2=value2;name1=value3&name3.\n name1=value1&name2=value2&name1=value3&name3.\n The name value pairs in this query string are\n

      \n
    • name: name1; values: value1 and value3
    • \n
    • name: name2; value: value2
    • \n
    • name: name3; value:
    • \n
    \n

    \n", "summary" : "

    Returns a sequence of parameter values for the given parameter name\n which are contained in the URL's query string or the body of a POST or PUT\n request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the parameter whose value(s) should be returned.
    " } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of values for the parameter with the given name. The empty sequence is returned if no parameter exists with the given name." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "parameter-values", "qname" : "request:parameter-values", "signature" : "($name as xs:string, $default-values as xs:string*) as xs:string*", "description" : "

    Returns a sequence of parameter values for the given parameter name\n which are contained in the URL's query string or the body of a POST or PUT\n request.

    \n

    This function is similar to the request:parameter-values#1 function.\n However, instead of returning the empty-sequence as a default value it returns\n the given default-values sequence if no parameter with the given name is found\n in this request.

    \n", "summary" : "

    Returns a sequence of parameter values for the given parameter name\n which are contained in the URL's query string or the body of a POST or PUT\n request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the parameter whose value(s) should be returned.
    " }, { "name" : "default-values", "type" : "xs:string", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of values for the parameter with the given name. The sequence given as $default-values parameter is returned if no parameter exists with the given name." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "parameter-values", "qname" : "request:parameter-values", "signature" : "($name as xs:string, $default-values as xs:string*, $encoding as xs:string) as xs:string* external", "description" : "

    Returns a sequence of parameter values for the given parameter name\n which are contained in the URL's query string or the body of a POST or PUT\n request.

    \n

    This function is similar to the request:parameter-values#2 function.\n However, the names and values are treated (after precent-decoding) using the\n given encoding supplied as third parameter. For example, parameters might\n be encoded using the ISO-8859-1 encoding.

    \n", "summary" : "

    Returns a sequence of parameter values for the given parameter name\n which are contained in the URL's query string or the body of a POST or PUT\n request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the parameter whose value(s) should be returned.
    " }, { "name" : "default-values", "type" : "xs:string", "occurrence" : "*", "description" : "" }, { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "
    The encoding of the parameters in the request (e.g. ISO-8859-1)
    " } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of values for the parameter with the given name. The sequence given as $default-values parameter is returned if no parameter exists with the given name." }, "errors" : [ "request:invalid-encoding if the given encoding is invalid or not supported." ] }, { "isDocumented" : true, "arity" : 0, "name" : "parts", "qname" : "request:parts", "signature" : "() as element(request:multipart) external", "description" : "

    Returns the metadata of all parts contained in a multipart request.

    \n

    The data is returned as an element with name request:mulitpart\n as shown in the following example.

    \n \n <multipart xmlns=\"http://www.28msec.com/modules/http/request\"\n media-type=\"multipart/...; boundary=...\">\n <header name=\"Content-Disposition\" value='form-data; filename=\"...\"'/>\n <header name=\"Content-Type\" value=\"application/octet-stream\"/>\n <body filename=\"...\" src=\"...\"/>\n <header name=\"Content-Disposition\" value='form-data; filename=\"...\"'/>\n <header name=\"Content-Type\" value=\"application/octet-stream\"/>\n <body filename=\"...\" src=\"...\"/>\n </multipart>\n \n

    The media-type is the type of the content as given in the\n request (i.e. it's value is equal to the value returned by\n request:header-values(\"Content-Type\")).

    \n

    Within the multipart element is a sequence of\n (header*,body) elements. Each such group corresponds to\n one part. Every header belongs to a header for this part and the\n body refers to the value of a part. The actual value of a part\n can be retrieved by passing the value of the src attribute of\n the body to the request:text-part or\n request:binary-part functions. The other attributes of the\n body element represent a parameter of the Content-Disposition\n header as described in RFC 2183 (e.g. filename, name, creation-date).

    \n

    Please note that recursive multipart content is not supported.

    \n", "summary" : "

    Returns the metadata of all parts contained in a multipart request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "element(request:multipart)", "description" : "a multipart element representing the meta data of the multipart content" }, "errors" : [ "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 0, "name" : "path", "qname" : "request:path", "signature" : "() as xs:string", "description" : " Return the path component of the request URI. The path starts after the\n host and ends before the query string starts.\n", "summary" : "

    Return the path component of the request URI.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The path component of the request URI" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "query-string", "qname" : "request:query-string", "signature" : "() as xs:string external", "description" : "

    Returns the query string that was used to make this request.

    \n

    The query string contains the part of the request URL that\n starts with the '?' character to the end or the starting of the\n fragment (i.e. the '#' character).

    \n", "summary" : "

    Returns the query string that was used to make this request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The query string part of the request's URL" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "remote-addr", "qname" : "request:remote-addr", "signature" : "() as xs:string external", "description" : "

    Returns the IP address of the client to which this request\n is connected.

    \n", "summary" : "

    Returns the IP address of the client to which this request\n is connected.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The IP address on the client side to which this request is connected." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "remote-port", "qname" : "request:remote-port", "signature" : "() as xs:int external", "description" : "

    Returns the port of the client to which this request is connected.

    \n", "summary" : "

    Returns the port of the client to which this request is connected.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:int", "description" : "The port on the client side to which this request is connected." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "server-name", "qname" : "request:server-name", "signature" : "() as xs:string external", "description" : "

    Returns the server name of the server running the application.

    \n

    The web server's hostname or IP address.

    \n", "summary" : "

    Returns the server name of the server running the application.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The name of the server that runs the application accepting this request." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "server-port", "qname" : "request:server-port", "signature" : "() as xs:int external", "description" : "

    Returns the sever port to which the client making the current request\n is connected.

    \n", "summary" : "

    Returns the sever port to which the client making the current request\n is connected.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:int", "description" : "The server port to which the client is connected." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "text-content", "qname" : "request:text-content", "signature" : "() as xs:string external", "description" : "

    Returns the content of the request as string.

    \n

    The function returns the content of the request only\n if the content-type refers to a type that can be treated\n as text (e.g. text/* or application/xml). The function raises\n an error if the content cannot be treated as text.

    \n

    The text content is interpreted using the encoding/charset\n that is specified in the Content-Type header of the request. If\n no charset is specified, the default ISO-8859-1 is used. If a encoding\n other than the specified or default one should be used, the\n request:text-content#1 function should be used.

    \n", "summary" : "

    Returns the content of the request as string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The content of the request as a string." }, "errors" : [ "request:invalid-encoding if the encoding specified in the Content-Type header is invalid or not supported.", "request:no-text-content if the content contained in the body of the request cannot be treated as text." ] }, { "isDocumented" : true, "arity" : 1, "name" : "text-content", "qname" : "request:text-content", "signature" : "($overwrite-encoding as xs:string) as xs:string external", "description" : "

    Returns the content of the request as string interpreting\n it with the given encoding.

    \n

    The function returns the content of the request only\n if the content-type refers to a type that can be treated\n as text (e.g. text/* or application/xml). The function raises\n an error if the content cannot be treated as text.

    \n

    The text content is interpreted using the given encoding/charset.\n That is, the charset specified in the Content-Type header of the request\n is ignored. An error is raised if the given encoding is invalid\n or not supported.

    \n", "summary" : "

    Returns the content of the request as string interpreting\n it with the given encoding.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "overwrite-encoding", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "The content of the request as a string." }, "errors" : [ "request:invalid-encoding if the encoding specified in the Content-Type header or the $overwrite-encoding parameter is invalid or not supported.", "request:no-text-content if the content contained in the body of the request cannot be treated as text." ] }, { "isDocumented" : true, "arity" : 1, "name" : "text-part", "qname" : "request:text-part", "signature" : "($ref as xs:string) as xs:string external", "description" : "

    Returns the value of a part as string

    \n

    A part is identified by a reference that is the value of a\n src attribute returned by the request:parts function.

    \n

    The value of the text part is interpreted using the encoding/charset\n given in the headers of the part. If no encoding is given, the default\n US-ASCII is assumed.

    \n", "summary" : "

    Returns the value of a part as string \n A part is identified by a reference that is the value of a\n src attribute returned by the request:parts function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "ref", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the part
    " } ], "returns" : { "type" : "xs:string", "description" : "the value of the part as string" }, "errors" : [ "request:invalid-encoding if the encoding given in the headers of the part is invalid or not supported.", "request:no-text-content if the value of the part cannot be treated as text", "request:invalid-part if the part with the given name ($ref) does not exist", "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 2, "name" : "text-part", "qname" : "request:text-part", "signature" : "($ref as xs:string, $overwrite-encoding as xs:string) as xs:string external", "description" : "

    Returns the value of a part as string interpreting\n it with the given encoding.

    \n

    A part is identified by a reference that is the value of a\n src attribute returned by the request:parts function.

    \n", "summary" : "

    Returns the value of a part as string interpreting\n it with the given encoding.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "ref", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the part
    " }, { "name" : "overwrite-encoding", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "the value of the part as string" }, "errors" : [ "request:invalid-encoding if the encoding given using the $overwrite-encoding parameter is invalid or not supported.", "request:no-text-content if the value of the part cannot be treated as text", "request:invalid-part if the part with the given name ($ref) does not exist", "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 0, "name" : "uri", "qname" : "request:uri", "signature" : "() as xs:string external", "description" : "

    Returns the URI that was used to make this request.

    \n

    The value returned contains the part of the URL starting\n from the path to the end or the starting of the fragment (i.e.\n the '#' character).

    \n", "summary" : "

    Returns the URI that was used to make this request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The path and query string part of the request's URL" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "user-agent", "qname" : "request:user-agent", "signature" : "() as xs:string? external", "description" : "

    Returns the user agent that made to perform the current request.

    \n

    This function returns the value of the User-Agent header\n contained in the current request.

    \n", "summary" : "

    Returns the user agent that made to perform the current request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string?", "description" : "The user agent used to perform this request of the empty sequence if there was no User-Agent header in the request." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.w3.org/2005/xpath-functions" : { "ns" : "http://www.w3.org/2005/xpath-functions", "description" : " This module contains all the functions specified in the\n W3C XPath and XQuery Functions and Operators 3.0.\n", "sees" : [ "http://www.w3.org/TR/xpath-functions-30/" ], "authors" : [ "www.w3c.org" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "QName", "qname" : "fn:QName", "signature" : "($paramURI as xs:string?, $paramQName as xs:string) as xs:QName external", "description" : "

    Constructs an xs:QName value given a namespace URI and a lexical\n QName.

    This function is deterministic, context-independent, and focus-independent.

    The namespace URI in the returned QName is taken from $paramURI. If\n $paramURI is the zero-length string or the empty sequence, it represents\n \"no namespace\".

    The prefix (or absence of a prefix) in $paramQName is retained in the\n returned xs:QName value.

    The local name in the result is taken from the local part of\n $paramQName.

    A dynamic error is raised if $paramQName does\n not have the correct lexical form for an instance of xs:QName.

    A dynamic error is raised if $paramURI is the\n zero-length string or the empty sequence, and the value of $paramQName\n contains a colon (:).

    A dynamic error may be raised if $paramURI is not a valid URI (XML Namespaces 1.0) or\n IRI (XML Namespaces 1.1).

    \n", "summary" : "

    Constructs an xs:QName value given a namespace URI and a lexical\n QName.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "paramURI", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "paramQName", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:QName", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "abs", "qname" : "fn:abs", "signature" : "($arg as numeric?) as numeric? external", "description" : "

    Returns the absolute value of $arg.

    This function is deterministic, context-independent, and focus-independent.

    General rules: see .

    If $arg is negative the function returns -$arg, otherwise it\n returns $arg.

    If the type of $arg is one of the four numeric types xs:float,\n xs:double, xs:decimal or xs:integer the type\n of the result is the same as the type of $arg. If the type of\n $arg is a type derived from one of the numeric types, the result is an\n instance of the base numeric type.

    For xs:float and xs:double arguments, if the argument is\n positive zero or negative zero, then positive zero is returned. If the argument is\n positive or negative infinity, positive infinity is returned.

    For detailed type semantics, see [Formal Semantics].

    The expression fn:abs(10.5) returns 10.5.

    The expression fn:abs(-10.5) returns 10.5.

    \n", "summary" : "

    Returns the absolute value of $arg .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "numeric", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "numeric?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "adjust-date-to-timezone", "qname" : "fn:adjust-date-to-timezone", "signature" : "($arg as xs:date?) as xs:date? external", "description" : "

    Adjusts an xs:date value to a specific timezone, or to no timezone\n at all; the result is the date in the target timezone that contains the starting instant\n of the supplied date.

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone.\n \t

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    If $timezone is not specified, then the effective value of\n $timezone is the value of the implicit timezone in the dynamic\n context.

    If $arg is the empty sequence, then the function returns the empty\n sequence.

    If $arg does not have a timezone component and $timezone is\n the empty sequence, then the result is the value of $arg.

    If $arg does not have a timezone component and $timezone is\n not the empty sequence, then the result is $arg with $timezone\n as the timezone component.

    If $arg has a timezone component and $timezone is the empty\n sequence, then the result is the local value of $arg without its timezone\n component.

    If $arg has a timezone component and $timezone is not the\n empty sequence, then the function returns the value of the expression:

    Let $dt be the value of fn:dateTime($arg,\n xs:time('00:00:00')).

    Let $adt be the value of fn:adjust-dateTime-to-timezone($dt,\n $timezone)

    The function returns the value of xs:date($adt)

    A dynamic error is raised if $timezone is less\n than -PT14H or greater than PT14H or is not an integral number\n of minutes.

    \n", "summary" : "

    Adjusts an xs:date value to a specific timezone, or to no timezone\n at all; the result is the date in the target timezone that contains the starting instant\n of the supplied date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:date", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:date?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "adjust-date-to-timezone", "qname" : "fn:adjust-date-to-timezone", "signature" : "($arg as xs:date?, $timezone as xs:dayTimeDuration?) as xs:date? external", "description" : "

    Adjusts an xs:date value to a specific timezone, or to no timezone\n at all; the result is the date in the target timezone that contains the starting instant\n of the supplied date.

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone.\n \t

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    If $timezone is not specified, then the effective value of\n $timezone is the value of the implicit timezone in the dynamic\n context.

    If $arg is the empty sequence, then the function returns the empty\n sequence.

    If $arg does not have a timezone component and $timezone is\n the empty sequence, then the result is the value of $arg.

    If $arg does not have a timezone component and $timezone is\n not the empty sequence, then the result is $arg with $timezone\n as the timezone component.

    If $arg has a timezone component and $timezone is the empty\n sequence, then the result is the local value of $arg without its timezone\n component.

    If $arg has a timezone component and $timezone is not the\n empty sequence, then the function returns the value of the expression:

    Let $dt be the value of fn:dateTime($arg,\n xs:time('00:00:00')).

    Let $adt be the value of fn:adjust-dateTime-to-timezone($dt,\n $timezone)

    The function returns the value of xs:date($adt)

    A dynamic error is raised if $timezone is less\n than -PT14H or greater than PT14H or is not an integral number\n of minutes.

    \n", "summary" : "

    Adjusts an xs:date value to a specific timezone, or to no timezone\n at all; the result is the date in the target timezone that contains the starting instant\n of the supplied date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:date", "occurrence" : "?", "description" : "" }, { "name" : "timezone", "type" : "xs:dayTimeDuration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:date?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "adjust-dateTime-to-timezone", "qname" : "fn:adjust-dateTime-to-timezone", "signature" : "($arg as xs:dateTime?) as xs:dateTime external", "description" : "

    Adjusts an xs:dateTime value to a specific timezone, or to no\n timezone at all.

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone.\n \t

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    If $timezone is not specified, then the effective value of\n $timezone is the value of the implicit timezone in the dynamic\n context.

    If $arg is the empty sequence, then the function returns the empty\n sequence.

    If $arg does not have a timezone component and $timezone is\n the empty sequence, then the result is $arg.

    If $arg does not have a timezone component and $timezone is\n not the empty sequence, then the result is $arg with $timezone\n as the timezone component.

    If $arg has a timezone component and $timezone is the empty\n sequence, then the result is the local value of $arg without its timezone\n component.

    If $arg has a timezone component and $timezone is not the\n empty sequence, then the result is the xs:dateTime value that is equal to\n $arg and that has a timezone component equal to\n $timezone.

    A dynamic error is raised if $timezone is less\n than -PT14H or greater than PT14H or is not an integral number\n of minutes.

    \n", "summary" : "

    Adjusts an xs:dateTime value to a specific timezone, or to no\n timezone at all.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:dateTime", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:dateTime", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "adjust-dateTime-to-timezone", "qname" : "fn:adjust-dateTime-to-timezone", "signature" : "($arg as xs:dateTime?, $timezone as xs:dayTimeDuration?) as xs:dateTime external", "description" : "

    Adjusts an xs:dateTime value to a specific timezone, or to no\n timezone at all.

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone.\n \t

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    If $timezone is not specified, then the effective value of\n $timezone is the value of the implicit timezone in the dynamic\n context.

    If $arg is the empty sequence, then the function returns the empty\n sequence.

    If $arg does not have a timezone component and $timezone is\n the empty sequence, then the result is $arg.

    If $arg does not have a timezone component and $timezone is\n not the empty sequence, then the result is $arg with $timezone\n as the timezone component.

    If $arg has a timezone component and $timezone is the empty\n sequence, then the result is the local value of $arg without its timezone\n component.

    If $arg has a timezone component and $timezone is not the\n empty sequence, then the result is the xs:dateTime value that is equal to\n $arg and that has a timezone component equal to\n $timezone.

    A dynamic error is raised if $timezone is less\n than -PT14H or greater than PT14H or is not an integral number\n of minutes.

    \n", "summary" : "

    Adjusts an xs:dateTime value to a specific timezone, or to no\n timezone at all.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:dateTime", "occurrence" : "?", "description" : "" }, { "name" : "timezone", "type" : "xs:dayTimeDuration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:dateTime", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "adjust-time-to-timezone", "qname" : "fn:adjust-time-to-timezone", "signature" : "($arg as xs:time?) as xs:time? external", "description" : "

    Adjusts an xs:time value to a specific timezone, or to no timezone\n at all.

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone.\n \t

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    If $timezone is not specified, then the effective value of\n $timezone is the value of the implicit timezone in the dynamic\n context.

    If $arg is the empty sequence, then the function returns the empty\n sequence.

    If $arg does not have a timezone component and $timezone is\n the empty sequence, then the result is $arg.

    If $arg does not have a timezone component and $timezone is\n not the empty sequence, then the result is $arg with $timezone\n as the timezone component.

    If $arg has a timezone component and $timezone is the empty\n sequence, then the result is the localized value of $arg without its\n timezone component.

    If $arg has a timezone component and $timezone is not the\n empty sequence, then:

    Let $dt be the xs:dateTime value\n fn:dateTime(xs:date('1972-12-31'), $arg).

    Let $adt be the value of fn:adjust-dateTime-to-timezone($dt,\n $timezone)\n

    The function returns the xs:time value\n xs:time($adt).

    A dynamic error is raised if $timezone is less\n than -PT14H or greater than PT14H or if does not contain an\n integral number of minutes.

    \n", "summary" : "

    Adjusts an xs:time value to a specific timezone, or to no timezone\n at all.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:time", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:time?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "adjust-time-to-timezone", "qname" : "fn:adjust-time-to-timezone", "signature" : "($arg as xs:time?, $timezone as xs:dayTimeDuration?) as xs:time? external", "description" : "

    Adjusts an xs:time value to a specific timezone, or to no timezone\n at all.

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone.\n \t

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    If $timezone is not specified, then the effective value of\n $timezone is the value of the implicit timezone in the dynamic\n context.

    If $arg is the empty sequence, then the function returns the empty\n sequence.

    If $arg does not have a timezone component and $timezone is\n the empty sequence, then the result is $arg.

    If $arg does not have a timezone component and $timezone is\n not the empty sequence, then the result is $arg with $timezone\n as the timezone component.

    If $arg has a timezone component and $timezone is the empty\n sequence, then the result is the localized value of $arg without its\n timezone component.

    If $arg has a timezone component and $timezone is not the\n empty sequence, then:

    Let $dt be the xs:dateTime value\n fn:dateTime(xs:date('1972-12-31'), $arg).

    Let $adt be the value of fn:adjust-dateTime-to-timezone($dt,\n $timezone)\n

    The function returns the xs:time value\n xs:time($adt).

    A dynamic error is raised if $timezone is less\n than -PT14H or greater than PT14H or if does not contain an\n integral number of minutes.

    \n", "summary" : "

    Adjusts an xs:time value to a specific timezone, or to no timezone\n at all.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:time", "occurrence" : "?", "description" : "" }, { "name" : "timezone", "type" : "xs:dayTimeDuration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:time?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "analyze-string", "qname" : "fn:analyze-string", "signature" : "($input as xs:string?, $pattern as xs:string) as element(fn:analyze-string-result) external", "description" : "

    Analyzes a string using a regular expression, returning an XML structure that\n identifies which parts of the input string matched or failed to match the regular\n expression, and in the case of matched substrings, which substrings matched each\n capturing group in the regular expression.

    This function is nondeterministic, context-independent, and focus-independent.

    The effect of calling the first version of this function (omitting the argument\n $flags) is the same as the effect of calling the second version with the\n $flags argument set to a zero-length string. Flags are defined in\n .

    The $flags argument is interpreted in the same way as for the\n fn:matches function.

    If $input is the empty sequence the function behaves as if\n $input were the zero-length string. In this situation the result will be\n an element node with no children.

    The function returns an element node whose local name is\n analyze-string-result. This element and all its descendant elements have\n the namespace URI http://www.w3.org/2005/xpath-functions. The namespace\n prefix is . The children of this element are a\n sequence of fn:match and fn:non-match elements. This sequence\n is formed by breaking the $input string into a sequence of strings,\n returning any substring that matches $pattern as the content of a\n match element, and any intervening substring as the content of a\n non-match element.

    More specifically, the function starts at the beginning of the input string and attempts\n to find the first substring that matches the regular expression. If there are several\n matches, the first match is defined to be the one whose starting position comes first in\n the string. If several alternatives within the regular expression both match at the same\n position in the input string, then the match that is chosen is the first alternative\n that matches. For example, if the input string is The quick brown fox jumps\n and the regular expression is jump|jumps, then the match that is chosen is\n jump.

    Having found the first match, the instruction proceeds to find the second and subsequent\n matches by repeating the search, starting at the first character that was not included in the previous match.

    The input string is thus partitioned into a sequence of substrings, some of which match\n the regular expression, others which do not match it. Each substring will contain at\n least one character. This sequence is represented in the result by the sequence of\n fn:match and fn:non-match children of the returned element\n node; the string value of the fn:match or fn:non-match element\n will be the corresponding substring of $input, and the string value of the\n returned element node will therefore be the same as $input.

    The content of an fn:non-match element is always a single text node.

    The content of a fn:match element, however, is in general a sequence of\n text nodes and fn:group element children. An fn:group element\n with a nr attribute having the integer value N identifies the\n substring captured by the Nth parenthesized sub-expression in the regular\n expression. For each capturing subexpression there will be at most one corresponding\n fn:group element in each fn:match element in the\n result.

    If the function is called twice with the same arguments, it is whether the two calls return the same element node\n or distinct (but deep equal) element nodes. In this respect it is\n nondeterministic.

    The base URI of the element nodes in the result is\n

    A schema is defined for the structure of the returned element, containing the\n definitions below. The returned element and its descendants will have type annotations\n obtained by validating the returned element against this schema, unless the function is\n used in an environment where type annotations are not supported (for example, a Basic\n XSLT Processor), in which case the elements will all be annotated as\n xs:untyped and the attributes as xs:untypedAtomic.

    A free-standing copy of this schema can be found at analyze-string.xsd

    \n <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n <xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n targetNamespace=\"http://www.w3.org/2005/xpath-functions\"\n xmlns:fn=\"http://www.w3.org/2005/xpath-functions\"\n elementFormDefault=\"qualified\">\n <xs:element name=\"analyze-string-result\" type=\"fn:analyze-string-result-type\"/>\n <xs:element name=\"match\" type=\"fn:match-type\"/>\n <xs:element name=\"non-match\" type=\"xs:string\"/>\n <xs:element name=\"group\" type=\"fn:group-type\"/>\n <xs:complexType name=\"analyze-string-result-type\" mixed=\"true\">\n <xs:choice minOccurs=\"0\" maxOccurs=\"unbounded\">\n <xs:element ref=\"fn:match\"/>\n <xs:element ref=\"fn:non-match\"/>\n </xs:choice>\n </xs:complexType>\n <xs:complexType name=\"match-type\" mixed=\"true\">\n <xs:sequence>\n <xs:element ref=\"fn:group\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n </xs:sequence>\n </xs:complexType>\n <xs:complexType name=\"group-type\" mixed=\"true\">\n <xs:sequence>\n <xs:element ref=\"fn:group\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n </xs:sequence>\n <xs:attribute name=\"nr\" type=\"xs:positiveInteger\"/>\n </xs:complexType>\n </xs:schema>\n \n

    A dynamic error is raised if the value of\n $pattern is invalid according to the rules described in section .

    A dynamic error is raised if the value of\n $flags is invalid according to the rules described in section .

    A dynamic error is raised if the supplied\n $pattern matches a zero-length string, that is, if fn:matches(\"\",\n $pattern, $flags) returns true.

    \n", "summary" : "

    Analyzes a string using a regular expression, returning an XML structure that\n identifies which parts of the input string matched or failed to match the regular\n expression, and in the case of matched substrings, which substrings matched each\n capturing group in the regular expression.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "element(fn:analyze-string-result)", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "analyze-string", "qname" : "fn:analyze-string", "signature" : "($input as xs:string?, $pattern as xs:string, $flags as xs:string) as element(fn:analyze-string-result) external", "description" : "

    Analyzes a string using a regular expression, returning an XML structure that\n identifies which parts of the input string matched or failed to match the regular\n expression, and in the case of matched substrings, which substrings matched each\n capturing group in the regular expression.

    This function is nondeterministic, context-independent, and focus-independent.

    The effect of calling the first version of this function (omitting the argument\n $flags) is the same as the effect of calling the second version with the\n $flags argument set to a zero-length string. Flags are defined in\n .

    The $flags argument is interpreted in the same way as for the\n fn:matches function.

    If $input is the empty sequence the function behaves as if\n $input were the zero-length string. In this situation the result will be\n an element node with no children.

    The function returns an element node whose local name is\n analyze-string-result. This element and all its descendant elements have\n the namespace URI http://www.w3.org/2005/xpath-functions. The namespace\n prefix is . The children of this element are a\n sequence of fn:match and fn:non-match elements. This sequence\n is formed by breaking the $input string into a sequence of strings,\n returning any substring that matches $pattern as the content of a\n match element, and any intervening substring as the content of a\n non-match element.

    More specifically, the function starts at the beginning of the input string and attempts\n to find the first substring that matches the regular expression. If there are several\n matches, the first match is defined to be the one whose starting position comes first in\n the string. If several alternatives within the regular expression both match at the same\n position in the input string, then the match that is chosen is the first alternative\n that matches. For example, if the input string is The quick brown fox jumps\n and the regular expression is jump|jumps, then the match that is chosen is\n jump.

    Having found the first match, the instruction proceeds to find the second and subsequent\n matches by repeating the search, starting at the first character that was not included in the previous match.

    The input string is thus partitioned into a sequence of substrings, some of which match\n the regular expression, others which do not match it. Each substring will contain at\n least one character. This sequence is represented in the result by the sequence of\n fn:match and fn:non-match children of the returned element\n node; the string value of the fn:match or fn:non-match element\n will be the corresponding substring of $input, and the string value of the\n returned element node will therefore be the same as $input.

    The content of an fn:non-match element is always a single text node.

    The content of a fn:match element, however, is in general a sequence of\n text nodes and fn:group element children. An fn:group element\n with a nr attribute having the integer value N identifies the\n substring captured by the Nth parenthesized sub-expression in the regular\n expression. For each capturing subexpression there will be at most one corresponding\n fn:group element in each fn:match element in the\n result.

    If the function is called twice with the same arguments, it is whether the two calls return the same element node\n or distinct (but deep equal) element nodes. In this respect it is\n nondeterministic.

    The base URI of the element nodes in the result is\n

    A schema is defined for the structure of the returned element, containing the\n definitions below. The returned element and its descendants will have type annotations\n obtained by validating the returned element against this schema, unless the function is\n used in an environment where type annotations are not supported (for example, a Basic\n XSLT Processor), in which case the elements will all be annotated as\n xs:untyped and the attributes as xs:untypedAtomic.

    A free-standing copy of this schema can be found at analyze-string.xsd

    \n <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n <xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n targetNamespace=\"http://www.w3.org/2005/xpath-functions\"\n xmlns:fn=\"http://www.w3.org/2005/xpath-functions\"\n elementFormDefault=\"qualified\">\n <xs:element name=\"analyze-string-result\" type=\"fn:analyze-string-result-type\"/>\n <xs:element name=\"match\" type=\"fn:match-type\"/>\n <xs:element name=\"non-match\" type=\"xs:string\"/>\n <xs:element name=\"group\" type=\"fn:group-type\"/>\n <xs:complexType name=\"analyze-string-result-type\" mixed=\"true\">\n <xs:choice minOccurs=\"0\" maxOccurs=\"unbounded\">\n <xs:element ref=\"fn:match\"/>\n <xs:element ref=\"fn:non-match\"/>\n </xs:choice>\n </xs:complexType>\n <xs:complexType name=\"match-type\" mixed=\"true\">\n <xs:sequence>\n <xs:element ref=\"fn:group\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n </xs:sequence>\n </xs:complexType>\n <xs:complexType name=\"group-type\" mixed=\"true\">\n <xs:sequence>\n <xs:element ref=\"fn:group\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n </xs:sequence>\n <xs:attribute name=\"nr\" type=\"xs:positiveInteger\"/>\n </xs:complexType>\n </xs:schema>\n \n

    A dynamic error is raised if the value of\n $pattern is invalid according to the rules described in section .

    A dynamic error is raised if the value of\n $flags is invalid according to the rules described in section .

    A dynamic error is raised if the supplied\n $pattern matches a zero-length string, that is, if fn:matches(\"\",\n $pattern, $flags) returns true.

    \n", "summary" : "

    Analyzes a string using a regular expression, returning an XML structure that\n identifies which parts of the input string matched or failed to match the regular\n expression, and in the case of matched substrings, which substrings matched each\n capturing group in the regular expression.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "flags", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "element(fn:analyze-string-result)", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "available-environment-variables", "qname" : "fn:available-environment-variables", "signature" : "() as xs:string* external", "description" : "

    Returns a list of environment variable names that are suitable for passing to\n fn:environment-variable, as a (possibly empty) sequence of strings.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tenvironment variables.\n \t

    The function returns a sequence of strings, being the names of the environment variables\n in the dynamic context in some implementation-dependent order.

    The function is deterministic: that is, the\n set of available environment variables does not vary during evaluation.

    The function returns a list of strings, containing no duplicates.

    It is intended that the strings in this list should be suitable for passing to\n fn:environment-variable.

    See also the note on security under the definition of the\n fn:environment-variable function. If access to environment variables has\n been disabled, fn:available-environment-variables always returns the empty\n sequence.

    \n", "summary" : "

    Returns a list of environment variable names that are suitable for passing to\n fn:environment-variable , as a (possibly empty) sequence of strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "available-environment-variables", "qname" : "fn:available-environment-variables", "signature" : "() as xs:string* external", "description" : "

    Returns a list of environment variable names that are suitable for passing to\n fn:environment-variable, as a (possibly empty) sequence of strings.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tenvironment variables.\n \t

    The function returns a sequence of strings, being the names of the environment variables\n in the dynamic context in some implementation-dependent order.

    The function is deterministic: that is, the\n set of available environment variables does not vary during evaluation.

    The function returns a list of strings, containing no duplicates.

    It is intended that the strings in this list should be suitable for passing to\n fn:environment-variable.

    See also the note on security under the definition of the\n fn:environment-variable function. If access to environment variables has\n been disabled, fn:available-environment-variables always returns the empty\n sequence.

    \n", "summary" : "

    Returns a list of environment variable names that are suitable for passing to\n fn:environment-variable , as a (possibly empty) sequence of strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "avg", "qname" : "fn:avg", "signature" : "($arg as xs:anyAtomicType*) as xs:anyAtomicType? external", "description" : "

    Returns the average of the values in the input sequence $arg, that\n is, the sum of the values divided by the number of values.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the empty sequence is returned.

    If $arg contains values of type xs:untypedAtomic they are cast\n to xs:double.

    Duration values must either all be xs:yearMonthDuration values or must all\n be xs:dayTimeDuration values. For numeric values, the numeric promotion\n rules defined in are used to promote all values to a single\n common type. After these operations, $arg must contain items of a single\n type, which must be one of the four numeric types, xs:yearMonthDuration or\n xs:dayTimeDuration or one if its subtypes.

    The function returns the average of the values as sum($arg) div\n count($arg); but the implementation may use an otherwise equivalent algorithm\n that avoids arithmetic overflow.

    For detailed type semantics, see [Formal Semantics].

    A type error is raised if the input sequence contains\n items of incompatible types, as described above.

    \n", "summary" : "

    Returns the average of the values in the input sequence $arg , that\n is, the sum of the values divided by the number of values.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:anyAtomicType?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "base-uri", "qname" : "fn:base-uri", "signature" : "() as xs:anyURI? external", "description" : "

    Returns the base URI of a node.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    The zero-argument version of the function returns the base URI of the\n context node: it is equivalent to calling fn:base-uri(.).

    The single-argument version of the function behaves as follows:

    If $arg is the empty sequence, the function returns the empty\n sequence.Otherwise, the function returns the value of the dm:base-uri accessor\n applied to the node $arg. This accessor is defined, for each kind of\n node, in the XDM specification (See ).As explained in XDM, document, element and processing-instruction nodes have a\n base-uri property which may be empty. The base-uri property for all other node kinds is\n the empty sequence. The dm:base-uri accessor returns the base-uri property of a node if\n it exists and is non-empty; otherwise it returns the result of applying the dm:base-uri\n accessor to its parent, recursively. If the node does not have a parent, or if the\n recursive ascent up the ancestor chain encounters a parentless node whose base-uri\n property is empty, the empty sequence is returned. In the case of namespace nodes,\n however, the result is always an empty sequence -- it does not depend on the base URI of\n the parent element.

    See also fn:static-base-uri.

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the base URI of a node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:anyURI?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "base-uri", "qname" : "fn:base-uri", "signature" : "($arg as node()?) as xs:anyURI? external", "description" : "

    Returns the base URI of a node.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    The zero-argument version of the function returns the base URI of the\n context node: it is equivalent to calling fn:base-uri(.).

    The single-argument version of the function behaves as follows:

    If $arg is the empty sequence, the function returns the empty\n sequence.Otherwise, the function returns the value of the dm:base-uri accessor\n applied to the node $arg. This accessor is defined, for each kind of\n node, in the XDM specification (See ).As explained in XDM, document, element and processing-instruction nodes have a\n base-uri property which may be empty. The base-uri property for all other node kinds is\n the empty sequence. The dm:base-uri accessor returns the base-uri property of a node if\n it exists and is non-empty; otherwise it returns the result of applying the dm:base-uri\n accessor to its parent, recursively. If the node does not have a parent, or if the\n recursive ascent up the ancestor chain encounters a parentless node whose base-uri\n property is empty, the empty sequence is returned. In the case of namespace nodes,\n however, the result is always an empty sequence -- it does not depend on the base URI of\n the parent element.

    See also fn:static-base-uri.

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the base URI of a node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "node()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:anyURI?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "boolean", "qname" : "fn:boolean", "signature" : "($arg as item()*) as xs:boolean external", "description" : "

    Computes the effective boolean value of the sequence $arg.

    The function computes the effective boolean value of a sequence, defined according to\n the following rules. See also .

    If $arg is the empty sequence, fn:boolean returns\n false.

    If $arg is a sequence whose first item is a node,\n fn:boolean returns true.

    If $arg is a singleton value of type xs:boolean or a\n derived from xs:boolean, fn:boolean returns\n $arg.

    If $arg is a singleton value of type xs:string or a type\n derived from xs:string, xs:anyURI or a type derived from\n xs:anyURI or xs:untypedAtomic,\n fn:boolean returns false if the operand value has\n zero length; otherwise it returns true.

    If $arg is a singleton value of any numeric type or a type derived\n from a numeric type, fn:boolean returns false if the\n operand value is NaN or is numerically equal to zero; otherwise it\n returns true.

    In all other cases, fn:boolean raises a type error .

    The static semantics of this function are described in [Formal\n Semantics].

    The result of this function is not necessarily the same as $arg cast as\n xs:boolean. For example, fn:boolean(\"false\") returns the value\n true whereas \"false\" cast as xs:boolean (which can also be\n written xs:boolean(\"false\")) returns false.

    let $abc := (\"a\", \"b\", \"\")

    fn:boolean($abc) raises a type error .

    The expression fn:boolean($abc[1]) returns true().

    The expression fn:boolean($abc[0]) returns false().

    The expression fn:boolean($abc[3]) returns false().

    \n", "summary" : "

    Computes the effective boolean value of the sequence $arg .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "ceiling", "qname" : "fn:ceiling", "signature" : "($arg as numeric?) as numeric? external", "description" : "

    Rounds $arg upwards to a whole number.

    This function is deterministic, context-independent, and focus-independent.

    General rules: see .

    The function returns the smallest (closest to negative infinity) number with no\n fractional part that is not less than the value of $arg.

    If the type of $arg is one of the four numeric types xs:float,\n xs:double, xs:decimal or xs:integer the type\n of the result is the same as the type of $arg. If the type of\n $arg is a type derived from one of the numeric types, the result is an\n instance of the base numeric type.

    For xs:float and xs:double arguments, if the argument is\n positive zero, then positive zero is returned. If the argument is negative zero, then\n negative zero is returned. If the argument is less than zero and greater than -1,\n negative zero is returned.

    For detailed type semantics, see [Formal Semantics].

    The expression fn:ceiling(10.5) returns 11.

    The expression fn:ceiling(-10.5) returns -10.

    \n", "summary" : "

    Rounds $arg upwards to a whole number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "numeric", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "numeric?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "codepoint-equal", "qname" : "fn:codepoint-equal", "signature" : "($comparand1 as xs:string?, $comparand2 as xs:string?) as xs:boolean? external", "description" : "

    Returns true if two strings are equal, considered codepoint-by-codepoint.

    This function is deterministic, context-independent, and focus-independent.

    If either argument is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns true or false depending on\n whether the value of $comparand1 is equal to the value of\n $comparand2, according to the Unicode codepoint collation\n (http://www.w3.org/2005/xpath-functions/collation/codepoint).

    This function allows xs:anyURI values to be compared without having to\n specify the Unicode codepoint collation.

    \n", "summary" : "

    Returns true if two strings are equal, considered codepoint-by-codepoint.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "comparand1", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "comparand2", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:boolean?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "codepoints-to-string", "qname" : "fn:codepoints-to-string", "signature" : "($arg as xs:integer*) as xs:string external", "description" : "

    Creates an xs:string from a sequence of codepoints.

    This function is deterministic, context-independent, and focus-independent.

    The function returns the string made up from the characters whose Unicode codepoints are\n supplied in $arg. This will be the zero-length string if $arg\n is the empty sequence.

    A dynamic error is raised if any of the codepoints in\n $arg is not a permitted XML character.

    \n", "summary" : "

    Creates an xs:string from a sequence of codepoints .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:integer", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "codepoints-to-string", "qname" : "fn:codepoints-to-string", "signature" : "($arg as xs:integer*) as xs:string external", "description" : "

    Creates an xs:string from a sequence of codepoints.

    This function is deterministic, context-independent, and focus-independent.

    The function returns the string made up from the characters whose Unicode codepoints are\n supplied in $arg. This will be the zero-length string if $arg\n is the empty sequence.

    A dynamic error is raised if any of the codepoints in\n $arg is not a permitted XML character.

    \n", "summary" : "

    Creates an xs:string from a sequence of codepoints .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:integer", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "collection", "qname" : "fn:collection", "signature" : "() as node()* external", "description" : "

    Returns a sequence of nodes representing a collection of documents indentified\n by a collection URI; or a default collection if no URI is supplied.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tavailable node collections, and static base uri.\n \t

    This function takes an xs:string as argument and returns a sequence of\n nodes obtained by interpreting $arg as an xs:anyURI and\n resolving it according to the mapping specified in Available node collections\n described in .

    If Available node collections provides a mapping from this string to a sequence\n of nodes, the function returns that sequence. If Available node collections maps\n the string to an empty sequence, then the function returns an empty sequence.

    If $arg is not specified, the function returns the sequence of the nodes in\n the default node collection in the dynamic context. See .

    If the value of $arg is a relative xs:anyURI, it is resolved\n against the value of the base-URI property from the static context.

    If $arg is the empty sequence, the function behaves as if it had been\n called without an argument. See above.

    By default, this function is deterministic.\n This means that repeated\n calls on the function with the same argument will return the same result. However, for\n performance reasons, implementations may provide a user option to evaluate the function\n without a guarantee of determinism. The manner in which any such option is provided is\n . If the user has not selected such an option,\n a call to this function must either return a deterministic result or must raise a dynamic error\n .

    There is no requirement that the returned nodes should be in document\n order, nor is there a requirement that the result should contain no duplicates.

    For detailed type semantics, see [Formal Semantics].

    A dynamic error is raised if no URI is supplied and the\n value of the default collection is absent.

    A dynamic error is raised if available\n node collections provides no mapping for the absolutized URI.

    A dynamic error is raised if $arg is not a\n valid xs:anyURI.

    \n", "summary" : "

    Returns a sequence of nodes representing a collection of documents indentified\n by a collection URI; or a default collection if no URI is supplied.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "collection", "qname" : "fn:collection", "signature" : "($arg as xs:string?) as node()* external", "description" : "

    Returns a sequence of nodes representing a collection of documents indentified\n by a collection URI; or a default collection if no URI is supplied.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tavailable node collections, and static base uri.\n \t

    This function takes an xs:string as argument and returns a sequence of\n nodes obtained by interpreting $arg as an xs:anyURI and\n resolving it according to the mapping specified in Available node collections\n described in .

    If Available node collections provides a mapping from this string to a sequence\n of nodes, the function returns that sequence. If Available node collections maps\n the string to an empty sequence, then the function returns an empty sequence.

    If $arg is not specified, the function returns the sequence of the nodes in\n the default node collection in the dynamic context. See .

    If the value of $arg is a relative xs:anyURI, it is resolved\n against the value of the base-URI property from the static context.

    If $arg is the empty sequence, the function behaves as if it had been\n called without an argument. See above.

    By default, this function is deterministic.\n This means that repeated\n calls on the function with the same argument will return the same result. However, for\n performance reasons, implementations may provide a user option to evaluate the function\n without a guarantee of determinism. The manner in which any such option is provided is\n . If the user has not selected such an option,\n a call to this function must either return a deterministic result or must raise a dynamic error\n .

    There is no requirement that the returned nodes should be in document\n order, nor is there a requirement that the result should contain no duplicates.

    For detailed type semantics, see [Formal Semantics].

    A dynamic error is raised if no URI is supplied and the\n value of the default collection is absent.

    A dynamic error is raised if available\n node collections provides no mapping for the absolutized URI.

    A dynamic error is raised if $arg is not a\n valid xs:anyURI.

    \n", "summary" : "

    Returns a sequence of nodes representing a collection of documents indentified\n by a collection URI; or a default collection if no URI is supplied.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "compare", "qname" : "fn:compare", "signature" : "($comparand1 as xs:string?, $comparand2 as xs:string?) as xs:integer? external", "description" : "

    Returns -1, 0, or 1, depending on whether $comparand1 collates\n before, equal to, or after $comparand2 according to the rules of a selected\n collation.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri.\n \t

    Returns -1, 0, or 1, depending on whether the value of the $comparand1 is\n respectively less than, equal to, or greater than the value of $comparand2,\n according to the rules of the collation that is used.

    The collation used by this function is determined according to the rules in .

    If either $comparand1 or $comparand2 is the empty sequence,\n the function returns the empty sequence.

    This function, called with the first signature, defines the semantics of the \"eq\", \"ne\",\n \"gt\", \"lt\", \"le\" and \"ge\" operators on xs:string values.

    The expression fn:compare('abc', 'abc') returns 0.

    The expression fn:compare('Strasse', 'Straße') returns 0. (Assuming the default collation includes provisions that equate\n ss and the (German) character ß\n (sharp-s). Otherwise, the returned value depends on the\n semantics of the default collation.).

    The expression fn:compare('Strasse', 'Straße',\n 'http://example.com/deutsch') returns 0. (Assuming the collation identified by the URI\n http://example.com/deutsch includes provisions that equate\n ss and the (German) character ß\n (sharp-s). Otherwise, the returned value depends on the\n semantics of that collation.).

    The expression fn:compare('Strassen', 'Straße') returns 1. (Assuming the default collation includes provisions that treat\n differences between ss and the (German) character ß\n (sharp-s) with less strength than the differences between the\n base characters, such as the final n. ).

    \n", "summary" : "

    Returns -1, 0, or 1, depending on whether $comparand1 collates\n before, equal to, or after $comparand2 according to the rules of a selected\n collation.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "comparand1", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "comparand2", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "compare", "qname" : "fn:compare", "signature" : "($comparand1 as xs:string?, $comparand2 as xs:string?, $collation as xs:string) as xs:integer? external", "description" : "

    Returns -1, 0, or 1, depending on whether $comparand1 collates\n before, equal to, or after $comparand2 according to the rules of a selected\n collation.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri.\n \t

    Returns -1, 0, or 1, depending on whether the value of the $comparand1 is\n respectively less than, equal to, or greater than the value of $comparand2,\n according to the rules of the collation that is used.

    The collation used by this function is determined according to the rules in .

    If either $comparand1 or $comparand2 is the empty sequence,\n the function returns the empty sequence.

    This function, called with the first signature, defines the semantics of the \"eq\", \"ne\",\n \"gt\", \"lt\", \"le\" and \"ge\" operators on xs:string values.

    The expression fn:compare('abc', 'abc') returns 0.

    The expression fn:compare('Strasse', 'Straße') returns 0. (Assuming the default collation includes provisions that equate\n ss and the (German) character ß\n (sharp-s). Otherwise, the returned value depends on the\n semantics of the default collation.).

    The expression fn:compare('Strasse', 'Straße',\n 'http://example.com/deutsch') returns 0. (Assuming the collation identified by the URI\n http://example.com/deutsch includes provisions that equate\n ss and the (German) character ß\n (sharp-s). Otherwise, the returned value depends on the\n semantics of that collation.).

    The expression fn:compare('Strassen', 'Straße') returns 1. (Assuming the default collation includes provisions that treat\n differences between ss and the (German) character ß\n (sharp-s) with less strength than the differences between the\n base characters, such as the final n. ).

    \n", "summary" : "

    Returns -1, 0, or 1, depending on whether $comparand1 collates\n before, equal to, or after $comparand2 according to the rules of a selected\n collation.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "comparand1", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "comparand2", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "collation", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "concat", "qname" : "fn:concat", "signature" : "($arg1 as xs:anyAtomicType?, $arg2 as xs:anyAtomicType?) as xs:string external", "description" : "

    Returns the concatenation of the string values of the arguments.

    \n The two-argument form of this function defines the semantics of the \"||\" operator.

    This function is deterministic, context-independent, and focus-independent.

    This function accepts two or more xs:anyAtomicType arguments and casts each\n one to xs:string. The function returns the xs:string that is\n the concatenation of the values of its arguments after conversion. If any argument is\n the empty sequence, that argument is treated as the zero-length string.

    The fn:concat function is specified to allow two or\n more arguments, which are concatenated together. This is the only function specified in\n this document that allows a variable number of arguments. This capability is retained\n for compatibility with .

    \n", "summary" : "

    Returns the concatenation of the string values of the arguments.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "" }, { "name" : "arg2", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "contains", "qname" : "fn:contains", "signature" : "($arg1 as xs:string?, $arg2 as xs:string?) as xs:boolean external", "description" : "

    Returns true if the string $arg1 contains $arg2 as a\n substring, taking collations into account.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri.\n \t

    If the value of $arg1 or $arg2 is the empty sequence, or\n contains only ignorable collation units, it is interpreted as the zero-length\n string.

    If the value of $arg2 is the zero-length string, then the function returns\n true.

    If the value of $arg1 is the zero-length string, the function returns\n false.

    The collation used by this function is determined according to the rules in .

    The function returns an xs:boolean indicating whether or not the value of\n $arg1 contains (at the beginning, at the end, or anywhere within) at\n least one sequence of collation units that provides a minimal match to the\n collation units in the value of $arg2, according to the collation that is\n used.

    Minimal match is defined in .

    A dynamic error may be raised if the\n specified collation does not support collation units.

    \n", "summary" : "

    Returns true if the string $arg1 contains $arg2 as a\n substring, taking collations into account.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "arg2", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "contains", "qname" : "fn:contains", "signature" : "($arg1 as xs:string?, $arg2 as xs:string?, $collation as xs:string) as xs:boolean external", "description" : "

    Returns true if the string $arg1 contains $arg2 as a\n substring, taking collations into account.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri.\n \t

    If the value of $arg1 or $arg2 is the empty sequence, or\n contains only ignorable collation units, it is interpreted as the zero-length\n string.

    If the value of $arg2 is the zero-length string, then the function returns\n true.

    If the value of $arg1 is the zero-length string, the function returns\n false.

    The collation used by this function is determined according to the rules in .

    The function returns an xs:boolean indicating whether or not the value of\n $arg1 contains (at the beginning, at the end, or anywhere within) at\n least one sequence of collation units that provides a minimal match to the\n collation units in the value of $arg2, according to the collation that is\n used.

    Minimal match is defined in .

    A dynamic error may be raised if the\n specified collation does not support collation units.

    \n", "summary" : "

    Returns true if the string $arg1 contains $arg2 as a\n substring, taking collations into account.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "arg2", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "collation", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "count", "qname" : "fn:count", "signature" : "($arg as item()*) as xs:integer external", "description" : "

    Returns the number of items in a sequence.

    This function is deterministic, context-independent, and focus-independent.

    The function returns the number of items in the value of $arg.

    Returns 0 if $arg is the empty sequence.

    \n", "summary" : "

    Returns the number of items in a sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "current-date", "qname" : "fn:current-date", "signature" : "() as xs:date external", "description" : "

    Returns the current date.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone.\n \t

    Returns xs:date(fn:current-dateTime()). This is an xs:date\n (with timezone) that is current at some time during the evaluation of a query or\n transformation in which fn:current-date is executed.

    This function is . The precise instant during the query or\n transformation represented by the value of fn:current-date is .

    The returned date will always have an associated timezone, which will always be the same\n as the implicit timezone in the dynamic context

    \n", "summary" : "

    Returns the current date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:date", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "current-dateTime", "qname" : "fn:current-dateTime", "signature" : "() as xs:dateTimeStamp external", "description" : "

    Returns the current date and time (with timezone).

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone.\n \t

    Returns the current dateTime (with timezone) from the dynamic context. (See .) This is an\n xs:dateTime that is current at some time during the evaluation of a\n query or transformation in which fn:current-dateTime is executed.

    This function is . The precise instant during the query or\n transformation represented by the value of fn:current-dateTime() is\n .

    If the implementation supports data types from XSD 1.1 then the\n returned value will be an instance of xs:dateTimeStamp. Otherwise, the only\n guarantees are that it will be an instance of xs:dateTime and will have a\n timezone component.

    The returned xs:dateTime will always have an associated timezone, which\n will always be the same as the implicit timezone in the dynamic context

    \n", "summary" : "

    Returns the current date and time (with timezone).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:dateTimeStamp", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "current-time", "qname" : "fn:current-time", "signature" : "() as xs:time external", "description" : "

    Returns the current time.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone.\n \t

    Returns xs:time(fn:current-dateTime()). This is an xs:time\n (with timezone) that is current at some time during the evaluation of a query or\n transformation in which fn:current-time is executed.

    This function is . The precise instant during the query or\n transformation represented by the value of fn:current-time() is .

    The returned time will always have an associated timezone, which will always be the same\n as the implicit timezone in the dynamic context

    \n", "summary" : "

    Returns the current time.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:time", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "data", "qname" : "fn:data", "signature" : "() as xs:anyAtomicType* external", "description" : "

    Returns the result of atomizing a sequence, that is, replacing all nodes in the\n sequence by their typed values.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item\n (.). The behavior of the function if the argument is omitted is exactly\n the same as if the context item had been passed as the argument.

    The result of fn:data is the sequence of atomic values produced by\n applying the following rules to each item in $arg:

    If the item is an atomic value, it is appended to the result sequence.

    If the item is a node, the typed value of the node is appended to the result\n sequence. The typed value is a sequence of zero or more atomic values:\n specifically, the result of the dm:typed-value accessor as defined in\n (See ).

    A type error is raised if an item in the\n sequence $arg is a node that does not have a typed value.

    A type error is raised \n if an item in the sequence $arg is a function item.

    A dynamic error is raised\n if $arg is omitted\n and the context item is absent.

    \n", "summary" : "

    Returns the result of atomizing a sequence, that is, replacing all nodes in the\n sequence by their typed values.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "data", "qname" : "fn:data", "signature" : "($arg as item()*) as xs:anyAtomicType* external", "description" : "

    Returns the result of atomizing a sequence, that is, replacing all nodes in the\n sequence by their typed values.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item\n (.). The behavior of the function if the argument is omitted is exactly\n the same as if the context item had been passed as the argument.

    The result of fn:data is the sequence of atomic values produced by\n applying the following rules to each item in $arg:

    If the item is an atomic value, it is appended to the result sequence.

    If the item is a node, the typed value of the node is appended to the result\n sequence. The typed value is a sequence of zero or more atomic values:\n specifically, the result of the dm:typed-value accessor as defined in\n (See ).

    A type error is raised if an item in the\n sequence $arg is a node that does not have a typed value.

    A type error is raised \n if an item in the sequence $arg is a function item.

    A dynamic error is raised\n if $arg is omitted\n and the context item is absent.

    \n", "summary" : "

    Returns the result of atomizing a sequence, that is, replacing all nodes in the\n sequence by their typed values.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "dateTime", "qname" : "fn:dateTime", "signature" : "($arg1 as xs:date?, $arg2 as xs:time?) as xs:dateTime? external", "description" : "

    Returns an xs:dateTime value created by combining an\n xs:date and an xs:time.

    This function is deterministic, context-independent, and focus-independent.

    If either $arg1 or $arg2 is the empty sequence the function\n returns the empty sequence.

    Otherwise, the function returns an xs:dateTime whose date component is\n equal to $arg1 and whose time component is equal to $arg2.

    The timezone of the result is computed as follows:

    If neither argument has a timezone, the result has no timezone.

    If exactly one of the arguments has a timezone, or if both arguments have the same\n timezone, the result has this timezone.

    A dynamic error is raised if the two arguments both have\n timezones and the timezones are different.

    \n", "summary" : "

    Returns an xs:dateTime value created by combining an\n xs:date and an xs:time .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:date", "occurrence" : "?", "description" : "" }, { "name" : "arg2", "type" : "xs:time", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:dateTime?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "day-from-date", "qname" : "fn:day-from-date", "signature" : "($arg as xs:date?) as xs:integer? external", "description" : "

    Returns the day component of an xs:date.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:integer between 1 and 31, both\n inclusive, representing the day component in the localized value of\n $arg.

    The expression fn:day-from-date(xs:date(\"1999-05-31-05:00\")) returns 31.

    The expression fn:day-from-date(xs:date(\"2000-01-01+05:00\")) returns 1.

    \n", "summary" : "

    Returns the day component of an xs:date .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:date", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "days-from-duration", "qname" : "fn:days-from-duration", "signature" : "($arg as xs:duration?) as xs:integer? external", "description" : "

    Returns the number of days in a duration.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:integer representing the days\n component in the value of $arg. The result is obtained by casting\n $arg to an xs:dayTimeDuration (see ) and then computing the days component as described in\n .

    If $arg is a negative duration then the result will be negative..

    If $arg is an xs:yearMonthDuration the function returns 0.

    The expression fn:days-from-duration(xs:dayTimeDuration(\"P3DT10H\")) returns 3.

    The expression fn:days-from-duration(xs:dayTimeDuration(\"P3DT55H\")) returns 5.

    The expression fn:days-from-duration(xs:yearMonthDuration(\"P3Y5M\")) returns 0.

    \n", "summary" : "

    Returns the number of days in a duration.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:duration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "deep-equal", "qname" : "fn:deep-equal", "signature" : "($parameter1 as item()*, $parameter2 as item()*) as xs:boolean external", "description" : "

    This function assesses whether two sequences are deep-equal to each other. To\n be deep-equal, they must contain items that are pairwise deep-equal; and for two items\n to be deep-equal, they must either be atomic values that compare equal, or nodes of the\n same kind, with the same name, whose children are deep-equal.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and implicit timezone.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri, and implicit timezone.\n \t

    The $collation argument identifies a collation which is used at all levels\n of recursion when strings are compared (but not when names are compared), according to\n the rules in .

    If the two sequences are both empty, the function returns true.

    If the two sequences are of different lengths, the function returns\n false.

    If the two sequences are of the same length, the function returns true if\n and only if every item in the sequence $parameter1 is deep-equal to the\n item at the same position in the sequence $parameter2. The rules for\n deciding whether two items are deep-equal follow.

    Call the two items $i1 and $i2 respectively.

    If $i1 and $i2 are both atomic values, they are deep-equal if\n and only if ($i1 eq $i2) is true, or if both values are\n NaN. If the eq operator is not defined for $i1\n and $i2, the function returns false.

    If one of the pair $i1 or $i2 is an atomic value and the\n other is not,\n \n the function returns false.

    If $i1 and $i2 are both nodes, they are compared as described\n below:

    If the two nodes are of different kinds, the result is false.

    If the two nodes are both document nodes then they are deep-equal if and only if\n the sequence $i1/(*|text()) is deep-equal to the sequence\n $i2/(*|text()).

    If the two nodes are both element nodes then they are deep-equal if and only if\n all of the following conditions are satisfied:

    The two nodes have the same name, that is (node-name($i1) eq\n node-name($i2)).

    Either both nodes are both annotated as having simple content or both nodes are\n annotated as having complex content. For this purpose \"simple content\" means either a simple\n type or a complex type with simple content; \"complex content\" means a complex type whose variety\n is mixed, element-only, or empty.

    It is a consequence of this rule that validating a document\n D against a schema will usually (but not necessarily) result in a document that is not deep-equal\n to D. The exception is when the schema allows all elements to have mixed content.

    The two nodes have the same number of attributes, and for every attribute\n $a1 in $i1/@* there exists an attribute\n $a2 in $i2/@* such that $a1 and\n $a2 are deep-equal.

    One of the following conditions holds:

    Both element nodes are annotated as having simple content\n (as defined in 3(b) above), and\n the typed value of $i1 is deep-equal to the typed value\n of $i2.

    Both element nodes have a type annotation that is a complex type with\n variety element-only, and the sequence $i1/* is\n deep-equal to the sequence $i2/*.

    Both element nodes have a type annotation that is a complex type with\n variety mixed, and the sequence $i1/(*|text()) is\n deep-equal to the sequence $i2/(*|text()).

    Both element nodes have a type annotation that is a complex type with\n variety empty.

    If the two nodes are both attribute nodes then they are deep-equal if and only if\n both the following conditions are satisfied:

    The two nodes have the same name, that is (node-name($i1) eq\n node-name($i2)).

    The typed value of $i1 is deep-equal to the typed value of\n $i2.

    If the two nodes are both processing instruction nodes or namespace bindings, then they are deep-equal if and\n only if both the following conditions are satisfied:

    The two nodes have the same name, that is (node-name($i1) eq\n node-name($i2)).

    The string value of $i1 is equal to the string value of\n $i2.

    If the two nodes are both namespace nodes, then they are deep-equal if and only\n if both the following conditions are satisfied:

    The two nodes either have the same name or are both nameless, that is\n fn:deep-equal(node-name($i1), node-name($i2)).

    The string value of $i1 is equal to the string value of\n $i2 when compared using the Unicode codepoint collation.

    If the two nodes are both text nodes or comment nodes, then they are deep-equal if\n and only if their string-values are equal.

    A type error is raised \n if either input sequence contains a function item.\n \n

    \n", "summary" : "

    This function assesses whether two sequences are deep-equal to each other.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "parameter1", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "parameter2", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "deep-equal", "qname" : "fn:deep-equal", "signature" : "($parameter1 as item()*, $parameter2 as item()*, $collation as xs:string) as xs:boolean external", "description" : "

    This function assesses whether two sequences are deep-equal to each other. To\n be deep-equal, they must contain items that are pairwise deep-equal; and for two items\n to be deep-equal, they must either be atomic values that compare equal, or nodes of the\n same kind, with the same name, whose children are deep-equal.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and implicit timezone.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri, and implicit timezone.\n \t

    The $collation argument identifies a collation which is used at all levels\n of recursion when strings are compared (but not when names are compared), according to\n the rules in .

    If the two sequences are both empty, the function returns true.

    If the two sequences are of different lengths, the function returns\n false.

    If the two sequences are of the same length, the function returns true if\n and only if every item in the sequence $parameter1 is deep-equal to the\n item at the same position in the sequence $parameter2. The rules for\n deciding whether two items are deep-equal follow.

    Call the two items $i1 and $i2 respectively.

    If $i1 and $i2 are both atomic values, they are deep-equal if\n and only if ($i1 eq $i2) is true, or if both values are\n NaN. If the eq operator is not defined for $i1\n and $i2, the function returns false.

    If one of the pair $i1 or $i2 is an atomic value and the\n other is not,\n \n the function returns false.

    If $i1 and $i2 are both nodes, they are compared as described\n below:

    If the two nodes are of different kinds, the result is false.

    If the two nodes are both document nodes then they are deep-equal if and only if\n the sequence $i1/(*|text()) is deep-equal to the sequence\n $i2/(*|text()).

    If the two nodes are both element nodes then they are deep-equal if and only if\n all of the following conditions are satisfied:

    The two nodes have the same name, that is (node-name($i1) eq\n node-name($i2)).

    Either both nodes are both annotated as having simple content or both nodes are\n annotated as having complex content. For this purpose \"simple content\" means either a simple\n type or a complex type with simple content; \"complex content\" means a complex type whose variety\n is mixed, element-only, or empty.

    It is a consequence of this rule that validating a document\n D against a schema will usually (but not necessarily) result in a document that is not deep-equal\n to D. The exception is when the schema allows all elements to have mixed content.

    The two nodes have the same number of attributes, and for every attribute\n $a1 in $i1/@* there exists an attribute\n $a2 in $i2/@* such that $a1 and\n $a2 are deep-equal.

    One of the following conditions holds:

    Both element nodes are annotated as having simple content\n (as defined in 3(b) above), and\n the typed value of $i1 is deep-equal to the typed value\n of $i2.

    Both element nodes have a type annotation that is a complex type with\n variety element-only, and the sequence $i1/* is\n deep-equal to the sequence $i2/*.

    Both element nodes have a type annotation that is a complex type with\n variety mixed, and the sequence $i1/(*|text()) is\n deep-equal to the sequence $i2/(*|text()).

    Both element nodes have a type annotation that is a complex type with\n variety empty.

    If the two nodes are both attribute nodes then they are deep-equal if and only if\n both the following conditions are satisfied:

    The two nodes have the same name, that is (node-name($i1) eq\n node-name($i2)).

    The typed value of $i1 is deep-equal to the typed value of\n $i2.

    If the two nodes are both processing instruction nodes or namespace bindings, then they are deep-equal if and\n only if both the following conditions are satisfied:

    The two nodes have the same name, that is (node-name($i1) eq\n node-name($i2)).

    The string value of $i1 is equal to the string value of\n $i2.

    If the two nodes are both namespace nodes, then they are deep-equal if and only\n if both the following conditions are satisfied:

    The two nodes either have the same name or are both nameless, that is\n fn:deep-equal(node-name($i1), node-name($i2)).

    The string value of $i1 is equal to the string value of\n $i2 when compared using the Unicode codepoint collation.

    If the two nodes are both text nodes or comment nodes, then they are deep-equal if\n and only if their string-values are equal.

    A type error is raised \n if either input sequence contains a function item.\n \n

    \n", "summary" : "

    This function assesses whether two sequences are deep-equal to each other.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "parameter1", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "parameter2", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "collation", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "default-collation", "qname" : "fn:default-collation", "signature" : "() as xs:string external", "description" : "

    Returns the value of the default collation property from the static context.\n

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations.\n \t

    Returns the value of the default collation property from the static context. Components\n of the static context are discussed in .

    The default collation property can never be absent. If it is not explicitly defined, a\n system defined default can be invoked. If this is not provided, the Unicode codepoint\n collation (http://www.w3.org/2005/xpath-functions/collation/codepoint) is\n used.

    \n", "summary" : "

    Returns the value of the default collation property from the static context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "distinct-values", "qname" : "fn:distinct-values", "signature" : "($arg as xs:anyAtomicType*) as xs:anyAtomicType* external", "description" : "

    Returns the values that appear in a sequence, with duplicates eliminated.

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and implicit timezone.\n \t

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri, and implicit timezone.\n \t

    The function returns the sequence that results from removing from $arg all\n but one of a set of values that are equal to one another. Values are compared using the\n eq operator, subject to the caveats defined below.

    Values of type xs:untypedAtomic are compared as if they were of type\n xs:string.

    Values that cannot be compared, because the eq operator is not defined for\n their types, are considered to be distinct.

    The collation used by this function is determined according to the rules in . This collation is used when string comparison is\n required.

    For xs:float and xs:double values, positive zero is equal to\n negative zero and, although NaN does not equal itself, if $arg\n contains multiple NaN values a single NaN is returned.

    If xs:dateTime, xs:date or xs:time values do not\n have a timezone, they are considered to have the implicit timezone provided by the\n dynamic context for the purpose of comparison. Note that xs:dateTime,\n xs:date or xs:time values can compare equal even if their\n timezones are different.

    The order in which the sequence of values is returned is .

    Which value of a set of values that compare equal is returned is .

    The static type of the result is a sequence of prime types as defined\n in [Formal Semantics].

    \n

    If the input sequence contains values of different numeric types that differ from\n each other by small amounts, then the eq operator is not transitive, because of\n rounding effects occurring during type promotion. In the situation where the input\n contains three values A, B, and C such that\n A eq B, B eq C, but A ne C, then the number\n of items in the result of the function (as well as the choice of which items are\n returned) is , subject only to the\n constraints that (a) no two items in the result sequence compare equal to each other,\n and (b) every input item that does not appear in the result sequence compares equal\n to some item that does appear in the result sequence.

    \n

    For example, this arises when computing:

    \n distinct-values(\n (xs:float('1.0'),\n xs:decimal('1.0000000000100000000001',\n xs:double( '1.00000000001'))\n

    because the values of type xs:float and xs:double both\n compare equal to the value of type xs:decimal but not equal to each\n other.

    \n

    If $arg is the empty sequence, the function returns the empty sequence.

    \n", "summary" : "

    Returns the values that appear in a sequence, with duplicates eliminated.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "distinct-values", "qname" : "fn:distinct-values", "signature" : "($arg as xs:anyAtomicType*, $collation as xs:string) as xs:anyAtomicType* external", "description" : "

    Returns the values that appear in a sequence, with duplicates eliminated.

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and implicit timezone.\n \t

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri, and implicit timezone.\n \t

    The function returns the sequence that results from removing from $arg all\n but one of a set of values that are equal to one another. Values are compared using the\n eq operator, subject to the caveats defined below.

    Values of type xs:untypedAtomic are compared as if they were of type\n xs:string.

    Values that cannot be compared, because the eq operator is not defined for\n their types, are considered to be distinct.

    The collation used by this function is determined according to the rules in . This collation is used when string comparison is\n required.

    For xs:float and xs:double values, positive zero is equal to\n negative zero and, although NaN does not equal itself, if $arg\n contains multiple NaN values a single NaN is returned.

    If xs:dateTime, xs:date or xs:time values do not\n have a timezone, they are considered to have the implicit timezone provided by the\n dynamic context for the purpose of comparison. Note that xs:dateTime,\n xs:date or xs:time values can compare equal even if their\n timezones are different.

    The order in which the sequence of values is returned is .

    Which value of a set of values that compare equal is returned is .

    The static type of the result is a sequence of prime types as defined\n in [Formal Semantics].

    \n

    If the input sequence contains values of different numeric types that differ from\n each other by small amounts, then the eq operator is not transitive, because of\n rounding effects occurring during type promotion. In the situation where the input\n contains three values A, B, and C such that\n A eq B, B eq C, but A ne C, then the number\n of items in the result of the function (as well as the choice of which items are\n returned) is , subject only to the\n constraints that (a) no two items in the result sequence compare equal to each other,\n and (b) every input item that does not appear in the result sequence compares equal\n to some item that does appear in the result sequence.

    \n

    For example, this arises when computing:

    \n distinct-values(\n (xs:float('1.0'),\n xs:decimal('1.0000000000100000000001',\n xs:double( '1.00000000001'))\n

    because the values of type xs:float and xs:double both\n compare equal to the value of type xs:decimal but not equal to each\n other.

    \n

    If $arg is the empty sequence, the function returns the empty sequence.

    \n", "summary" : "

    Returns the values that appear in a sequence, with duplicates eliminated.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "" }, { "name" : "collation", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "doc-available", "qname" : "fn:doc-available", "signature" : "($uri as xs:string?) as xs:boolean external", "description" : "

    The function returns true if and only if the function\n call fn:doc($uri) would return a document node.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tavailable documents, and static base uri.\n \t

    If $uri is an empty sequence, this function returns\n false.

    If a call on fn:doc($uri) would return a document\n node, this function returns true.

    A dynamic error is raised if\n $uri is not a valid URI according to the rules applied by the\n implementation of fn:doc.

    Otherwise, this function returns false.

    If this function returns true, then calling fn:doc($uri)\n within the same must return a document node. However,\n if nondeterministic processing has been selected for the fn:doc function,\n this guarantee is lost.

    \n", "summary" : "

    The function returns true if and only if the function\n call fn:doc($uri) would return a document node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "doc", "qname" : "fn:doc", "signature" : "($uri as xs:string?) as document()? external", "description" : "

    Retrieves a document using a URI supplied as an\n xs:string, and returns the corresponding document node.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tavailable documents, and static base uri.\n \t

    If $uri is the empty sequence, the result is an empty sequence.

    If $uri is a relative URI reference, it is resolved\n relative to the value of the Static Base URI property from the static context. The resulting\n absolute URI is promoted to an xs:string.

    If the Available documents described in provides a mapping from this string to a document\n node, the function returns that document node.

    The URI may include a fragment identifier.

    By default, this function is deterministic. Two calls on this function\n return the same document node if the same URI Reference (after resolution to an absolute\n URI Reference) is supplied to both calls. Thus, the following expression (if it does not\n raise an error) will always be true:

    doc(\"foo.xml\") is doc(\"foo.xml\")

    However, for performance reasons, implementations may provide a user option to evaluate\n the function without a guarantee of determinism. The manner in which any such option is\n provided is implementation-defined. If the user has not selected such an option, a call\n of the function must either return a deterministic result or must raise a dynamic error\n .

    For detailed type semantics, see [Formal Semantics].

    If $uri is read from a source document, it is generally appropriate to\n resolve it relative to the base URI property of the relevant node in the source\n document. This can be achieved by calling the fn:resolve-uri function,\n and passing the resulting absolute URI as an argument to the fn:doc\n function.

    If two calls to this function supply different absolute URI References as arguments, the\n same document node may be returned if the implementation can determine that the two\n arguments refer to the same resource.

    By defining the semantics of this function in terms of a string-to-document-node\n mapping in the dynamic context, the specification is acknowledging that the results of\n this function are outside the purview of the language specification itself, and depend\n entirely on the run-time environment in which the expression is evaluated. This run-time\n environment includes not only an unpredictable collection of resources (\"the web\"), but\n configurable machinery for locating resources and turning their contents into document\n nodes within the XPath data model. Both the set of resources that are reachable, and the\n mechanisms by which those resources are parsed and validated, are .

    One possible processing model for this function is as follows. The resource identified\n by the URI Reference is retrieved. If the resource cannot be retrieved, a dynamic error is\n raised . The data resulting from the retrieval action\n is then parsed as an XML document and a tree is constructed in accordance with the\n . If the top-level media type is known and is\n \"text\", the content is parsed in the same way as if the media type were text/xml;\n otherwise, it is parsed in the same way as if the media type were application/xml. If\n the contents cannot be parsed successfully, a dynamic error is raised . Otherwise, the result of the function is the document node at the root\n of the resulting tree. This tree is then optionally validated against a schema.

    Various aspects of this processing are .\n Implementations may provide external configuration options that allow any aspect of the\n processing to be controlled by the user. In particular:

    The set of URI schemes that the implementation recognizes is\n implementation-defined. Implementations may allow the mapping of URIs to resources\n to be configured by the user, using mechanisms such as catalogs or user-written\n URI handlers.

    The handling of non-XML media types is implementation-defined. Implementations may\n allow instances of the data model to be constructed from non-XML resources, under\n user control.

    It is whether DTD validation and/or schema\n validation is applied to the source document.

    Implementations may provide user-defined error handling options that allow\n processing to continue following an error in retrieving a resource, or in parsing\n and validating its content. When errors have been handled in this way, the\n function may return either an empty sequence, or a fallback document provided by\n the error handler.

    Implementations may provide user options that relax the requirement for the\n function to return deterministic results.

    A dynamic error may be raised if $uri is not a valid URI.

    A dynamic error is raised if the\n available documents provides no mapping for the absolutized URI.

    A dynamic error is raised if the resource cannot be\n retrieved or cannot be parsed successfully as XML.

    A dynamic error is raised if the implementation is not able\n to guarantee that the result of the function will be deterministic, and the user has not\n indicated that an unstable result is acceptable.

    \n", "summary" : "

    Retrieves a document using a URI supplied as an\n xs:string , and returns the corresponding document node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "document()?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "document-uri", "qname" : "fn:document-uri", "signature" : "() as xs:anyURI? external", "description" : "

    Returns the URI of a resource where a document can be found, if available.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item\n (.). The behavior of the function if the argument is omitted is exactly\n the same as if the context item had been passed as the argument.

    If $arg is the empty sequence, the function returns the empty sequence.

    If $arg is not a document node, the function returns the empty\n sequence.

    Otherwise, the function returns the value of the document-uri accessor\n applied to $arg, as defined in (See\n ).

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the URI of a resource where a document can be found, if available.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:anyURI?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "document-uri", "qname" : "fn:document-uri", "signature" : "($arg as node()?) as xs:anyURI? external", "description" : "

    Returns the URI of a resource where a document can be found, if available.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item\n (.). The behavior of the function if the argument is omitted is exactly\n the same as if the context item had been passed as the argument.

    If $arg is the empty sequence, the function returns the empty sequence.

    If $arg is not a document node, the function returns the empty\n sequence.

    Otherwise, the function returns the value of the document-uri accessor\n applied to $arg, as defined in (See\n ).

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the URI of a resource where a document can be found, if available.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "node()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:anyURI?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "element-with-id", "qname" : "fn:element-with-id", "signature" : "($arg as xs:string*) as element(*)* external", "description" : "

    Returns the sequence of element nodes that have an\n ID value matching the value of one or more of the IDREF\n values supplied in $arg.

    The one-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    \n

    The effect of this function is identical to fn:id in respect\n of elements that have an attribute with the is-id property. However,\n it behaves differently in respect of element nodes with the is-id\n property. Whereas the fn:id, for legacy reasons, returns the element\n that has the is-id property, this parent returns the element\n identified by the ID, which is the parent of the element having the\n is-id property.

    \n

    The function returns a sequence, in document order with duplicates eliminated,\n containing every element node E that satisfies all the following\n conditions:

    \n

    \n E is in the target document. The target document is the document\n containing $node, or the document containing the context item\n (.) if the second argument is omitted. The behavior of the\n function if $node is omitted is exactly the same as if the context\n item had been passed as $node.

    E has an ID value equal to one of the candidate\n IDREF values, where:

    An element has an ID value equal to V if\n either or both of the following conditions are true:

    The element has an child element node whose is-id\n property (See .) is true and\n whose typed value is equal to V under the rules of the\n eq operator using the Unicode code point collation\n (http://www.w3.org/2005/xpath-functions/collation/codepoint).

    The element has an attribute node whose is-id property\n (See .) is true and whose\n typed value is equal to V under the rules of the\n eq operator using the Unicode code point collation\n (http://www.w3.org/2005/xpath-functions/collation/codepoint).

    Each xs:string in $arg is parsed as if it were\n of type IDREFS, that is, each xs:string in\n $arg is treated as a whitespace-separated sequence of\n tokens, each acting as an IDREF. These tokens are then\n included in the list of candidate IDREFs. If any of the\n tokens is not a lexically valid IDREF (that is, if it is not\n lexically an xs:NCName), it is ignored. Formally, the\n candidate IDREF values are the strings in the sequence given\n by the expression:

    for $s in $arg return\n fn:tokenize(fn:normalize-space($s), ' ')[. castable as xs:IDREF]

    If several elements have the same ID value, then E\n is the one that is first in document order.

    \n
    \n

    A dynamic error is raised if\n $node, or the context item if the second argument is omitted, is a\n node in a tree whose root is not a document node.

    \n

    The following errors may be raised when $node is omitted:

    \n
    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n
    \n", "summary" : "

    Returns the sequence of element nodes that have an\n ID value matching the value of one or more of the IDREF \n values supplied in $arg .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "element(*)*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "element-with-id", "qname" : "fn:element-with-id", "signature" : "($arg as xs:string*, $node as node()) as element(*)* external", "description" : "

    Returns the sequence of element nodes that have an\n ID value matching the value of one or more of the IDREF\n values supplied in $arg.

    The one-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    \n

    The effect of this function is identical to fn:id in respect\n of elements that have an attribute with the is-id property. However,\n it behaves differently in respect of element nodes with the is-id\n property. Whereas the fn:id, for legacy reasons, returns the element\n that has the is-id property, this parent returns the element\n identified by the ID, which is the parent of the element having the\n is-id property.

    \n

    The function returns a sequence, in document order with duplicates eliminated,\n containing every element node E that satisfies all the following\n conditions:

    \n

    \n E is in the target document. The target document is the document\n containing $node, or the document containing the context item\n (.) if the second argument is omitted. The behavior of the\n function if $node is omitted is exactly the same as if the context\n item had been passed as $node.

    E has an ID value equal to one of the candidate\n IDREF values, where:

    An element has an ID value equal to V if\n either or both of the following conditions are true:

    The element has an child element node whose is-id\n property (See .) is true and\n whose typed value is equal to V under the rules of the\n eq operator using the Unicode code point collation\n (http://www.w3.org/2005/xpath-functions/collation/codepoint).

    The element has an attribute node whose is-id property\n (See .) is true and whose\n typed value is equal to V under the rules of the\n eq operator using the Unicode code point collation\n (http://www.w3.org/2005/xpath-functions/collation/codepoint).

    Each xs:string in $arg is parsed as if it were\n of type IDREFS, that is, each xs:string in\n $arg is treated as a whitespace-separated sequence of\n tokens, each acting as an IDREF. These tokens are then\n included in the list of candidate IDREFs. If any of the\n tokens is not a lexically valid IDREF (that is, if it is not\n lexically an xs:NCName), it is ignored. Formally, the\n candidate IDREF values are the strings in the sequence given\n by the expression:

    for $s in $arg return\n fn:tokenize(fn:normalize-space($s), ' ')[. castable as xs:IDREF]

    If several elements have the same ID value, then E\n is the one that is first in document order.

    \n
    \n

    A dynamic error is raised if\n $node, or the context item if the second argument is omitted, is a\n node in a tree whose root is not a document node.

    \n

    The following errors may be raised when $node is omitted:

    \n
    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n
    \n", "summary" : "

    Returns the sequence of element nodes that have an\n ID value matching the value of one or more of the IDREF \n values supplied in $arg .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "*", "description" : "" }, { "name" : "node", "type" : "node()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "element(*)*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "empty", "qname" : "fn:empty", "signature" : "($arg as item()*) as xs:boolean external", "description" : "

    Returns true if the argument is the empty sequence.

    This function is deterministic, context-independent, and focus-independent.

    If the value of $arg is the empty sequence, the function returns\n true; otherwise, the function returns false.

    The expression fn:empty((1,2,3)[10]) returns true().

    The expression fn:empty(fn:remove((\"hello\", \"world\"), 1)) returns false().

    \n", "summary" : "

    Returns true if the argument is the empty sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "encode-for-uri", "qname" : "fn:encode-for-uri", "signature" : "($uri-part as xs:string?) as xs:string external", "description" : "

    Encodes reserved characters in a string that is intended to be used in the path\n segment of a URI.

    This function is deterministic, context-independent, and focus-independent.

    If $uri-part is the empty sequence, the function returns the zero-length\n string.

    This function applies the URI escaping rules defined in section 2 of to the xs:string supplied as $uri-part. The\n effect of the function is to escape reserved characters. Each such character in the\n string is replaced with its percent-encoded form as described in .

    Since recommends that, for consistency, URI producers and\n normalizers should use uppercase hexadecimal digits for all percent-encodings, this\n function must always generate hexadecimal values using the upper-case letters A-F.

    All characters are escaped except those identified as \"unreserved\" by , that is the upper- and lower-case letters A-Z, the digits 0-9,\n HYPHEN-MINUS (\"-\"), LOW LINE (\"_\"), FULL STOP \".\", and TILDE \"~\".

    This function escapes URI delimiters and therefore cannot be used indiscriminately to\n encode \"invalid\" characters in a path segment.

    This function is invertible but not idempotent. This is because a string containing a\n percent character will be modified by applying the function: for example\n 100% becomes 100%25, while 100%25 becomes\n 100%2525.

    \n", "summary" : "

    Encodes reserved characters in a string that is intended to be used in the path\n segment of a URI.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri-part", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "ends-with", "qname" : "fn:ends-with", "signature" : "($arg1 as xs:string?, $arg2 as xs:string?) as xs:boolean external", "description" : "

    Returns true if the string $arg1 contains $arg2 as a\n trailing substring, taking collations into account.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri.\n \t

    If the value of $arg1 or $arg2 is the empty sequence, or\n contains only ignorable collation units, it is interpreted as the zero-length\n string.

    If the value of $arg2 is the zero-length string, then the function returns\n true. If the value of $arg1 is the zero-length string and\n the value of $arg2 is not the zero-length string, then the function returns\n false.

    The collation used by this function is determined according to the rules in .

    The function returns an xs:boolean indicating whether or not the value of\n $arg1 starts with a sequence of collation units that provides a\n match to the collation units of $arg2 according to the\n collation that is used.

    \n Match is defined in .

    A dynamic error may be raised if the\n specified collation does not support collation units.

    \n", "summary" : "

    Returns true if the string $arg1 contains $arg2 as a\n trailing substring, taking collations into account.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "arg2", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "ends-with", "qname" : "fn:ends-with", "signature" : "($arg1 as xs:string?, $arg2 as xs:string?, $collation as xs:string) as xs:boolean external", "description" : "

    Returns true if the string $arg1 contains $arg2 as a\n trailing substring, taking collations into account.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri.\n \t

    If the value of $arg1 or $arg2 is the empty sequence, or\n contains only ignorable collation units, it is interpreted as the zero-length\n string.

    If the value of $arg2 is the zero-length string, then the function returns\n true. If the value of $arg1 is the zero-length string and\n the value of $arg2 is not the zero-length string, then the function returns\n false.

    The collation used by this function is determined according to the rules in .

    The function returns an xs:boolean indicating whether or not the value of\n $arg1 starts with a sequence of collation units that provides a\n match to the collation units of $arg2 according to the\n collation that is used.

    \n Match is defined in .

    A dynamic error may be raised if the\n specified collation does not support collation units.

    \n", "summary" : "

    Returns true if the string $arg1 contains $arg2 as a\n trailing substring, taking collations into account.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "arg2", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "collation", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "environment-variable", "qname" : "fn:environment-variable", "signature" : "($arg as xs:string) as xs:string? external", "description" : "

    Returns the value of a system environment variable, if it exists.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tenvironment variables.\n \t

    The set of available environment variables\n is a set of (name, value) pairs forming part\n of the dynamic context, in which the name is unique within the set of pairs. The name\n and value are arbitrary strings.

    If the $name argument matches the name of one of these pairs, the function\n returns the corresponding value.

    If there is no environment variable with a matching name, the function returns the empty\n sequence.

    The collation used for matching names is , but\n must be the same as the collation used to ensure that the names of all environment\n variables are unique.

    The function is deterministic,\n which means that if it is called several times\n within the same execution scope, with the same arguments,\n it must return the same result.

    On many platforms, the term \"environment variable\" has a natural meaning in terms of\n facilities provided by the operating system. This interpretation of the concept does not\n exclude other interpretations, such as a mapping to a set of configuration parameters in\n a database system.

    Environment variable names are usually case sensitive. Names are usually of the form\n (letter|_) (letter|_|digit)*, but this varies by platform.

    On some platforms, there may sometimes be multiple environment variables with the same name;\n in this case, it is implementation-dependent as to which is returned; see for example\n (Chapter 8, Environment Variables).\n Implementations may use prefixes or other naming conventions\n to disambiguate the names.

    The requirement to ensure that the function is deterministic means in practice that\n the implementation must make a snapshot of the environment variables at some time\n during execution, and return values obtained from this snapshot, rather than using\n live values that are subject to change at any time.

    Operating system environment variables may be associated with a particular process,\n while queries and stylesheets may execute across multiple processes (or multiple machines).\n In such circumstances implementations may choose to provide access\n to the environment variables associated with the process in which the query or stylesheet\n processing was initiated.

    Security advice: Queries from untrusted sources should not be permitted unrestricted\n access to environment variables. For example, the name of the account under which the\n query is running may be useful information to a would-be intruder. An implementation may\n therefore choose to restrict access to the environment, or may provide a facility to\n make fn:environment-variable always return the empty sequence.

    \n", "summary" : "

    Returns the value of a system environment variable, if it exists.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "environment-variable", "qname" : "fn:environment-variable", "signature" : "($name as xs:string) as xs:string? external", "description" : "

    Returns the value of a system environment variable, if it exists.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tenvironment variables.\n \t

    The set of available environment variables\n is a set of (name, value) pairs forming part\n of the dynamic context, in which the name is unique within the set of pairs. The name\n and value are arbitrary strings.

    If the $name argument matches the name of one of these pairs, the function\n returns the corresponding value.

    If there is no environment variable with a matching name, the function returns the empty\n sequence.

    The collation used for matching names is , but\n must be the same as the collation used to ensure that the names of all environment\n variables are unique.

    The function is deterministic,\n which means that if it is called several times\n within the same execution scope, with the same arguments,\n it must return the same result.

    On many platforms, the term \"environment variable\" has a natural meaning in terms of\n facilities provided by the operating system. This interpretation of the concept does not\n exclude other interpretations, such as a mapping to a set of configuration parameters in\n a database system.

    Environment variable names are usually case sensitive. Names are usually of the form\n (letter|_) (letter|_|digit)*, but this varies by platform.

    On some platforms, there may sometimes be multiple environment variables with the same name;\n in this case, it is implementation-dependent as to which is returned; see for example\n (Chapter 8, Environment Variables).\n Implementations may use prefixes or other naming conventions\n to disambiguate the names.

    The requirement to ensure that the function is deterministic means in practice that\n the implementation must make a snapshot of the environment variables at some time\n during execution, and return values obtained from this snapshot, rather than using\n live values that are subject to change at any time.

    Operating system environment variables may be associated with a particular process,\n while queries and stylesheets may execute across multiple processes (or multiple machines).\n In such circumstances implementations may choose to provide access\n to the environment variables associated with the process in which the query or stylesheet\n processing was initiated.

    Security advice: Queries from untrusted sources should not be permitted unrestricted\n access to environment variables. For example, the name of the account under which the\n query is running may be useful information to a would-be intruder. An implementation may\n therefore choose to restrict access to the environment, or may provide a facility to\n make fn:environment-variable always return the empty sequence.

    \n", "summary" : "

    Returns the value of a system environment variable, if it exists.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "error", "qname" : "fn:error", "signature" : "() as none external", "description" : "

    Calling the fn:error function raises an application-defined\n error.

    This function is nondeterministic, context-independent, and focus-independent.

    This function never returns a value. Instead it always raises an error. The effect of\n the error is identical to the effect of dynamic errors raised implicitly, for example\n when an incorrect argument is supplied to a function.

    The parameters to the fn:error function supply information that is\n associated with the error condition and that is made available to a caller that asks for\n information about the error. The error may be caught either by the host language (using\n a try/catch construct in XSLT or XQuery, for example), or by the calling application or\n external processing environment. The way in which error information is returned to the\n external processing environment is

    If fn:error is called with no arguments, then its behavior is the same as\n the function call:

    fn:error(fn:QName('http://www.w3.org/2005/xqt-errors', 'err:FOER0000'))

    If $code is the empty sequence then the effective value is the\n xs:QName constructed by:

    fn:QName('http://www.w3.org/2005/xqt-errors', 'err:FOER0000')

    There are three pieces of information that may be associated with an error:

    The $code is an error code that distinguishes this error from others.\n It is an xs:QName; the namespace URI conventionally identifies the\n component, subsystem, or authority responsible for defining the meaning of the\n error code, while the local part identifies the specific error condition. The\n namespace URI http://www.w3.org/2005/xqt-errors is used for errors\n defined in this specification; other namespace URIs may be used for errors defined\n by the application.

    If the external processing environment expects the error code to be returned as a\n URI or a string rather than as an xs:QName, then an error code with\n namespace URI NS and local part LP will be returned in\n the form NS#LP. The namespace URI part of the error code should\n therefore not include a fragment identifier.

    The $description is a natural-language description of the error\n condition.

    The $error-object is an arbitrary value used to convey additional\n information about the error, and may be used in any way the application\n chooses.

    This function always raises a dynamic error. By default, it raises

    \n", "summary" : "

    Calling the fn:error function raises an application-defined\n error.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "none", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "error", "qname" : "fn:error", "signature" : "($code as xs:QName) as none external", "description" : "

    Calling the fn:error function raises an application-defined\n error.

    This function is nondeterministic, context-independent, and focus-independent.

    This function never returns a value. Instead it always raises an error. The effect of\n the error is identical to the effect of dynamic errors raised implicitly, for example\n when an incorrect argument is supplied to a function.

    The parameters to the fn:error function supply information that is\n associated with the error condition and that is made available to a caller that asks for\n information about the error. The error may be caught either by the host language (using\n a try/catch construct in XSLT or XQuery, for example), or by the calling application or\n external processing environment. The way in which error information is returned to the\n external processing environment is

    If fn:error is called with no arguments, then its behavior is the same as\n the function call:

    fn:error(fn:QName('http://www.w3.org/2005/xqt-errors', 'err:FOER0000'))

    If $code is the empty sequence then the effective value is the\n xs:QName constructed by:

    fn:QName('http://www.w3.org/2005/xqt-errors', 'err:FOER0000')

    There are three pieces of information that may be associated with an error:

    The $code is an error code that distinguishes this error from others.\n It is an xs:QName; the namespace URI conventionally identifies the\n component, subsystem, or authority responsible for defining the meaning of the\n error code, while the local part identifies the specific error condition. The\n namespace URI http://www.w3.org/2005/xqt-errors is used for errors\n defined in this specification; other namespace URIs may be used for errors defined\n by the application.

    If the external processing environment expects the error code to be returned as a\n URI or a string rather than as an xs:QName, then an error code with\n namespace URI NS and local part LP will be returned in\n the form NS#LP. The namespace URI part of the error code should\n therefore not include a fragment identifier.

    The $description is a natural-language description of the error\n condition.

    The $error-object is an arbitrary value used to convey additional\n information about the error, and may be used in any way the application\n chooses.

    This function always raises a dynamic error. By default, it raises

    \n", "summary" : "

    Calling the fn:error function raises an application-defined\n error.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "code", "type" : "xs:QName", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "none", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "error", "qname" : "fn:error", "signature" : "($code as xs:QName?, $description as xs:string) as none external", "description" : "

    Calling the fn:error function raises an application-defined\n error.

    This function is nondeterministic, context-independent, and focus-independent.

    This function never returns a value. Instead it always raises an error. The effect of\n the error is identical to the effect of dynamic errors raised implicitly, for example\n when an incorrect argument is supplied to a function.

    The parameters to the fn:error function supply information that is\n associated with the error condition and that is made available to a caller that asks for\n information about the error. The error may be caught either by the host language (using\n a try/catch construct in XSLT or XQuery, for example), or by the calling application or\n external processing environment. The way in which error information is returned to the\n external processing environment is

    If fn:error is called with no arguments, then its behavior is the same as\n the function call:

    fn:error(fn:QName('http://www.w3.org/2005/xqt-errors', 'err:FOER0000'))

    If $code is the empty sequence then the effective value is the\n xs:QName constructed by:

    fn:QName('http://www.w3.org/2005/xqt-errors', 'err:FOER0000')

    There are three pieces of information that may be associated with an error:

    The $code is an error code that distinguishes this error from others.\n It is an xs:QName; the namespace URI conventionally identifies the\n component, subsystem, or authority responsible for defining the meaning of the\n error code, while the local part identifies the specific error condition. The\n namespace URI http://www.w3.org/2005/xqt-errors is used for errors\n defined in this specification; other namespace URIs may be used for errors defined\n by the application.

    If the external processing environment expects the error code to be returned as a\n URI or a string rather than as an xs:QName, then an error code with\n namespace URI NS and local part LP will be returned in\n the form NS#LP. The namespace URI part of the error code should\n therefore not include a fragment identifier.

    The $description is a natural-language description of the error\n condition.

    The $error-object is an arbitrary value used to convey additional\n information about the error, and may be used in any way the application\n chooses.

    This function always raises a dynamic error. By default, it raises

    \n", "summary" : "

    Calling the fn:error function raises an application-defined\n error.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "code", "type" : "xs:QName", "occurrence" : "?", "description" : "" }, { "name" : "description", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "none", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "error", "qname" : "fn:error", "signature" : "($code as xs:QName?, $description as xs:string, $error-object as item()*) as none external", "description" : "

    Calling the fn:error function raises an application-defined\n error.

    This function is nondeterministic, context-independent, and focus-independent.

    This function never returns a value. Instead it always raises an error. The effect of\n the error is identical to the effect of dynamic errors raised implicitly, for example\n when an incorrect argument is supplied to a function.

    The parameters to the fn:error function supply information that is\n associated with the error condition and that is made available to a caller that asks for\n information about the error. The error may be caught either by the host language (using\n a try/catch construct in XSLT or XQuery, for example), or by the calling application or\n external processing environment. The way in which error information is returned to the\n external processing environment is

    If fn:error is called with no arguments, then its behavior is the same as\n the function call:

    fn:error(fn:QName('http://www.w3.org/2005/xqt-errors', 'err:FOER0000'))

    If $code is the empty sequence then the effective value is the\n xs:QName constructed by:

    fn:QName('http://www.w3.org/2005/xqt-errors', 'err:FOER0000')

    There are three pieces of information that may be associated with an error:

    The $code is an error code that distinguishes this error from others.\n It is an xs:QName; the namespace URI conventionally identifies the\n component, subsystem, or authority responsible for defining the meaning of the\n error code, while the local part identifies the specific error condition. The\n namespace URI http://www.w3.org/2005/xqt-errors is used for errors\n defined in this specification; other namespace URIs may be used for errors defined\n by the application.

    If the external processing environment expects the error code to be returned as a\n URI or a string rather than as an xs:QName, then an error code with\n namespace URI NS and local part LP will be returned in\n the form NS#LP. The namespace URI part of the error code should\n therefore not include a fragment identifier.

    The $description is a natural-language description of the error\n condition.

    The $error-object is an arbitrary value used to convey additional\n information about the error, and may be used in any way the application\n chooses.

    This function always raises a dynamic error. By default, it raises

    \n", "summary" : "

    Calling the fn:error function raises an application-defined\n error.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "code", "type" : "xs:QName", "occurrence" : "?", "description" : "" }, { "name" : "description", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "error-object", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "none", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "escape-html-uri", "qname" : "fn:escape-html-uri", "signature" : "($uri as xs:string?) as xs:string external", "description" : "

    Escapes a URI in the same way that HTML user agents handle attribute values\n expected to contain URIs.

    This function is deterministic, context-independent, and focus-independent.

    If $uri is the empty sequence, the function returns the zero-length\n string.

    Otherwise, the function escapes all characters except\n printable characters of the US-ASCII coded character set, specifically the codepoints between 32 and 126 (decimal) inclusive. Each\n character in $uri to be escaped is replaced by an escape sequence, which is\n formed by encoding the character as a sequence of octets in UTF-8, and then representing\n each of these octets in the form %HH, where HH is the hexadecimal representation of the\n octet. This function must always generate hexadecimal values using the upper-case\n letters A-F.

    The behavior of this function corresponds to the recommended handling of non-ASCII\n characters in URI attribute values as described in Appendix\n B.2.1.

    \n", "summary" : "

    Escapes a URI in the same way that HTML user agents handle attribute values\n expected to contain URIs.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "exactly-one", "qname" : "fn:exactly-one", "signature" : "($arg as item()*) as item() external", "description" : "

    Returns $arg if it contains exactly one item. Otherwise, raises an\n error.

    This function is deterministic, context-independent, and focus-independent.

    Except in error cases, the function returns $arg unchanged.

    For detailed type semantics, see [Formal Semantics].

    A dynamic error is raised if $arg is an empty\n sequence or a sequence containing more than one item.

    \n", "summary" : "

    Returns $arg if it contains exactly one item.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "item()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "exists", "qname" : "fn:exists", "signature" : "($arg as item()*) as xs:boolean external", "description" : "

    Returns true if the argument is a non-empty sequence.

    This function is deterministic, context-independent, and focus-independent.

    If the value of $arg is a non-empty sequence, the function returns\n true; otherwise, the function returns false.

    The expression fn:exists(fn:remove((\"hello\"), 1)) returns false().

    The expression fn:exists(fn:remove((\"hello\", \"world\"), 1)) returns true().

    \n", "summary" : "

    Returns true if the argument is a non-empty sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "false", "qname" : "fn:false", "signature" : "() as xs:boolean external", "description" : "

    Returns the xs:boolean value false.

    This function is deterministic, context-independent, and focus-independent.

    The result is equivalent to xs:boolean(\"0\").

    The expression fn:false() returns xs:boolean(0).

    \n", "summary" : "

    Returns the xs:boolean value false .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "filter", "qname" : "fn:filter", "signature" : "($seq as item()*, $f as function (item()) as xs:boolean) as item()* external", "description" : "

    Returns those items from the sequence $seq for which the supplied\n function $f returns true.

    This function is deterministic, context-independent, and focus-independent.

    The effect of the function is equivalent to the following implementation in XQuery:

    \n declare function fn:filter(\n $seq as item()*,\n $f as function(item()) as xs:boolean)\n as item()* {\n if (fn:empty($seq))\n then ()\n else ( fn:head($seq)[$f(.) eq fn:true()],\n fn:filter(fn:tail($seq), $f)\n )\n };

    or its equivalent in XSLT:

    \n <xsl:function name=\"fn:filter\" as=\"item()*\">\n <xsl:param name=\"seq\" as=\"item()*\"/>\n <xsl:param name=\"f\" as=\"function(item()) as xs:boolean\"/>\n <xsl:if test=\"fn:exists($seq)\">\n <xsl:sequence select=\"fn:head($seq)[$f(.) eq fn:true()], fn:filter(fn:tail($seq), $f)\"/>\n </xsl:if>\n </xsl:function>\n

    As a consequence of the function signature and the function calling\n rules, a type error occurs if the supplied function $f returns anything other\n than a single xs:boolean item; there is no conversion to an effective\n boolean value.

    \n", "summary" : "

    Returns those items from the sequence $seq for which the supplied\n function $f returns true.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "f", "type" : "function (item()) as xs:boolean", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "floor", "qname" : "fn:floor", "signature" : "($arg as numeric?) as numeric? external", "description" : "

    Rounds $arg downwards to a whole number.

    This function is deterministic, context-independent, and focus-independent.

    General rules: see .

    The function returns the largest (closest to positive infinity) number with no\n fractional part that is not greater than the value of $arg.

    If the type of $arg is one of the four numeric types xs:float,\n xs:double, xs:decimal or xs:integer the type\n of the result is the same as the type of $arg. If the type of\n $arg is a type derived from one of the numeric types, the result is an\n instance of the base numeric type.

    For xs:float and xs:double arguments, if the argument is\n positive zero, then positive zero is returned. If the argument is negative zero, then\n negative zero is returned.

    For detailed type semantics, see [Formal Semantics].

    The expression fn:floor(10.5) returns 10.

    The expression fn:floor(-10.5) returns -11.

    \n", "summary" : "

    Rounds $arg downwards to a whole number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "numeric", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "numeric?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "fold-left", "qname" : "fn:fold-left", "signature" : "($seq as item()*, $zero as item()*, $f as function (item()*, item()) as item()*) as item()* external", "description" : "

    Processes the supplied sequence from left to right, applying the supplied\n function repeatedly to each item in turn, together with an accumulated result value.

    This function is deterministic, context-independent, and focus-independent.

    The effect of the function is equivalent to the following implementation in XQuery:

    \n declare function fn:fold-left(\n $seq as item()*\n $zero as item()*,\n $f as function(item()*, item()) as item()*)\n as item()* {\n if (fn:empty($seq))\n then $zero\n else fn:fold-left(fn:tail($seq), $f($zero, fn:head($seq)), $f)\n };

    or its equivalent in XSLT:

    \n <xsl:function name=\"fn:fold-left\" as=\"item()*\">\n <xsl:param name=\"seq\" as=\"item()*\"/>\n <xsl:param name=\"zero\" as=\"item()*\"/>\n <xsl:param name=\"f\" as=\"function(item()*, item()) as item()*\"/>\n <xsl:choose>\n <xsl:when test=\"fn:empty($seq)\">\n <xsl:sequence select=\"$zero\"/>\n </xsl:when>\n <xsl:otherwise>\n <xsl:sequence select=\"fn:fold-left(fn:tail($seq), $f($zero, fn:head($seq)), $f)\"/>\n </xsl:otherwise>\n </xsl:choose>\n </xsl:function>\n

    As a consequence of the function signature and the function calling\n rules, a type error occurs if the supplied function $f cannot be applied to\n two arguments, where the first argument is either the value of $zero or the\n result of a previous application of $f, and the second is $seq or\n any trailing subsequence of $seq.

    \n", "summary" : "

    Processes the supplied sequence from left to right, applying the supplied\n function repeatedly to each item in turn, together with an accumulated result value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "zero", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "f", "type" : "function (item()*, item()) as item()*", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "fold-right", "qname" : "fn:fold-right", "signature" : "($seq as item()*, $zero as item()*, $f as function (item()*, item()) as item()*) as item()* external", "description" : "

    Processes the supplied sequence from right to left, applying the supplied\n function repeatedly to each item in turn, together with an accumulated result value.

    This function is deterministic, context-independent, and focus-independent.

    The effect of the function is equivalent to the following implementation in XQuery:

    \n declare function fn:fold-right(\n $seq as item()*,\n $zero as item()*,\n $f as function(item(), item()*) as item()*)\n as item()* {\n if (fn:empty($seq))\n then $zero\n else $f(fn:head($seq), fn:fold-right(fn:tail($seq), $zero, $f))\n };

    or its equivalent in XSLT:

    \n <xsl:function name=\"fn:fold-right\" as=\"item()*\">\n <xsl:param name=\"seq\" as=\"item()*\"/>\n <xsl:param name=\"zero\" as=\"item()*\"/>\n <xsl:param name=\"f\" as=\"function(item(), item()*) as item()*\"/>\n <xsl:choose>\n <xsl:when test=\"fn:empty($seq)\">\n <xsl:sequence select=\"$zero\"/>\n </xsl:when>\n <xsl:otherwise>\n <xsl:sequence select=\"$f(fn:head($seq), fn:fold-right(fn:tail($seq), $zero, $f))\"/>\n </xsl:otherwise>\n </xsl:choose>\n </xsl:function>\n

    As a consequence of the function signature and the function calling\n rules, a type error occurs if the supplied function $f cannot be applied to\n two arguments, where the first argument is any item in the sequence $seq, and\n the second is either the value of $zero or the result of a previous\n application of $f.

    \n", "summary" : "

    Processes the supplied sequence from right to left, applying the supplied\n function repeatedly to each item in turn, together with an accumulated result value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "zero", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "f", "type" : "function (item()*, item()) as item()*", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "for-each-pair", "qname" : "fn:for-each-pair", "signature" : "($seq1 as item()*, $seq2 as item()*, $f as function (item(), item()) as item()*) as item()* external", "description" : "

    Applies the function item $f to successive pairs of items taken one\n from $seq1 and one from $seq2, returning the concatenation of the\n resulting sequences in order.

    This function is deterministic, context-independent, and focus-independent.

    The effect of the function is equivalent to the following implementation in XQuery:

    \n declare function fn:for-each-pair($seq1, $seq2, $f)\n {\n if(fn:exists($seq1) and fn:exists($seq2))\n then (\n $f(fn:head($seq1), fn:head($seq2)),\n fn:for-each-pair(fn:tail($seq1), fn:tail($seq2), $f)\n )\n else ()\n };

    or its equivalent in XSLT:

    \n <xsl:function name=\"fn:for-each-pair\">\n <xsl:param name=\"seq1/>\n <xsl:param name=\"seq2/>\n <xsl:param name=\"f\"/>\n <xsl:if test=\"fn:exists($seq1) and fn:exists($seq2)\">\n <xsl:sequence select=\"$f(fn:head($seq1), fn:head($seq2))\"/>\n <xsl:sequence select=\"fn:for-each-pair(fn:tail($seq1), fn:tail($seq2), $f)\"/>\n </xsl:if>\n </xsl:function>\n

    The expression fn:for-each-pair((\"a\", \"b\", \"c\"), (\"x\", \"y\", \"z\"), concat#2) returns (\"ax\", \"by\", \"cz\").

    The expression fn:for-each-pair(1 to 5, 1 to 5, function($a, $b){10*$a + $b} returns (11, 22, 33, 44, 55).

    \n", "summary" : "

    Applies the function item $f to successive pairs of items taken one\n from $seq1 and one from $seq2 , returning the concatenation of the\n resulting sequences in order.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq1", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "seq2", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "f", "type" : "function (item(), item()) as item()*", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "for-each", "qname" : "fn:for-each", "signature" : "($seq as item()*, $f as function (item()) as item()*) as item()* external", "description" : "

    Applies the function item $f to every item from the sequence\n $seq in turn, returning the concatenation of the resulting sequences in\n order.

    This function is deterministic, context-independent, and focus-independent.

    The effect of the function is equivalent to the following implementation in XQuery:

    \n declare function fn:for-each($seq, $f) {\n if (fn:empty($seq))\n then ()\n else ($f(fn:head($seq)), fn:for-each(fn:tail($seq), $f))\n };

    or its equivalent in XSLT:

    \n <xsl:function name=\"fn:for-each\">\n <xsl:param name=\"seq\"/>\n <xsl:param name=\"f\"/>\n <xsl:if test=\"fn:exists($seq)\">\n <xsl:sequence select=\"$f(fn:head($seq)), fn:for-each(fn:tail($seq), $f)\"/>\n </xsl:if>\n </xsl:function>\n

    The function call fn:for-each($SEQ, $F) is equivalent to the expression\n for $i in $SEQ return $F($i), assuming that\n ordering mode is ordered.

    \n", "summary" : "

    Applies the function item $f to every item from the sequence\n $seq in turn, returning the concatenation of the resulting sequences in\n order.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "f", "type" : "function (item()) as item()*", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "format-date", "qname" : "fn:format-date", "signature" : "($value as xs:date?, $picture as xs:string) as xs:string? external", "description" : "

    Returns a string containing an xs:date value formatted for display.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tdefault calendar, and default language, and default place, and implicit timezone.\n \t

    The five-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone, and namespaces.\n \t

    See .

    \n", "summary" : "

    Returns a string containing an xs:date value formatted for display.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:date", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "format-date", "qname" : "fn:format-date", "signature" : "($value as xs:date?, $picture as xs:string, $language as xs:string?, $calendar as xs:string?, $place as xs:string?) as xs:string? external", "description" : "

    Returns a string containing an xs:date value formatted for display.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tdefault calendar, and default language, and default place, and implicit timezone.\n \t

    The five-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone, and namespaces.\n \t

    See .

    \n", "summary" : "

    Returns a string containing an xs:date value formatted for display.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:date", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "language", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "calendar", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "place", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "format-dateTime", "qname" : "fn:format-dateTime", "signature" : "($value as xs:dateTime?, $picture as xs:string) as xs:string? external", "description" : "

    Returns a string containing an xs:dateTime value formatted for display.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tdefault calendar, and default language, and default place, and implicit timezone.\n \t

    The five-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone, and namespaces.\n \t

    See .

    \n", "summary" : "

    Returns a string containing an xs:dateTime value formatted for display.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:dateTime", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "format-dateTime", "qname" : "fn:format-dateTime", "signature" : "($value as xs:dateTime?, $picture as xs:string, $language as xs:string?, $calendar as xs:string?, $place as xs:string?) as xs:string? external", "description" : "

    Returns a string containing an xs:dateTime value formatted for display.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tdefault calendar, and default language, and default place, and implicit timezone.\n \t

    The five-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone, and namespaces.\n \t

    See .

    \n", "summary" : "

    Returns a string containing an xs:dateTime value formatted for display.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:dateTime", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "language", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "calendar", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "place", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "format-integer", "qname" : "fn:format-integer", "signature" : "($value as xs:integer?, $picture as xs:string) as xs:string external", "description" : "

    Formats an integer according to a given picture string, using the conventions\n of a given natural language if specified.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tdefault language.\n \t

    The three-argument form of this function is deterministic, context-independent, and focus-independent.

    If $value is an empty sequence, the function returns a zero-length\n string.

    In all other cases, the $picture argument describes the format in which\n $value is output.

    The rules that follow describe how non-negative numbers are output. If the value of\n $value is negative, the rules below are applied to the absolute value of\n $value, and a minus sign is prepended to the result.

    The value of $picture consists of a primary format token,\n optionally followed\n by a format modifier. The primary format token is always present and must not\n be zero-length. If the string contains one or more semicolons then everything that\n precedes the last semicolon is taken as the primary format token and everything\n that follows is taken as the format modifier; if the string contains no\n semicolon then the entire picture is taken as the primary format token, and the\n format modifier is taken to be absent (which is equivalent to supplying a\n zero-length string).

    The primary format token is classified as one of the following:

    A decimal-digit-pattern made up of optional-digit-signs,\n mandatory-digit-signs, and grouping-separator-signs.

    The optional-digit-sign is the character \"#\".

    A mandatory-digit-sign is a character in Unicode category Nd. All\n mandatory-digit-signs within the format token must be from the\n same digit family, where a digit family is a sequence of ten consecutive\n characters in Unicode category Nd, having digit values 0 through 9. Within\n the format token, these digits are interchangeable: a three-digit number may\n thus be indicated equivalently by 000, 001, or\n 999.

    a grouping-separator-sign is a non-alphanumeric character, that\n is a character whose Unicode category is\n other than Nd, Nl, No, Lu, Ll, Lt, Lm or Lo.

    If the primary format token contains at least one Unicode digit\n then it is taken as a decimal digit pattern, and in this case it must\n match the regular expression ^((\\p{Nd}|#|[^\\p{N}\\p{L}])+?)$. If it contains\n a digit but does not match this pattern, a dynamic error\n is raised .

    If a semicolon is to be used as a grouping separator, then the primary\n format token as a whole must be followed by another semicolon, to ensure that\n the grouping separator is not mistaken as a separator between the primary format\n token and the format modifier.

    There must be at least one mandatory-digit-sign. There may be zero or\n more optional-digit-signs, and (if present) these must precede all\n mandatory-digit-signs. There may be zero or more\n grouping-separator-signs. A grouping-separator-sign must\n not appear at the start or end of the decimal-digit-pattern, nor\n adjacent to another grouping-separator-sign.

    The corresponding output format is a decimal number, using this digit family, with\n at least as many digits as there are mandatory-digit-signs in the\n format token. Thus, a format token 1 generates the sequence 0 1\n 2 ... 10 11 12 ..., and a format token 01 (or equivalently,\n 00 or 99) generates the sequence 00 01 02 ...\n 09 10 11 12 ... 99 100 101. A format token of &#x661;\n (Arabic-Indic digit one) generates the sequence ١ then ٢\n then ٣ ...

    The grouping-separator-signs are handled as follows. The position of\n grouping separators within the format token, counting backwards from the last\n digit, indicates the position of grouping separators to appear within the\n formatted number, and the character used as the grouping-separator-sign\n within the format token indicates the character to be used as the corresponding\n grouping separator in the formatted number. If grouping-separator-signs\n appear at regular intervals within the format token, that is if the same grouping\n separator appears at positions forming a sequence N, 2N,\n 3N, ... for some integer value N (including the case\n where there is only one number in the list), then the sequence is extrapolated to\n the left, so grouping separators will be used in the formatted number at every\n multiple of N. For example, if the format token is 0'000\n then the number one million will be formatted as 1'000'000, while the\n number fifteen will be formatted as 0'015.

    The only purpose of optional-digit-signs is to mark the position of\n grouping-separator-signs. For example, if the format token is\n #'##0 then the number one million will be formatted as\n 1'000'000, while the number fifteen will be formatted as\n 15. A grouping separator is included in the formatted number only\n if there is a digit to its left, which will only be the case if either (a) the\n number is large enough to require that digit, or (b) the number of\n mandatory-digit-signs in the format token requires insignificant\n leading zeros to be present.

    Numbers will never be truncated. Given the decimal-digit-pattern\n 01, the number three hundred will be output as 300,\n despite the absence of any optional-digit-sign.

    The format token A, which generates the sequence A B C ... Z AA AB\n AC....

    The format token a, which generates the sequence a b c ... z aa ab\n ac....

    The format token i, which generates the sequence i ii iii iv v vi vii\n viii ix x ....

    The format token I, which generates the sequence I II III IV V VI VII\n VIII IX X ....

    The format token w, which generates numbers written as lower-case words, for\n example in English, one two three four ...\n

    The format token W, which generates numbers written as upper-case words, for\n example in English, ONE TWO THREE FOUR ...\n

    The format token Ww, which generates numbers written as title-case words, for\n example in English, One Two Three Four ...\n

    Any other format token, which indicates a numbering sequence in which that token\n represents the number 1 (one) (but see the note below).\n \n It is implementation-defined which\n numbering sequences, additional to those listed above, are supported. If an\n implementation does not support a numbering sequence represented by the given\n token, it must use a format token of 1.

    In some traditional numbering sequences additional signs are added to denote\n that the letters should be interpreted as numbers; these are not included in\n the format token. An example (see also the example below) is classical Greek\n where a dexia keraia (x0374, ʹ) and sometimes an aristeri keraia\n (x0375, ͵) is added.

    For all format tokens other than the first kind above (one that consists of decimal\n digits), there may be implementation-defined lower and upper bounds on the range of numbers that\n can be formatted using this format token; indeed, for some numbering sequences there may\n be intrinsic limits. For example, the format token &#x2460; (circled\n digit one, ①) has a range imposed by the Unicode character repertoire — 1 to 20 in\n Unicode versions prior to 4.0, increased in subsequent versions. For\n the numbering sequences described above any upper bound imposed by the implementation\n must not be less than 1000 (one thousand) and any lower bound must\n not be greater than 1. Numbers that fall outside this range must be\n formatted using the format token 1.

    The above expansions of numbering sequences for format tokens such as a and\n i are indicative but not prescriptive. There are various conventions in\n use for how alphabetic sequences continue when the alphabet is exhausted, and differing\n conventions for how roman numerals are written (for example, IV versus\n IIII as the representation of the number 4). Sometimes alphabetic\n sequences are used that omit letters such as i and o. This\n specification does not prescribe the detail of any sequence other than those sequences\n consisting entirely of decimal digits.

    Many numbering sequences are language-sensitive. This applies especially to the sequence\n selected by the tokens w, W and Ww. It also\n applies to other sequences, for example different languages using the Cyrillic alphabet\n use different sequences of characters, each starting with the letter #x410 (Cyrillic\n capital letter A). In such cases, the $lang argument specifies which\n language's conventions are to be used. If the argument\n is specified, the value should be either an empty sequence\n or a value that would be valid for the xml:lang attribute (see ).\n Note that this permits the identification of sublanguages based on country codes (from ISO 3166-1)\n as well as identification of dialects and regions within a country..

    The set of languages\n for which numbering is supported is .\n If the $lang argument is absent,\n or is set to an empty sequence, or is invalid, or is not a language supported by the\n implementation, then the number is formatted using the\n default language from the dynamic context.\n

    The format modifier must\n be a string that matches the regular expression ^([co](\\(.+\\))?)?[at]?$. \n That is, if it is present it must consist of one or more of\n the following, in any order:

    either c or o, optionally followed by\n a sequence of characters enclosed between parentheses, to indicate cardinal or\n ordinal numbering respectively, the default being cardinal numbering

    either a or t, to indicate alphabetic\n or traditional numbering respectively, the default being implementation-defined.

    If the o modifier is present, this indicates a request to output ordinal\n numbers rather than cardinal numbers. For example, in English, when used with the format\n token 1, this outputs the sequence 1st 2nd 3rd 4th ..., and\n when used with the format token w outputs the sequence first second\n third fourth ....

    The string of characters between the parentheses, if present, is used to\n select between other possible variations of cardinal or ordinal numbering sequences.\n The interpretation of this string is implementation-defined. No error occurs\n if the implementation does not define any interpretation for the defined string.

    For example, in some languages, ordinal numbers vary depending on the grammatical context:\n they may have different genders and may decline with the noun that they qualify.\n In such cases the string appearing in parentheses after the letter o may be\n used to indicate the variation of the ordinal number required. The way in which the\n variation is indicated will depend on the conventions of the language. For inflected\n languages that vary the ending of the word, the recommended approach is to indicate the\n required ending, preceded by a hyphen: for example in German, appropriate values are\n o(-e), o(-er), o(-es), o(-en).

    It is implementation-defined what\n combinations of values of the format token, the language, and the cardinal/ordinal\n modifier are supported. If ordinal numbering is not supported for the combination of the\n format token, the language, and the string appearing in parentheses, the request is\n ignored and cardinal numbers are generated instead.

    Ordinal Numbering in Italian

    The specification \"1;o(-º)\" with $lang equal to\n it, if supported, should produce the sequence:

    1º 2º 3º 4º ...

    The specification \"Ww;o\" with $lang equal to\n it, if supported, should produce the sequence:

    Primo Secondo Terzo Quarto Quinto ...

    The use of the a or t\n modifier disambiguates between numbering sequences that use letters. In many\n languages there are two commonly used numbering sequences that use letters. One\n numbering sequence assigns numeric values to letters in alphabetic sequence, and the\n other assigns numeric values to each letter in some other manner traditional in that\n language. In English, these would correspond to the numbering sequences specified by the\n format tokens a and i. In some languages, the first member of\n each sequence is the same, and so the format token alone would be ambiguous. In the absence of the a or t modifier,\n the default is implementation-defined.

    A dynamic error is raised if the format token is invalid,\n that is, if it violates any mandatory rules (indicated by an emphasized must\n or required keyword in the above rules). For example, the error is raised if\n the primary format token contains a digit but does not match the required regular expression.

    \n", "summary" : "

    Formats an integer according to a given picture string, using the conventions\n of a given natural language if specified.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:integer", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "format-integer", "qname" : "fn:format-integer", "signature" : "($value as xs:integer?, $picture as xs:string, $language as xs:string) as xs:string external", "description" : "

    Formats an integer according to a given picture string, using the conventions\n of a given natural language if specified.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tdefault language.\n \t

    The three-argument form of this function is deterministic, context-independent, and focus-independent.

    If $value is an empty sequence, the function returns a zero-length\n string.

    In all other cases, the $picture argument describes the format in which\n $value is output.

    The rules that follow describe how non-negative numbers are output. If the value of\n $value is negative, the rules below are applied to the absolute value of\n $value, and a minus sign is prepended to the result.

    The value of $picture consists of a primary format token,\n optionally followed\n by a format modifier. The primary format token is always present and must not\n be zero-length. If the string contains one or more semicolons then everything that\n precedes the last semicolon is taken as the primary format token and everything\n that follows is taken as the format modifier; if the string contains no\n semicolon then the entire picture is taken as the primary format token, and the\n format modifier is taken to be absent (which is equivalent to supplying a\n zero-length string).

    The primary format token is classified as one of the following:

    A decimal-digit-pattern made up of optional-digit-signs,\n mandatory-digit-signs, and grouping-separator-signs.

    The optional-digit-sign is the character \"#\".

    A mandatory-digit-sign is a character in Unicode category Nd. All\n mandatory-digit-signs within the format token must be from the\n same digit family, where a digit family is a sequence of ten consecutive\n characters in Unicode category Nd, having digit values 0 through 9. Within\n the format token, these digits are interchangeable: a three-digit number may\n thus be indicated equivalently by 000, 001, or\n 999.

    a grouping-separator-sign is a non-alphanumeric character, that\n is a character whose Unicode category is\n other than Nd, Nl, No, Lu, Ll, Lt, Lm or Lo.

    If the primary format token contains at least one Unicode digit\n then it is taken as a decimal digit pattern, and in this case it must\n match the regular expression ^((\\p{Nd}|#|[^\\p{N}\\p{L}])+?)$. If it contains\n a digit but does not match this pattern, a dynamic error\n is raised .

    If a semicolon is to be used as a grouping separator, then the primary\n format token as a whole must be followed by another semicolon, to ensure that\n the grouping separator is not mistaken as a separator between the primary format\n token and the format modifier.

    There must be at least one mandatory-digit-sign. There may be zero or\n more optional-digit-signs, and (if present) these must precede all\n mandatory-digit-signs. There may be zero or more\n grouping-separator-signs. A grouping-separator-sign must\n not appear at the start or end of the decimal-digit-pattern, nor\n adjacent to another grouping-separator-sign.

    The corresponding output format is a decimal number, using this digit family, with\n at least as many digits as there are mandatory-digit-signs in the\n format token. Thus, a format token 1 generates the sequence 0 1\n 2 ... 10 11 12 ..., and a format token 01 (or equivalently,\n 00 or 99) generates the sequence 00 01 02 ...\n 09 10 11 12 ... 99 100 101. A format token of &#x661;\n (Arabic-Indic digit one) generates the sequence ١ then ٢\n then ٣ ...

    The grouping-separator-signs are handled as follows. The position of\n grouping separators within the format token, counting backwards from the last\n digit, indicates the position of grouping separators to appear within the\n formatted number, and the character used as the grouping-separator-sign\n within the format token indicates the character to be used as the corresponding\n grouping separator in the formatted number. If grouping-separator-signs\n appear at regular intervals within the format token, that is if the same grouping\n separator appears at positions forming a sequence N, 2N,\n 3N, ... for some integer value N (including the case\n where there is only one number in the list), then the sequence is extrapolated to\n the left, so grouping separators will be used in the formatted number at every\n multiple of N. For example, if the format token is 0'000\n then the number one million will be formatted as 1'000'000, while the\n number fifteen will be formatted as 0'015.

    The only purpose of optional-digit-signs is to mark the position of\n grouping-separator-signs. For example, if the format token is\n #'##0 then the number one million will be formatted as\n 1'000'000, while the number fifteen will be formatted as\n 15. A grouping separator is included in the formatted number only\n if there is a digit to its left, which will only be the case if either (a) the\n number is large enough to require that digit, or (b) the number of\n mandatory-digit-signs in the format token requires insignificant\n leading zeros to be present.

    Numbers will never be truncated. Given the decimal-digit-pattern\n 01, the number three hundred will be output as 300,\n despite the absence of any optional-digit-sign.

    The format token A, which generates the sequence A B C ... Z AA AB\n AC....

    The format token a, which generates the sequence a b c ... z aa ab\n ac....

    The format token i, which generates the sequence i ii iii iv v vi vii\n viii ix x ....

    The format token I, which generates the sequence I II III IV V VI VII\n VIII IX X ....

    The format token w, which generates numbers written as lower-case words, for\n example in English, one two three four ...\n

    The format token W, which generates numbers written as upper-case words, for\n example in English, ONE TWO THREE FOUR ...\n

    The format token Ww, which generates numbers written as title-case words, for\n example in English, One Two Three Four ...\n

    Any other format token, which indicates a numbering sequence in which that token\n represents the number 1 (one) (but see the note below).\n \n It is implementation-defined which\n numbering sequences, additional to those listed above, are supported. If an\n implementation does not support a numbering sequence represented by the given\n token, it must use a format token of 1.

    In some traditional numbering sequences additional signs are added to denote\n that the letters should be interpreted as numbers; these are not included in\n the format token. An example (see also the example below) is classical Greek\n where a dexia keraia (x0374, ʹ) and sometimes an aristeri keraia\n (x0375, ͵) is added.

    For all format tokens other than the first kind above (one that consists of decimal\n digits), there may be implementation-defined lower and upper bounds on the range of numbers that\n can be formatted using this format token; indeed, for some numbering sequences there may\n be intrinsic limits. For example, the format token &#x2460; (circled\n digit one, ①) has a range imposed by the Unicode character repertoire — 1 to 20 in\n Unicode versions prior to 4.0, increased in subsequent versions. For\n the numbering sequences described above any upper bound imposed by the implementation\n must not be less than 1000 (one thousand) and any lower bound must\n not be greater than 1. Numbers that fall outside this range must be\n formatted using the format token 1.

    The above expansions of numbering sequences for format tokens such as a and\n i are indicative but not prescriptive. There are various conventions in\n use for how alphabetic sequences continue when the alphabet is exhausted, and differing\n conventions for how roman numerals are written (for example, IV versus\n IIII as the representation of the number 4). Sometimes alphabetic\n sequences are used that omit letters such as i and o. This\n specification does not prescribe the detail of any sequence other than those sequences\n consisting entirely of decimal digits.

    Many numbering sequences are language-sensitive. This applies especially to the sequence\n selected by the tokens w, W and Ww. It also\n applies to other sequences, for example different languages using the Cyrillic alphabet\n use different sequences of characters, each starting with the letter #x410 (Cyrillic\n capital letter A). In such cases, the $lang argument specifies which\n language's conventions are to be used. If the argument\n is specified, the value should be either an empty sequence\n or a value that would be valid for the xml:lang attribute (see ).\n Note that this permits the identification of sublanguages based on country codes (from ISO 3166-1)\n as well as identification of dialects and regions within a country..

    The set of languages\n for which numbering is supported is .\n If the $lang argument is absent,\n or is set to an empty sequence, or is invalid, or is not a language supported by the\n implementation, then the number is formatted using the\n default language from the dynamic context.\n

    The format modifier must\n be a string that matches the regular expression ^([co](\\(.+\\))?)?[at]?$. \n That is, if it is present it must consist of one or more of\n the following, in any order:

    either c or o, optionally followed by\n a sequence of characters enclosed between parentheses, to indicate cardinal or\n ordinal numbering respectively, the default being cardinal numbering

    either a or t, to indicate alphabetic\n or traditional numbering respectively, the default being implementation-defined.

    If the o modifier is present, this indicates a request to output ordinal\n numbers rather than cardinal numbers. For example, in English, when used with the format\n token 1, this outputs the sequence 1st 2nd 3rd 4th ..., and\n when used with the format token w outputs the sequence first second\n third fourth ....

    The string of characters between the parentheses, if present, is used to\n select between other possible variations of cardinal or ordinal numbering sequences.\n The interpretation of this string is implementation-defined. No error occurs\n if the implementation does not define any interpretation for the defined string.

    For example, in some languages, ordinal numbers vary depending on the grammatical context:\n they may have different genders and may decline with the noun that they qualify.\n In such cases the string appearing in parentheses after the letter o may be\n used to indicate the variation of the ordinal number required. The way in which the\n variation is indicated will depend on the conventions of the language. For inflected\n languages that vary the ending of the word, the recommended approach is to indicate the\n required ending, preceded by a hyphen: for example in German, appropriate values are\n o(-e), o(-er), o(-es), o(-en).

    It is implementation-defined what\n combinations of values of the format token, the language, and the cardinal/ordinal\n modifier are supported. If ordinal numbering is not supported for the combination of the\n format token, the language, and the string appearing in parentheses, the request is\n ignored and cardinal numbers are generated instead.

    Ordinal Numbering in Italian

    The specification \"1;o(-º)\" with $lang equal to\n it, if supported, should produce the sequence:

    1º 2º 3º 4º ...

    The specification \"Ww;o\" with $lang equal to\n it, if supported, should produce the sequence:

    Primo Secondo Terzo Quarto Quinto ...

    The use of the a or t\n modifier disambiguates between numbering sequences that use letters. In many\n languages there are two commonly used numbering sequences that use letters. One\n numbering sequence assigns numeric values to letters in alphabetic sequence, and the\n other assigns numeric values to each letter in some other manner traditional in that\n language. In English, these would correspond to the numbering sequences specified by the\n format tokens a and i. In some languages, the first member of\n each sequence is the same, and so the format token alone would be ambiguous. In the absence of the a or t modifier,\n the default is implementation-defined.

    A dynamic error is raised if the format token is invalid,\n that is, if it violates any mandatory rules (indicated by an emphasized must\n or required keyword in the above rules). For example, the error is raised if\n the primary format token contains a digit but does not match the required regular expression.

    \n", "summary" : "

    Formats an integer according to a given picture string, using the conventions\n of a given natural language if specified.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:integer", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "language", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "format-number", "qname" : "fn:format-number", "signature" : "($value as numeric?, $picture as xs:string) as xs:string external", "description" : "

    Returns a string containing a number formatted according to a given picture\n string, taking account of decimal formats specified in the static context.

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tdecimal formats, and namespaces.\n \t

    The effect of the two-argument form of the function is equivalent to calling\n the three-argument form with an empty sequence as the value of the third argument.

    The function formats $value as a string using the picture string specified by the\n $picture argument and the decimal-format named by the\n $decimal-format-name argument, or the default decimal-format, if there\n is no $decimal-format-name argument. The syntax of the picture string is\n described in .

    The $value argument may be of any numeric data type\n (xs:double, xs:float, xs:decimal, or their\n subtypes including xs:integer). Note that if an xs:decimal is\n supplied, it is not automatically promoted to an xs:double, as such\n promotion can involve a loss of precision.

    If the supplied value of the $value argument is an empty sequence, the\n function behaves as if the supplied value were the xs:double value\n NaN.

    The value of $decimal-format-name,\n if present and non-empty, \n must be a string which after removal of leading and trailing whitespace is in the form of an\n an EQName as defined in the XPath 3.0 grammar, that is one of the following:

    A lexical QName, which is expanded using the\n statically known namespaces.\n The default namespace is not used (no prefix means no namespace).

    A URIQualifiedName using the syntax Q{uri}local,\n where the URI can be zero-length to indicate a name in no namespace.

    The decimal format that is used is the decimal format\n in the static context whose name matches $decimal-format-name if supplied,\n or the default decimal format in the static context otherwise.

    The evaluation of the format-number function takes place in two\n phases, an analysis phase described in and a\n formatting phase described in .

    The analysis phase takes as its inputs the picture\n string and the variables derived from the relevant decimal format in the\n static context, and produces as its output a number of variables with defined values.\n The formatting phase takes as its inputs the number to be formatted and the variables\n produced by the analysis phase, and produces as its output a string containing a\n formatted representation of the number.

    The result of the function is the formatted string representation of the supplied\n number.

    A dynamic error is raised if the name specified as the\n $decimal-format-name argument is\n neither a valid lexical QName nor a valid URIQualifiedName, or if it\n uses a prefix that is not found in the statically known namespaces, or if the static\n context does not contain a declaration of a decimal-format with a matching expanded\n QName. If the processor is able to detect the error statically (for example, when the\n argument is supplied as a string literal), then the processor may\n optionally signal this as a static error.

    \n", "summary" : "

    Returns a string containing a number formatted according to a given picture\n string, taking account of decimal formats specified in the static context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "numeric", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "format-number", "qname" : "fn:format-number", "signature" : "($value as numeric?, $picture as xs:string, $decimal-format-name as xs:string) as xs:string external", "description" : "

    Returns a string containing a number formatted according to a given picture\n string, taking account of decimal formats specified in the static context.

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tdecimal formats, and namespaces.\n \t

    The effect of the two-argument form of the function is equivalent to calling\n the three-argument form with an empty sequence as the value of the third argument.

    The function formats $value as a string using the picture string specified by the\n $picture argument and the decimal-format named by the\n $decimal-format-name argument, or the default decimal-format, if there\n is no $decimal-format-name argument. The syntax of the picture string is\n described in .

    The $value argument may be of any numeric data type\n (xs:double, xs:float, xs:decimal, or their\n subtypes including xs:integer). Note that if an xs:decimal is\n supplied, it is not automatically promoted to an xs:double, as such\n promotion can involve a loss of precision.

    If the supplied value of the $value argument is an empty sequence, the\n function behaves as if the supplied value were the xs:double value\n NaN.

    The value of $decimal-format-name,\n if present and non-empty, \n must be a string which after removal of leading and trailing whitespace is in the form of an\n an EQName as defined in the XPath 3.0 grammar, that is one of the following:

    A lexical QName, which is expanded using the\n statically known namespaces.\n The default namespace is not used (no prefix means no namespace).

    A URIQualifiedName using the syntax Q{uri}local,\n where the URI can be zero-length to indicate a name in no namespace.

    The decimal format that is used is the decimal format\n in the static context whose name matches $decimal-format-name if supplied,\n or the default decimal format in the static context otherwise.

    The evaluation of the format-number function takes place in two\n phases, an analysis phase described in and a\n formatting phase described in .

    The analysis phase takes as its inputs the picture\n string and the variables derived from the relevant decimal format in the\n static context, and produces as its output a number of variables with defined values.\n The formatting phase takes as its inputs the number to be formatted and the variables\n produced by the analysis phase, and produces as its output a string containing a\n formatted representation of the number.

    The result of the function is the formatted string representation of the supplied\n number.

    A dynamic error is raised if the name specified as the\n $decimal-format-name argument is\n neither a valid lexical QName nor a valid URIQualifiedName, or if it\n uses a prefix that is not found in the statically known namespaces, or if the static\n context does not contain a declaration of a decimal-format with a matching expanded\n QName. If the processor is able to detect the error statically (for example, when the\n argument is supplied as a string literal), then the processor may\n optionally signal this as a static error.

    \n", "summary" : "

    Returns a string containing a number formatted according to a given picture\n string, taking account of decimal formats specified in the static context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "numeric", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "decimal-format-name", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "format-time", "qname" : "fn:format-time", "signature" : "($value as xs:time?, $picture as xs:string) as xs:string? external", "description" : "

    Returns a string containing an xs:time value formatted for display.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tdefault calendar, and default language, and default place, and implicit timezone.\n \t

    The five-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone, and namespaces.\n \t

    See .

    \n", "summary" : "

    Returns a string containing an xs:time value formatted for display.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:time", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "format-time", "qname" : "fn:format-time", "signature" : "($value as xs:time?, $picture as xs:string, $language as xs:string?, $calendar as xs:string?, $place as xs:string?) as xs:string? external", "description" : "

    Returns a string containing an xs:time value formatted for display.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tdefault calendar, and default language, and default place, and implicit timezone.\n \t

    The five-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone, and namespaces.\n \t

    See .

    \n", "summary" : "

    Returns a string containing an xs:time value formatted for display.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:time", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "language", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "calendar", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "place", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "function-arity", "qname" : "fn:function-arity", "signature" : "($func as function (*)) as xs:integer external", "description" : "

    Returns the arity of the function identified by a function item.

    This function is deterministic, context-independent, and focus-independent.

    The fn:function-arity function returns the arity (number of arguments) of\n the function identified by $func.

    The expression fn:function-arity(fn:substring#2) returns 2.

    The expression fn:function-arity(function($node){name($node)}) returns 1.

    The expression let $initial := fn:substring(?, 1, 1) return fn:function-arity($initial) returns 1.

    \n", "summary" : "

    Returns the arity of the function identified by a function item.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "func", "type" : "function (*)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "generate-id", "qname" : "fn:generate-id", "signature" : "() as xs:string external", "description" : "

    This function returns a string that uniquely identifies a given node.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item (.). The\n behavior of the function if the argument is omitted is exactly the same as if the\n context item had been passed as the argument.

    If the argument is the empty sequence, the result is the zero-length string.

    In other cases, the function returns a string that uniquely identifies a given node.

    The returned identifier must consist of ASCII alphanumeric characters\n and must start with an alphabetic character. Thus, the string is\n syntactically an XML name.

    An implementation is free to generate an identifier in any convenient way provided that\n it always generates the same identifier for the same node and that different identifiers\n are always generated from different nodes. An implementation is under no obligation to\n generate the same identifiers each time a document is transformed or queried.

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    This function returns a string that uniquely identifies a given node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "generate-id", "qname" : "fn:generate-id", "signature" : "($arg as node()?) as xs:string external", "description" : "

    This function returns a string that uniquely identifies a given node.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item (.). The\n behavior of the function if the argument is omitted is exactly the same as if the\n context item had been passed as the argument.

    If the argument is the empty sequence, the result is the zero-length string.

    In other cases, the function returns a string that uniquely identifies a given node.

    The returned identifier must consist of ASCII alphanumeric characters\n and must start with an alphabetic character. Thus, the string is\n syntactically an XML name.

    An implementation is free to generate an identifier in any convenient way provided that\n it always generates the same identifier for the same node and that different identifiers\n are always generated from different nodes. An implementation is under no obligation to\n generate the same identifiers each time a document is transformed or queried.

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    This function returns a string that uniquely identifies a given node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "node()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "has-children", "qname" : "fn:has-children", "signature" : "() as xs:boolean external", "description" : "

    Returns true if the supplied node has one or more child nodes (of any kind).

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item (.). The\n behavior of the function if the argument is omitted is exactly the same as if the\n context item had been passed as the argument.

    Provided that the supplied argument $node matches the expected\n type node()?, the result of the function call fn:has-children($node) is defined to be\n the same as the result of the expression\n fn:exists($node/child::node()).

    The following errors may be raised when $node is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns true if the supplied node has one or more child nodes (of any kind).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "has-children", "qname" : "fn:has-children", "signature" : "($node as node()?) as xs:boolean external", "description" : "

    Returns true if the supplied node has one or more child nodes (of any kind).

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item (.). The\n behavior of the function if the argument is omitted is exactly the same as if the\n context item had been passed as the argument.

    Provided that the supplied argument $node matches the expected\n type node()?, the result of the function call fn:has-children($node) is defined to be\n the same as the result of the expression\n fn:exists($node/child::node()).

    The following errors may be raised when $node is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns true if the supplied node has one or more child nodes (of any kind).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "head", "qname" : "fn:head", "signature" : "($arg as item()*) as item()? external", "description" : "

    Returns the first item in a sequence.

    This function is deterministic, context-independent, and focus-independent.

    The function returns the value of the expression $arg[1]

    If $arg is the empty sequence, the empty sequence is returned. Otherwise\n the first item in the sequence is returned.

    \n", "summary" : "

    Returns the first item in a sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "item()?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "hours-from-duration", "qname" : "fn:hours-from-duration", "signature" : "($arg as xs:duration?) as xs:integer? external", "description" : "

    Returns the number of hours in a duration.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:integer representing the hours\n component in the value of $arg. The result is obtained by casting\n $arg to an xs:dayTimeDuration (see ) and then computing the hours component as described in\n .

    If $arg is a negative duration then the result will be negative..

    If $arg is an xs:yearMonthDuration the function returns 0.

    The expression fn:hours-from-duration(xs:dayTimeDuration(\"P3DT10H\")) returns 10.

    The expression fn:hours-from-duration(xs:dayTimeDuration(\"P3DT12H32M12S\")) returns 12.

    The expression fn:hours-from-duration(xs:dayTimeDuration(\"PT123H\")) returns 3.

    The expression fn:hours-from-duration(xs:dayTimeDuration(\"-P3DT10H\")) returns -10.

    \n", "summary" : "

    Returns the number of hours in a duration.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:duration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "hours-from-time", "qname" : "fn:hours-from-time", "signature" : "($arg as xs:time?) as xs:integer? external", "description" : "

    Returns the hours component of an xs:time.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:integer between 0 and 23, both\n inclusive, representing the value of the hours component in the local value of\n $arg.

    Assume that the dynamic context provides an implicit timezone value of\n -05:00.

    The expression fn:hours-from-time(xs:time(\"11:23:00\")) returns 11.

    The expression fn:hours-from-time(xs:time(\"21:23:00\")) returns 21.

    The expression fn:hours-from-time(xs:time(\"01:23:00+05:00\")) returns 1.

    The expression fn:hours-from-time(fn:adjust-time-to-timezone(xs:time(\"01:23:00+05:00\"),\n xs:dayTimeDuration(\"PT0S\"))) returns 20.

    The expression fn:hours-from-time(xs:time(\"24:00:00\")) returns 0.

    \n", "summary" : "

    Returns the hours component of an xs:time .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:time", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "id", "qname" : "fn:id", "signature" : "($arg as xs:string*) as element(*)* external", "description" : "

    Returns the sequence of element nodes that have an ID value\n matching the value of one or more of the IDREF values supplied in\n $arg.

    The one-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    The function returns a sequence, in document order with duplicates eliminated,\n containing every element node E that satisfies all the following\n conditions:

    \n E is in the target document. The target document is the document\n containing $node, or the document containing the context item\n (.) if the second argument is omitted. The behavior of the\n function if $node is omitted is exactly the same as if the context\n item had been passed as $node.

    E has an ID value equal to one of the candidate\n IDREF values, where:

    An element has an ID value equal to V if either\n or both of the following conditions are true:

    The is-id property (See .) of the element node is true, and the typed value\n of the element node is equal to V under the rules of the\n eq operator using the Unicode codepoint collation\n (http://www.w3.org/2005/xpath-functions/collation/codepoint).

    The element has an attribute node whose is-id property\n (See .) is true and whose typed\n value is equal to V under the rules of the\n eq operator using the Unicode code point collation\n (http://www.w3.org/2005/xpath-functions/collation/codepoint).

    Each xs:string in $arg is parsed as if it were of\n type IDREFS, that is, each xs:string in\n $arg is treated as a whitespace-separated sequence of\n tokens, each acting as an IDREF. These tokens are then included\n in the list of candidate IDREFs. If any of the tokens is not a\n lexically valid IDREF (that is, if it is not lexically an\n xs:NCName), it is ignored. Formally, the candidate\n IDREF values are the strings in the sequence given by the\n expression:

    for $s in $arg return\n fn:tokenize(fn:normalize-space($s), ' ')[. castable as xs:IDREF]

    If several elements have the same ID value, then E is\n the one that is first in document order.

    A dynamic error is raised if\n $node, or the context item if the second argument is absent, is a node\n in a tree whose root is not a document node.

    The following errors may be raised when $node is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the sequence of element nodes that have an ID value\n matching the value of one or more of the IDREF values supplied in\n $arg .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "element(*)*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "id", "qname" : "fn:id", "signature" : "($arg as xs:string*, $node as node()) as element(*)* external", "description" : "

    Returns the sequence of element nodes that have an ID value\n matching the value of one or more of the IDREF values supplied in\n $arg.

    The one-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    The function returns a sequence, in document order with duplicates eliminated,\n containing every element node E that satisfies all the following\n conditions:

    \n E is in the target document. The target document is the document\n containing $node, or the document containing the context item\n (.) if the second argument is omitted. The behavior of the\n function if $node is omitted is exactly the same as if the context\n item had been passed as $node.

    E has an ID value equal to one of the candidate\n IDREF values, where:

    An element has an ID value equal to V if either\n or both of the following conditions are true:

    The is-id property (See .) of the element node is true, and the typed value\n of the element node is equal to V under the rules of the\n eq operator using the Unicode codepoint collation\n (http://www.w3.org/2005/xpath-functions/collation/codepoint).

    The element has an attribute node whose is-id property\n (See .) is true and whose typed\n value is equal to V under the rules of the\n eq operator using the Unicode code point collation\n (http://www.w3.org/2005/xpath-functions/collation/codepoint).

    Each xs:string in $arg is parsed as if it were of\n type IDREFS, that is, each xs:string in\n $arg is treated as a whitespace-separated sequence of\n tokens, each acting as an IDREF. These tokens are then included\n in the list of candidate IDREFs. If any of the tokens is not a\n lexically valid IDREF (that is, if it is not lexically an\n xs:NCName), it is ignored. Formally, the candidate\n IDREF values are the strings in the sequence given by the\n expression:

    for $s in $arg return\n fn:tokenize(fn:normalize-space($s), ' ')[. castable as xs:IDREF]

    If several elements have the same ID value, then E is\n the one that is first in document order.

    A dynamic error is raised if\n $node, or the context item if the second argument is absent, is a node\n in a tree whose root is not a document node.

    The following errors may be raised when $node is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the sequence of element nodes that have an ID value\n matching the value of one or more of the IDREF values supplied in\n $arg .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "*", "description" : "" }, { "name" : "node", "type" : "node()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "element(*)*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "idref", "qname" : "fn:idref", "signature" : "($arg as xs:string*) as node()* external", "description" : "

    Returns the sequence of element or attribute nodes with an IDREF\n value matching the value of one or more of the ID values supplied in\n $arg.

    The one-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    The function returns a sequence, in document order with duplicates eliminated,\n containing every element or attribute node $N that satisfies all the\n following conditions:

    $N is in the target document. The target document is the document\n containing $node or the document containing the context item\n (.) if the second argument is omitted. The behavior of the\n function if $node is omitted is exactly the same as if the context\n item had been passed as $node.

    $N has an IDREF value equal to one of the candidate\n ID values, where:

    A node $N has an IDREF value equal to\n V if both of the following conditions are true:

    The is-idrefs property (see ) of $N is true.

    The sequence fn:tokenize(fn:normalize-space(fn:string($N)), ' ')\n contains a string that is\n equal to V under the rules of the eq\n operator using the Unicode code point collation\n (http://www.w3.org/2005/xpath-functions/collation/codepoint).

    Each xs:string in $arg is parsed as if it were of\n lexically of type xs:ID. These xs:strings are then\n included in the list of candidate xs:IDs. If any of the strings\n in $arg is not a lexically valid xs:ID (that is,\n if it is not lexically an xs:NCName), it is ignored. More\n formally, the candidate ID values are the strings in the\n sequence:

    $arg[. castable as xs:NCName]

    A dynamic error is raised if\n $node, or the context item if the second argument is omitted, is a node\n in a tree whose root is not a document node.

    The following errors may be raised when $node is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the sequence of element or attribute nodes with an IDREF \n value matching the value of one or more of the ID values supplied in\n $arg .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "idref", "qname" : "fn:idref", "signature" : "($arg as xs:string*, $node as node()) as node()* external", "description" : "

    Returns the sequence of element or attribute nodes with an IDREF\n value matching the value of one or more of the ID values supplied in\n $arg.

    The one-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    The function returns a sequence, in document order with duplicates eliminated,\n containing every element or attribute node $N that satisfies all the\n following conditions:

    $N is in the target document. The target document is the document\n containing $node or the document containing the context item\n (.) if the second argument is omitted. The behavior of the\n function if $node is omitted is exactly the same as if the context\n item had been passed as $node.

    $N has an IDREF value equal to one of the candidate\n ID values, where:

    A node $N has an IDREF value equal to\n V if both of the following conditions are true:

    The is-idrefs property (see ) of $N is true.

    The sequence fn:tokenize(fn:normalize-space(fn:string($N)), ' ')\n contains a string that is\n equal to V under the rules of the eq\n operator using the Unicode code point collation\n (http://www.w3.org/2005/xpath-functions/collation/codepoint).

    Each xs:string in $arg is parsed as if it were of\n lexically of type xs:ID. These xs:strings are then\n included in the list of candidate xs:IDs. If any of the strings\n in $arg is not a lexically valid xs:ID (that is,\n if it is not lexically an xs:NCName), it is ignored. More\n formally, the candidate ID values are the strings in the\n sequence:

    $arg[. castable as xs:NCName]

    A dynamic error is raised if\n $node, or the context item if the second argument is omitted, is a node\n in a tree whose root is not a document node.

    The following errors may be raised when $node is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the sequence of element or attribute nodes with an IDREF \n value matching the value of one or more of the ID values supplied in\n $arg .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "*", "description" : "" }, { "name" : "node", "type" : "node()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "implicit-timezone", "qname" : "fn:implicit-timezone", "signature" : "() as xs:dayTimeDuration external", "description" : "

    Returns the value of the implicit timezone property from the dynamic context.\n

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\timplicit timezone.\n \t

    Returns the value of the implicit timezone property from the dynamic context. Components\n of the dynamic context are discussed in .

    \n", "summary" : "

    Returns the value of the implicit timezone property from the dynamic context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:dayTimeDuration", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "in-scope-prefixes", "qname" : "fn:in-scope-prefixes", "signature" : "($element as element(*)) as xs:string* external", "description" : "

    Returns the prefixes of the in-scope namespaces for an element node.

    This function is deterministic, context-independent, and focus-independent.

    The function returns a sequence of strings representing the prefixes of the in-scope\n namespaces for $element.

    For namespace bindings that have a prefix, the function returns the prefix as an\n xs:NCName. For the default namespace, which has no prefix, it returns\n the zero-length string.

    The result sequence contains no duplicates.

    The ordering of the result sequence is implementation-dependent.

    \n", "summary" : "

    Returns the prefixes of the in-scope namespaces for an element node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "element", "type" : "element(*)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "index-of", "qname" : "fn:index-of", "signature" : "($seq as xs:anyAtomicType*, $search as xs:anyAtomicType) as xs:integer* external", "description" : "

    Returns a sequence of positive integers giving the positions within the\n sequence $seq of items that are equal to $search.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and implicit timezone.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri, and implicit timezone.\n \t

    The function returns a sequence of positive integers giving the positions within the\n sequence $seq of items that are equal to $search.

    The collation used by this function is determined according to the rules in . This collation is used when string comparison is\n required.

    The items in the sequence $seq are compared with $search under\n the rules for the eq operator. Values of type xs:untypedAtomic\n are compared as if they were of type xs:string. Values that cannot be\n compared, because the eq operator is not defined for their types, are\n considered to be distinct. If an item compares equal, then the position of that item in\n the sequence $seq is included in the result.

    The first item in a sequence is at position 1, not position 0.

    The result sequence is in ascending numeric order.

    If the value of $seq is the empty sequence, or if no item in\n $seq matches $search, then the function returns the empty\n sequence.

    No error occurs if non-comparable values are encountered. So when\n comparing two atomic values, the effective boolean value of fn:index-of($a,\n $b) is true if $a and $b are equal, false if they\n are not equal or not comparable.

    \n", "summary" : "

    Returns a sequence of positive integers giving the positions within the\n sequence $seq of items that are equal to $search .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "" }, { "name" : "search", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:integer*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "index-of", "qname" : "fn:index-of", "signature" : "($seq as xs:anyAtomicType*, $search as xs:anyAtomicType, $collation as xs:string) as xs:integer* external", "description" : "

    Returns a sequence of positive integers giving the positions within the\n sequence $seq of items that are equal to $search.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and implicit timezone.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri, and implicit timezone.\n \t

    The function returns a sequence of positive integers giving the positions within the\n sequence $seq of items that are equal to $search.

    The collation used by this function is determined according to the rules in . This collation is used when string comparison is\n required.

    The items in the sequence $seq are compared with $search under\n the rules for the eq operator. Values of type xs:untypedAtomic\n are compared as if they were of type xs:string. Values that cannot be\n compared, because the eq operator is not defined for their types, are\n considered to be distinct. If an item compares equal, then the position of that item in\n the sequence $seq is included in the result.

    The first item in a sequence is at position 1, not position 0.

    The result sequence is in ascending numeric order.

    If the value of $seq is the empty sequence, or if no item in\n $seq matches $search, then the function returns the empty\n sequence.

    No error occurs if non-comparable values are encountered. So when\n comparing two atomic values, the effective boolean value of fn:index-of($a,\n $b) is true if $a and $b are equal, false if they\n are not equal or not comparable.

    \n", "summary" : "

    Returns a sequence of positive integers giving the positions within the\n sequence $seq of items that are equal to $search .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "" }, { "name" : "search", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "" }, { "name" : "collation", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:integer*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "innermost", "qname" : "fn:innermost", "signature" : "($nodes as node()*) as node()* external", "description" : "

    Returns every node within the input sequence that is not an ancestor of another member\n of the input sequence; the nodes are returned in document order with duplicates\n eliminated.

    This function is deterministic, context-independent, and focus-independent.

    The effect of the function call fn:innermost($nodes) is defined to be\n equivalent to the result of the expression $nodes except\n $nodes/ancestor::node().

    That is, the function takes as input a sequence of nodes, and returns every node within\n the sequence that is not an ancestor of another node within the sequence; the nodes are\n returned in document order with duplicates eliminated.

    If the source document contains nested sections represented by div\n elements, the expression innermost(//div) returns those div\n elements that do not contain further div elements.

    \n", "summary" : "

    Returns every node within the input sequence that is not an ancestor of another member\n of the input sequence; the nodes are returned in document order with duplicates\n eliminated.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "insert-before", "qname" : "fn:insert-before", "signature" : "($target as item()*, $position as xs:integer, $inserts as item()*) as item()* external", "description" : "

    Returns a sequence constructed by inserting an item or a sequence of items at a\n given position within an existing sequence.

    This function is deterministic, context-independent, and focus-independent.

    The value returned by the function consists of all items of $target whose\n index is less than $position, followed by all items of\n $inserts, followed by the remaining elements of $target, in\n that order.

    For detailed type semantics, see [Formal Semantics].

    If $target is the empty sequence, $inserts is returned. If\n $inserts is the empty sequence, $target is returned.

    If $position is less than one (1), the first position, the effective value\n of $position is one (1). If $position is greater than the\n number of items in $target, then the effective value of\n $position is equal to the number of items in $target plus\n 1.

    The value of $target is not affected by the sequence construction.

    \n", "summary" : "

    Returns a sequence constructed by inserting an item or a sequence of items at a\n given position within an existing sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "target", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "position", "type" : "xs:integer", "occurrence" : null, "description" : "" }, { "name" : "inserts", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "iri-to-uri", "qname" : "fn:iri-to-uri", "signature" : "($iri as xs:string?) as xs:string external", "description" : "

    Converts a string containing an IRI into a URI according to the rules of\n .

    This function is deterministic, context-independent, and focus-independent.

    If $iri is the empty sequence, the function returns the zero-length\n string.

    Otherwise, the function converts the value of $iri into a URI according to\n the rules given in Section 3.1 of by percent-encoding characters\n that are allowed in an IRI but not in a URI. If $iri contains a character\n that is invalid in an IRI, such as the space character (see note below), the invalid\n character is replaced by its percent-encoded form as described in before the conversion is performed.

    Since recommends that, for consistency, URI producers and\n normalizers should use uppercase hexadecimal digits for all percent-encodings, this\n function must always generate hexadecimal values using the upper-case letters A-F.

    The function is idempotent but not invertible. Both the inputs My Documents\n and My%20Documents will be converted to the output\n My%20Documents.

    This function does not check whether $iri is a valid IRI. It treats it as\n an string and operates on the characters in the string.

    The following printable ASCII characters are invalid in an IRI: \"<\", \">\", \n \" (double quote), space, \"{\", \"}\", \"|\", \"\\\", \"^\", and \"`\". Since these\n characters should not appear in an IRI, if they do appear in $iri they will\n be percent-encoded. In addition, characters outside the range x20-x7E will be percent-encoded because they are invalid in a URI.

    Since this function does not escape the PERCENT SIGN \"%\" and this character is not\n allowed in data within a URI, users wishing to convert character strings (such as file\n names) that include \"%\" to a URI should manually escape \"%\" by replacing it with \"%25\".\n

    \n", "summary" : "

    Converts a string containing an IRI into a URI according to the rules of\n .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "iri", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "lang", "qname" : "fn:lang", "signature" : "($testlang as xs:string?) as xs:boolean external", "description" : "

    This function tests whether the language of $node, or the context\n item if the second argument is omitted, as specified by xml:lang attributes\n is the same as, or is a sublanguage of, the language specified by\n $testlang.

    The one-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    The behavior of the function if the second argument is omitted is exactly the same as if\n the context item (.) had been passed as the second argument.

    The language of the argument $node, or the context item if the second\n argument is omitted, is determined by the value of the xml:lang attribute\n on the node, or, if the node has no such attribute, by the value of the\n xml:lang attribute on the nearest ancestor of the node that has an\n xml:lang attribute. If there is no such ancestor, then the function\n returns false.

    If $testlang is the empty sequence it is interpreted as the zero-length\n string.

    The relevant xml:lang attribute is determined by the value of the XPath\n expression:

    (ancestor-or-self::*/@xml:lang)[last()]

    If this expression returns an empty sequence, the function returns false.

    Otherwise, the function returns true if and only if, based on a caseless\n default match as specified in section 3.13 of , either:

    \n $testlang is equal to the string-value of the relevant\n xml:lang attribute, or

    \n $testlang is equal to some substring of the string-value of the\n relevant xml:lang attribute that starts at the start of the\n string-value and ends immediately before a hyphen, \"-\" (the character \"-\" is\n HYPHEN-MINUS, #x002D).

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    This function tests whether the language of $node , or the context\n item if the second argument is omitted, as specified by xml:lang attributes\n is the same as, or is a sublanguage of, the language specified by\n $testlang .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "testlang", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "lang", "qname" : "fn:lang", "signature" : "($testlang as xs:string?, $node as node()) as xs:boolean external", "description" : "

    This function tests whether the language of $node, or the context\n item if the second argument is omitted, as specified by xml:lang attributes\n is the same as, or is a sublanguage of, the language specified by\n $testlang.

    The one-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    The behavior of the function if the second argument is omitted is exactly the same as if\n the context item (.) had been passed as the second argument.

    The language of the argument $node, or the context item if the second\n argument is omitted, is determined by the value of the xml:lang attribute\n on the node, or, if the node has no such attribute, by the value of the\n xml:lang attribute on the nearest ancestor of the node that has an\n xml:lang attribute. If there is no such ancestor, then the function\n returns false.

    If $testlang is the empty sequence it is interpreted as the zero-length\n string.

    The relevant xml:lang attribute is determined by the value of the XPath\n expression:

    (ancestor-or-self::*/@xml:lang)[last()]

    If this expression returns an empty sequence, the function returns false.

    Otherwise, the function returns true if and only if, based on a caseless\n default match as specified in section 3.13 of , either:

    \n $testlang is equal to the string-value of the relevant\n xml:lang attribute, or

    \n $testlang is equal to some substring of the string-value of the\n relevant xml:lang attribute that starts at the start of the\n string-value and ends immediately before a hyphen, \"-\" (the character \"-\" is\n HYPHEN-MINUS, #x002D).

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    This function tests whether the language of $node , or the context\n item if the second argument is omitted, as specified by xml:lang attributes\n is the same as, or is a sublanguage of, the language specified by\n $testlang .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "testlang", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "node", "type" : "node()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "last", "qname" : "fn:last", "signature" : "() as xs:integer external", "description" : "

    Returns the context size from the dynamic context.

    This function is deterministic, context-dependent, and focus-dependent.

    Returns the context size from the dynamic context. (See .)

    A dynamic error is raised if the\n context item is absent.

    \n", "summary" : "

    Returns the context size from the dynamic context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "local-name-from-QName", "qname" : "fn:local-name-from-QName", "signature" : "($arg as xs:QName?) as xs:NCName? external", "description" : "

    Returns the local part of the supplied QName.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence the function returns the empty sequence.

    Otherwise, the function returns an xs:NCName representing the local part of\n $arg.

    The expression fn:local-name-from-QName(fn:QName(\"http://www.example.com/example\",\n \"person\")) returns \"person\".

    \n", "summary" : "

    Returns the local part of the supplied QName.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:QName", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:NCName?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "local-name", "qname" : "fn:local-name", "signature" : "() as xs:string external", "description" : "

    Returns the local part of the name of $arg as an\n xs:string that is either the zero-length string, or has the lexical form\n of an xs:NCName.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item (.). The\n behavior of the function if the argument is omitted is exactly the same as if the\n context item had been passed as the argument.

    If the argument is supplied and is the empty sequence, the function returns the\n zero-length string.

    If the node identified by $arg has no name (that is, if it is a document\n node, a comment, a text node, or a namespace node having no name), the function returns\n the zero-length string.

    Otherwise, the function returns the local part of the expanded-QName of the node\n identified by $arg, as determined by the dm:node-name accessor\n defined in ). This will be an\n xs:string whose lexical form is an xs:NCName.

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the local part of the name of $arg as an\n xs:string that is either the zero-length string, or has the lexical form\n of an xs:NCName .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "local-name", "qname" : "fn:local-name", "signature" : "($arg as node()?) as xs:string external", "description" : "

    Returns the local part of the name of $arg as an\n xs:string that is either the zero-length string, or has the lexical form\n of an xs:NCName.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item (.). The\n behavior of the function if the argument is omitted is exactly the same as if the\n context item had been passed as the argument.

    If the argument is supplied and is the empty sequence, the function returns the\n zero-length string.

    If the node identified by $arg has no name (that is, if it is a document\n node, a comment, a text node, or a namespace node having no name), the function returns\n the zero-length string.

    Otherwise, the function returns the local part of the expanded-QName of the node\n identified by $arg, as determined by the dm:node-name accessor\n defined in ). This will be an\n xs:string whose lexical form is an xs:NCName.

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the local part of the name of $arg as an\n xs:string that is either the zero-length string, or has the lexical form\n of an xs:NCName .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "node()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "lower-case", "qname" : "fn:lower-case", "signature" : "($arg as xs:string?) as xs:string external", "description" : "

    Converts a string to lower case.

    This function is deterministic, context-independent, and focus-independent.

    If the value of $arg is the empty sequence, the zero-length string is\n returned.

    Otherwise, the function returns the value of $arg after translating every\n character to its lower-case correspondent as\n defined in the appropriate case mappings section in the Unicode standard . For versions of Unicode beginning with the 2.1.8 update, only\n locale-insensitive case mappings should be applied. Beginning with version 3.2.0 (and\n likely future versions) of Unicode, precise mappings are described in default case\n operations, which are full case mappings in the absence of tailoring for particular\n languages and environments. Every upper-case character that does not have a lower-case\n correspondent, as well as every lower-case character, is included in the returned value\n in its original form.

    Case mappings may change the length of a string. In general, the\n fn:upper-case and fn:lower-case functions are not inverses\n of each other: fn:lower-case(fn:upper-case($arg)) is not guaranteed to\n return $arg, nor is fn:upper-case(fn:lower-case($arg)). The\n Latin small letter dotless i (as used in Turkish) is perhaps the most prominent\n lower-case letter which will not round-trip. The Latin capital letter i with dot above\n is the most prominent upper-case letter which will not round trip; there are others,\n such as Latin capital letter Sharp S (#1E9E) which is introduced in Unicode 5.1.

    These functions may not always be linguistically appropriate (e.g. Turkish i without\n dot) or appropriate for the application (e.g. titlecase). In cases such as Turkish, a\n simple translation should be used first.

    Because the function is not sensitive to locale, results will not always match user\n expectations. In Quebec, for example, the standard uppercase equivalent of \"è\" is \"È\",\n while in metropolitan France it is more commonly \"E\"; only one of these is supported by\n the functions as defined.

    Many characters of class Ll lack uppercase equivalents in the Unicode case mapping\n tables; many characters of class Lu lack lowercase equivalents.

    \n", "summary" : "

    Converts a string to lower case.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "matches", "qname" : "fn:matches", "signature" : "($input as xs:string?, $pattern as xs:string) as xs:boolean external", "description" : "

    Returns true if the supplied string matches a given regular expression.

    This function is deterministic, context-independent, and focus-independent.

    The effect of calling the first version of this function (omitting the argument\n $flags) is the same as the effect of calling the second version with the\n $flags argument set to a zero-length string. Flags are defined in\n .

    If $input is the empty sequence, it is interpreted as the zero-length\n string.

    The function returns true if $input or some substring of\n $input matches the regular expression supplied as $pattern.\n Otherwise, the function returns false. The matching rules are influenced by\n the value of $flags if present.

    A dynamic error is raised if the value of\n $pattern is invalid according to the rules described in .

    A dynamic error is raised if the value of\n $flags is invalid according to the rules described in .

    \n", "summary" : "

    Returns true if the supplied string matches a given regular expression.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "matches", "qname" : "fn:matches", "signature" : "($input as xs:string?, $pattern as xs:string, $flags as xs:string) as xs:boolean external", "description" : "

    Returns true if the supplied string matches a given regular expression.

    This function is deterministic, context-independent, and focus-independent.

    The effect of calling the first version of this function (omitting the argument\n $flags) is the same as the effect of calling the second version with the\n $flags argument set to a zero-length string. Flags are defined in\n .

    If $input is the empty sequence, it is interpreted as the zero-length\n string.

    The function returns true if $input or some substring of\n $input matches the regular expression supplied as $pattern.\n Otherwise, the function returns false. The matching rules are influenced by\n the value of $flags if present.

    A dynamic error is raised if the value of\n $pattern is invalid according to the rules described in .

    A dynamic error is raised if the value of\n $flags is invalid according to the rules described in .

    \n", "summary" : "

    Returns true if the supplied string matches a given regular expression.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "flags", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "max", "qname" : "fn:max", "signature" : "($arg as xs:anyAtomicType*) as xs:anyAtomicType? external", "description" : "

    Returns a value that is equal to the highest value appearing in the input\n sequence.

    The zero-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and implicit timezone.\n \t

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri, and implicit timezone.\n \t

    The following rules are applied to the input sequence $arg:

    Values of type xs:untypedAtomic in $arg are cast to\n xs:double.

    Numeric and xs:anyURI values are converted to\n the least common type reachable by a combination of type promotion and subtype\n substitution. See and .

    The items in the resulting sequence may be reordered in an arbitrary order. The\n resulting sequence is referred to below as the converted sequence. The function returns\n an item from the converted sequence rather than the input sequence.

    If the converted sequence is empty, the function returns the empty sequence.

    All items in the converted sequence must be\n derived from a single base type for which the le operator is\n defined. In addition, the values in the sequence must have a total order. If date/time\n values do not have a timezone, they are considered to have the implicit timezone\n provided by the dynamic context for the purpose of comparison. Duration values must\n either all be xs:yearMonthDuration values or must all be\n xs:dayTimeDuration values.

    If the converted sequence contains the value NaN, the value\n NaN is returned.

    If the items in the converted sequence are of\n type xs:string or types derived by restriction from xs:string,\n then the determination of the item with the smallest value is made according to the\n collation that is used. If the type of the items in the converted sequence is not xs:string and\n $collation is specified, the collation is ignored.

    The collation used by this function is determined according to the rules in .

    The function returns the result of the expression:

    \n if (every $v in $c satisfies $c[1] ge $v)\n then $c[1]\n else fn:max(fn:subsequence($c, 2))

    evaluated with $collation as the default collation if specified, and with\n $c as the converted sequence.

    For detailed type semantics, see [Formal Semantics].

    A type error is raised if the input sequence contains\n items of incompatible types, as described above.

    \n", "summary" : "

    Returns a value that is equal to the highest value appearing in the input\n sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:anyAtomicType?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "max", "qname" : "fn:max", "signature" : "($arg as xs:anyAtomicType*, $collation as xs:string) as xs:anyAtomicType? external", "description" : "

    Returns a value that is equal to the highest value appearing in the input\n sequence.

    The zero-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and implicit timezone.\n \t

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri, and implicit timezone.\n \t

    The following rules are applied to the input sequence $arg:

    Values of type xs:untypedAtomic in $arg are cast to\n xs:double.

    Numeric and xs:anyURI values are converted to\n the least common type reachable by a combination of type promotion and subtype\n substitution. See and .

    The items in the resulting sequence may be reordered in an arbitrary order. The\n resulting sequence is referred to below as the converted sequence. The function returns\n an item from the converted sequence rather than the input sequence.

    If the converted sequence is empty, the function returns the empty sequence.

    All items in the converted sequence must be\n derived from a single base type for which the le operator is\n defined. In addition, the values in the sequence must have a total order. If date/time\n values do not have a timezone, they are considered to have the implicit timezone\n provided by the dynamic context for the purpose of comparison. Duration values must\n either all be xs:yearMonthDuration values or must all be\n xs:dayTimeDuration values.

    If the converted sequence contains the value NaN, the value\n NaN is returned.

    If the items in the converted sequence are of\n type xs:string or types derived by restriction from xs:string,\n then the determination of the item with the smallest value is made according to the\n collation that is used. If the type of the items in the converted sequence is not xs:string and\n $collation is specified, the collation is ignored.

    The collation used by this function is determined according to the rules in .

    The function returns the result of the expression:

    \n if (every $v in $c satisfies $c[1] ge $v)\n then $c[1]\n else fn:max(fn:subsequence($c, 2))

    evaluated with $collation as the default collation if specified, and with\n $c as the converted sequence.

    For detailed type semantics, see [Formal Semantics].

    A type error is raised if the input sequence contains\n items of incompatible types, as described above.

    \n", "summary" : "

    Returns a value that is equal to the highest value appearing in the input\n sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "" }, { "name" : "collation", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:anyAtomicType?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "min", "qname" : "fn:min", "signature" : "($arg as xs:anyAtomicType*) as xs:anyAtomicType? external", "description" : "

    Returns a value that is equal to the lowest value appearing in the input\n sequence.

    The zero-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and implicit timezone.\n \t

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri, and implicit timezone.\n \t

    The following rules are applied to the input sequence:

    Values of type xs:untypedAtomic in $arg are cast to\n xs:double.

    Numeric and xs:anyURI values are converted to\n the least common type reachable by a combination of type promotion and subtype\n substitution. See and .

    The items in the resulting sequence may be reordered in an arbitrary order. The\n resulting sequence is referred to below as the converted sequence. The function returns\n an item from the converted sequence rather than the input sequence.

    If the converted sequence is empty, the empty sequence is returned.

    All items in the converted sequence must be\n derived from a single base type for which the le operator is\n defined. In addition, the values in the sequence must have a total order. If date/time\n values do not have a timezone, they are considered to have the implicit timezone\n provided by the dynamic context for the purpose of comparison. Duration values must\n either all be xs:yearMonthDuration values or must all be\n xs:dayTimeDuration values.

    If the converted sequence contains the value NaN, the value\n NaN is returned.

    If the items in the converted sequence are of\n type xs:string or types derived by restriction from xs:string,\n then the determination of the item with the smallest value is made according to the\n collation that is used. If the type of the items in the converted sequence is not xs:string and\n $collation is specified, the collation is ignored.

    The collation used by this function is determined according to the rules in .

    The function returns the result of the expression:

    \n if (every $v in $c satisfies $c[1] le $v)\n then $c[1]\n else fn:min(fn:subsequence($c, 2))

    evaluated with $collation as the default collation if specified, and with\n $c as the converted sequence.

    For detailed type semantics, see [Formal Semantics].

    A type error is raised if the input sequence contains\n items of incompatible types, as described above.

    \n", "summary" : "

    Returns a value that is equal to the lowest value appearing in the input\n sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:anyAtomicType?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "min", "qname" : "fn:min", "signature" : "($arg as xs:anyAtomicType*, $collation as xs:string) as xs:anyAtomicType? external", "description" : "

    Returns a value that is equal to the lowest value appearing in the input\n sequence.

    The zero-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and implicit timezone.\n \t

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri, and implicit timezone.\n \t

    The following rules are applied to the input sequence:

    Values of type xs:untypedAtomic in $arg are cast to\n xs:double.

    Numeric and xs:anyURI values are converted to\n the least common type reachable by a combination of type promotion and subtype\n substitution. See and .

    The items in the resulting sequence may be reordered in an arbitrary order. The\n resulting sequence is referred to below as the converted sequence. The function returns\n an item from the converted sequence rather than the input sequence.

    If the converted sequence is empty, the empty sequence is returned.

    All items in the converted sequence must be\n derived from a single base type for which the le operator is\n defined. In addition, the values in the sequence must have a total order. If date/time\n values do not have a timezone, they are considered to have the implicit timezone\n provided by the dynamic context for the purpose of comparison. Duration values must\n either all be xs:yearMonthDuration values or must all be\n xs:dayTimeDuration values.

    If the converted sequence contains the value NaN, the value\n NaN is returned.

    If the items in the converted sequence are of\n type xs:string or types derived by restriction from xs:string,\n then the determination of the item with the smallest value is made according to the\n collation that is used. If the type of the items in the converted sequence is not xs:string and\n $collation is specified, the collation is ignored.

    The collation used by this function is determined according to the rules in .

    The function returns the result of the expression:

    \n if (every $v in $c satisfies $c[1] le $v)\n then $c[1]\n else fn:min(fn:subsequence($c, 2))

    evaluated with $collation as the default collation if specified, and with\n $c as the converted sequence.

    For detailed type semantics, see [Formal Semantics].

    A type error is raised if the input sequence contains\n items of incompatible types, as described above.

    \n", "summary" : "

    Returns a value that is equal to the lowest value appearing in the input\n sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "" }, { "name" : "collation", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:anyAtomicType?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "minutes-from-dateTime", "qname" : "fn:minutes-from-dateTime", "signature" : "($arg as xs:dateTime?) as xs:integer? external", "description" : "

    Returns the minute component of an xs:dateTime.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:integer value between 0 and 59, both\n inclusive, representing the minute component in the local value of\n $arg.

    The expression fn:minutes-from-dateTime(xs:dateTime(\"1999-05-31T13:20:00-05:00\")) returns 20.

    The expression fn:minutes-from-dateTime(xs:dateTime(\"1999-05-31T13:30:00+05:30\")) returns 30.

    \n", "summary" : "

    Returns the minute component of an xs:dateTime .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:dateTime", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "minutes-from-duration", "qname" : "fn:minutes-from-duration", "signature" : "($arg as xs:duration?) as xs:integer? external", "description" : "

    Returns the number of minutes in a duration.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:integer representing the minutes\n component in the value of $arg. The result is obtained by casting\n $arg to an xs:dayTimeDuration (see ) and then computing the minutes component as described\n in .

    If $arg is a negative duration then the result will be negative..

    If $arg is an xs:yearMonthDuration the function returns 0.

    The expression fn:minutes-from-duration(xs:dayTimeDuration(\"P3DT10H\")) returns 0.

    The expression fn:minutes-from-duration(xs:dayTimeDuration(\"-P5DT12H30M\")) returns -30.

    \n", "summary" : "

    Returns the number of minutes in a duration.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:duration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "minutes-from-time", "qname" : "fn:minutes-from-time", "signature" : "($arg as xs:time?) as xs:integer? external", "description" : "

    Returns the minutes component of an xs:time.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:integer value between 0 and 59, both\n inclusive, representing the value of the minutes component in the local value of\n $arg.

    The expression fn:minutes-from-time(xs:time(\"13:00:00Z\")) returns 0.

    \n", "summary" : "

    Returns the minutes component of an xs:time .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:time", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "month-from-date", "qname" : "fn:month-from-date", "signature" : "($arg as xs:date?) as xs:integer? external", "description" : "

    Returns the month component of an xs:date.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:integer between 1 and 12, both\n inclusive, representing the month component in the local value of $arg.\n

    The expression fn:month-from-date(xs:date(\"1999-05-31-05:00\")) returns 5.

    The expression fn:month-from-date(xs:date(\"2000-01-01+05:00\")) returns 1.

    \n", "summary" : "

    Returns the month component of an xs:date .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:date", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "months-from-duration", "qname" : "fn:months-from-duration", "signature" : "($arg as xs:duration?) as xs:integer? external", "description" : "

    Returns the number of months in a duration.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:integer representing the months\n component in the value of $arg. The result is obtained by casting\n $arg to an xs:yearMonthDuration (see ) and then computing the months component as described in\n .

    If $arg is a negative duration then the result will be negative..

    If $arg is an xs:dayTimeDuration the function returns 0.

    The expression fn:months-from-duration(xs:yearMonthDuration(\"P20Y15M\")) returns 3.

    The expression fn:months-from-duration(xs:yearMonthDuration(\"-P20Y18M\")) returns -6.

    The expression fn:months-from-duration(xs:dayTimeDuration(\"-P2DT15H0M0S\")) returns 0.

    \n", "summary" : "

    Returns the number of months in a duration.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:duration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "name", "qname" : "fn:name", "signature" : "() as xs:string external", "description" : "

    Returns the name of a node, as an xs:string that is either the\n zero-length string, or has the lexical form of an xs:QName.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item (.). The\n behavior of the function if the argument is omitted is exactly the same as if the\n context item had been passed as the argument.

    If the argument is supplied and is the empty sequence, the function returns the\n zero-length string.

    If the node identified by $arg has no name (that is, if it is a document\n node, a comment, a text node, or a namespace node having no name), the function returns\n the zero-length string.

    Otherwise, the function returns the value of the expression\n fn:string(fn:node-name($arg)).

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the name of a node, as an xs:string that is either the\n zero-length string, or has the lexical form of an xs:QName .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "name", "qname" : "fn:name", "signature" : "($arg as node()?) as xs:string external", "description" : "

    Returns the name of a node, as an xs:string that is either the\n zero-length string, or has the lexical form of an xs:QName.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item (.). The\n behavior of the function if the argument is omitted is exactly the same as if the\n context item had been passed as the argument.

    If the argument is supplied and is the empty sequence, the function returns the\n zero-length string.

    If the node identified by $arg has no name (that is, if it is a document\n node, a comment, a text node, or a namespace node having no name), the function returns\n the zero-length string.

    Otherwise, the function returns the value of the expression\n fn:string(fn:node-name($arg)).

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the name of a node, as an xs:string that is either the\n zero-length string, or has the lexical form of an xs:QName .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "node()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "namespace-uri-for-prefix", "qname" : "fn:namespace-uri-for-prefix", "signature" : "($prefix as xs:string?, $element as element(*)) as xs:anyURI? external", "description" : "

    Returns the namespace URI of one of the in-scope namespaces for\n $element, identified by its namespace prefix.

    This function is deterministic, context-independent, and focus-independent.

    If $element has an in-scope namespace whose namespace prefix is equal to\n $prefix, the function returns the namespace URI of that namespace.

    If $element has no in-scope namespace whose namespace prefix is equal to\n $prefix, the function returns the empty sequence.

    If $prefix is the zero-length string or the empty\n sequence, then if $element has a default namespace (that is, a namespace\n node with no name), the function returns the namespace URI of the default namespace. If\n $element has no default namespace, the function returns the empty\n sequence.

    Prefixes are equal only if their Unicode codepoints match exactly.

    let $e := \n <z:a xmlns=\"http://example.org/one\" xmlns:z=\"http://example.org/two\">\n <b xmlns=\"\"/>\n </z:a>

    The expression fn:namespace-uri-for-prefix(\"z\", $e) returns \"http://example.org/two\".

    The expression fn:namespace-uri-for-prefix(\"\", $e) returns \"http://example.org/one\".

    The expression fn:namespace-uri-for-prefix((), $e) returns \"http://example.org/one\".

    The expression fn:namespace-uri-for-prefix(\"xml\", $e) returns \"http://www.w3.org/XML/1998/namespace\".

    The expression fn:namespace-uri-for-prefix(\"xml\", $e) returns \"http://www.w3.org/XML/1998/namespace\".

    \n", "summary" : "

    Returns the namespace URI of one of the in-scope namespaces for\n $element , identified by its namespace prefix.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "prefix", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "element", "type" : "element(*)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:anyURI?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "namespace-uri-from-QName", "qname" : "fn:namespace-uri-from-QName", "signature" : "($arg as xs:QName?) as xs:anyURI? external", "description" : "

    Returns the namespace URI part of the supplied QName.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence the function returns the empty sequence.

    Otherwise, the function returns an xs:anyURI representing the namespace URI\n part of $arg.

    If $arg is in no namespace, the function returns the zero-length\n xs:anyURI.

    The expression fn:namespace-uri-from-QName(fn:QName(\"http://www.example.com/example\",\n \"person\")) returns xs:anyURI(\"http://www.example.com/example\").

    \n", "summary" : "

    Returns the namespace URI part of the supplied QName.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:QName", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:anyURI?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "namespace-uri", "qname" : "fn:namespace-uri", "signature" : "() as xs:anyURI external", "description" : "

    Returns the namespace URI part of the name of\n $arg, as an xs:anyURI value.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context node (.). The\n behavior of the function if the argument is omitted is exactly the same as if the\n context item had been passed as the argument.

    If the node identified by $arg is neither an element nor an attribute node,\n or if it is an element or attribute node whose expanded-QName (as determined by the\n dm:node-name accessor in the )\n is in no namespace, then the function returns the zero-length xs:anyURI\n value.

    Otherwise, the result will be the namespace URI part of the expanded-QName of the node\n identified by $arg, as determined by the dm:node-name accessor\n defined in ), returned as an\n xs:anyURI value.

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the namespace URI part of the name of\n $arg , as an xs:anyURI value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:anyURI", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "namespace-uri", "qname" : "fn:namespace-uri", "signature" : "($arg as node()?) as xs:anyURI external", "description" : "

    Returns the namespace URI part of the name of\n $arg, as an xs:anyURI value.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context node (.). The\n behavior of the function if the argument is omitted is exactly the same as if the\n context item had been passed as the argument.

    If the node identified by $arg is neither an element nor an attribute node,\n or if it is an element or attribute node whose expanded-QName (as determined by the\n dm:node-name accessor in the )\n is in no namespace, then the function returns the zero-length xs:anyURI\n value.

    Otherwise, the result will be the namespace URI part of the expanded-QName of the node\n identified by $arg, as determined by the dm:node-name accessor\n defined in ), returned as an\n xs:anyURI value.

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the namespace URI part of the name of\n $arg , as an xs:anyURI value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "node()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:anyURI", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "nilled", "qname" : "fn:nilled", "signature" : "() as xs:boolean external", "description" : "

    Returns true for an element that is nilled.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item (.). The\n behavior of the function if the argument is omitted is exactly the same as if the\n context item had been passed as the argument.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise the function returns the result of the dm:nilled accessor as\n defined in (see ).

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns true for an element that is nilled .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "nilled", "qname" : "fn:nilled", "signature" : "($arg as node()?) as xs:boolean? external", "description" : "

    Returns true for an element that is nilled.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item (.). The\n behavior of the function if the argument is omitted is exactly the same as if the\n context item had been passed as the argument.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise the function returns the result of the dm:nilled accessor as\n defined in (see ).

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns true for an element that is nilled .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "node()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:boolean?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "node-name", "qname" : "fn:node-name", "signature" : "() as xs:QName? external", "description" : "

    Returns the name of a node, as an xs:QName.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item\n (.). The behavior of the function if the argument is omitted is exactly\n the same as if the context item had been passed as the argument.

    If $arg is the empty sequence, the empty sequence is returned.

    Otherwise, the function returns the result of the dm:node-name accessor as\n defined in (see ).

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the name of a node, as an xs:QName .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "node-name", "qname" : "fn:node-name", "signature" : "($arg as node()?) as xs:QName? external", "description" : "

    Returns the name of a node, as an xs:QName.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the argument is omitted, it defaults to the context item\n (.). The behavior of the function if the argument is omitted is exactly\n the same as if the context item had been passed as the argument.

    If $arg is the empty sequence, the empty sequence is returned.

    Otherwise, the function returns the result of the dm:node-name accessor as\n defined in (see ).

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the name of a node, as an xs:QName .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "node()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:QName?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "normalize-space", "qname" : "fn:normalize-space", "signature" : "() as xs:string external", "description" : "

    Returns the value of $arg with leading and trailing whitespace\n removed, and sequences of internal whitespace reduced to a single space character.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the value of $arg is the empty sequence, the function returns the\n zero-length string.

    The function returns a string constructed by stripping leading and trailing whitespace\n from the value of $arg, and replacing sequences of one or more adjacent\n whitespace characters with a single space, #x20.

    The whitespace characters are defined in the metasymbol S (Production 3) of .

    If no argument is supplied, then $arg defaults to the\n string value (calculated using fn:string) of the context item\n (.).

    If no argument is supplied and the context item is absent then a dynamic error is raised: .

    \n", "summary" : "

    Returns the value of $arg with leading and trailing whitespace\n removed, and sequences of internal whitespace reduced to a single space character.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "normalize-space", "qname" : "fn:normalize-space", "signature" : "($arg as xs:string?) as xs:string external", "description" : "

    Returns the value of $arg with leading and trailing whitespace\n removed, and sequences of internal whitespace reduced to a single space character.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the value of $arg is the empty sequence, the function returns the\n zero-length string.

    The function returns a string constructed by stripping leading and trailing whitespace\n from the value of $arg, and replacing sequences of one or more adjacent\n whitespace characters with a single space, #x20.

    The whitespace characters are defined in the metasymbol S (Production 3) of .

    If no argument is supplied, then $arg defaults to the\n string value (calculated using fn:string) of the context item\n (.).

    If no argument is supplied and the context item is absent then a dynamic error is raised: .

    \n", "summary" : "

    Returns the value of $arg with leading and trailing whitespace\n removed, and sequences of internal whitespace reduced to a single space character.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "normalize-unicode", "qname" : "fn:normalize-unicode", "signature" : "($arg as xs:string?) as xs:string external", "description" : "

    Returns the value of $arg after applying Unicode\n normalization.

    This function is deterministic, context-independent, and focus-independent.

    If the value of $arg is the empty sequence, the function returns the\n zero-length string.

    If the single-argument version of the function is used, the result is the same as\n calling the two-argument version with $normalizationForm set to the string\n \"NFC\".

    Otherwise, the function returns the value of $arg normalized according to\n the rules of the normalization form identified by the value of\n $normalizationForm.

    The effective value of $normalizationForm is the value of the expression\n fn:upper-case(fn:normalize-space($normalizationForm)).

    See for a description of the\n normalization forms.

    If the effective value of $normalizationForm is NFC,\n then the function returns the value of $arg converted to Unicode\n Normalization Form C (NFC).

    If the effective value of $normalizationForm is NFD,\n then the function returns the value of $arg converted to Unicode\n Normalization Form D (NFD).

    If the effective value of $normalizationForm is NFKC,\n then the function returns the value of $arg in Unicode Normalization\n Form KC (NFKC).

    If the effective value of $normalizationForm is NFKD,\n then the function returns the value of $arg converted to Unicode\n Normalization Form KD (NFKD).

    If the effective value of $normalizationForm is\n FULLY-NORMALIZED, then the function returns the value of\n $arg converted to fully normalized form.

    If the effective value of $normalizationForm is the zero-length\n string, no normalization is performed and $arg is returned.

    Normalization forms NFC, NFD, NFKC, and NFKD, and the algorithms to be\n used for converting a string to each of these forms, are defined in .

    The motivation for normalization form FULLY-NORMALIZED is explained in\n . However, as that specification did not\n progress beyond working draft status, the normative specification is as follows:

    A string is fully-normalized if (a) it is in normalization form NFC\n as defined in , and (b) it does not start\n with a composing character.

    A composing character is a character that is one or both of the following:

    the second character in the canonical decomposition mapping of some\n character that is not listed in the Composition Exclusion Table defined in\n ;

    of non-zero canonical combining class (as defined in ).

    A string is converted to FULLY-NORMALIZED form as follows:

    if the first character in the string is a composing character, prepend a\n single space (x20);

    convert the resulting string to normalization form NFC.

    Conforming implementations must support normalization form \"NFC\" and\n may support normalization forms \"NFD\", \"NFKC\", \"NFKD\", and\n \"FULLY-NORMALIZED\". They may also support other normalization forms\n with implementation-defined semantics.

    It is implementation-defined which version of\n Unicode (and therefore, of the normalization algorithms and their underlying\n data) is supported by the implementation. See for details of the\n stability policy regarding changes to the normalization rules in future\n versions of Unicode. If the input string contains codepoints that are\n unassigned in the relevant version of Unicode, or for which no normalization\n rules are defined, the fn:normalize-unicode function leaves such codepoints\n unchanged. If the implementation supports the requested normalization form then\n it must be able to handle every input string without raising an error.

    A dynamic error is raised if the effective value of the\n $normalizationForm argument is not one of the values supported by the\n implementation.

    \n", "summary" : "

    Returns the value of $arg after applying Unicode\n normalization.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "normalize-unicode", "qname" : "fn:normalize-unicode", "signature" : "($arg as xs:string?, $normalizationForm as xs:string) as xs:string external", "description" : "

    Returns the value of $arg after applying Unicode\n normalization.

    This function is deterministic, context-independent, and focus-independent.

    If the value of $arg is the empty sequence, the function returns the\n zero-length string.

    If the single-argument version of the function is used, the result is the same as\n calling the two-argument version with $normalizationForm set to the string\n \"NFC\".

    Otherwise, the function returns the value of $arg normalized according to\n the rules of the normalization form identified by the value of\n $normalizationForm.

    The effective value of $normalizationForm is the value of the expression\n fn:upper-case(fn:normalize-space($normalizationForm)).

    See for a description of the\n normalization forms.

    If the effective value of $normalizationForm is NFC,\n then the function returns the value of $arg converted to Unicode\n Normalization Form C (NFC).

    If the effective value of $normalizationForm is NFD,\n then the function returns the value of $arg converted to Unicode\n Normalization Form D (NFD).

    If the effective value of $normalizationForm is NFKC,\n then the function returns the value of $arg in Unicode Normalization\n Form KC (NFKC).

    If the effective value of $normalizationForm is NFKD,\n then the function returns the value of $arg converted to Unicode\n Normalization Form KD (NFKD).

    If the effective value of $normalizationForm is\n FULLY-NORMALIZED, then the function returns the value of\n $arg converted to fully normalized form.

    If the effective value of $normalizationForm is the zero-length\n string, no normalization is performed and $arg is returned.

    Normalization forms NFC, NFD, NFKC, and NFKD, and the algorithms to be\n used for converting a string to each of these forms, are defined in .

    The motivation for normalization form FULLY-NORMALIZED is explained in\n . However, as that specification did not\n progress beyond working draft status, the normative specification is as follows:

    A string is fully-normalized if (a) it is in normalization form NFC\n as defined in , and (b) it does not start\n with a composing character.

    A composing character is a character that is one or both of the following:

    the second character in the canonical decomposition mapping of some\n character that is not listed in the Composition Exclusion Table defined in\n ;

    of non-zero canonical combining class (as defined in ).

    A string is converted to FULLY-NORMALIZED form as follows:

    if the first character in the string is a composing character, prepend a\n single space (x20);

    convert the resulting string to normalization form NFC.

    Conforming implementations must support normalization form \"NFC\" and\n may support normalization forms \"NFD\", \"NFKC\", \"NFKD\", and\n \"FULLY-NORMALIZED\". They may also support other normalization forms\n with implementation-defined semantics.

    It is implementation-defined which version of\n Unicode (and therefore, of the normalization algorithms and their underlying\n data) is supported by the implementation. See for details of the\n stability policy regarding changes to the normalization rules in future\n versions of Unicode. If the input string contains codepoints that are\n unassigned in the relevant version of Unicode, or for which no normalization\n rules are defined, the fn:normalize-unicode function leaves such codepoints\n unchanged. If the implementation supports the requested normalization form then\n it must be able to handle every input string without raising an error.

    A dynamic error is raised if the effective value of the\n $normalizationForm argument is not one of the values supported by the\n implementation.

    \n", "summary" : "

    Returns the value of $arg after applying Unicode\n normalization.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "normalizationForm", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "not", "qname" : "fn:not", "signature" : "($arg as item()*) as xs:boolean external", "description" : "

    Returns true if the effective boolean value of $arg\n is false, or false if it is true.

    This function is deterministic, context-independent, and focus-independent.

    The value of $arg is first reduced to an effective boolean value by\n applying the fn:boolean() function. The function returns true\n if the effective boolean value is false, or false if the\n effective boolean value is true.

    The expression fn:not(fn:true()) returns false().

    The expression fn:not(\"false\") returns false().

    \n", "summary" : "

    Returns true if the effective boolean value of $arg \n is false , or false if it is true .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "number", "qname" : "fn:number", "signature" : "() as xs:double external", "description" : "

    Returns the value indicated by $arg or, if $arg is\n not specified, the context item after atomization, converted to an\n xs:double.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    Calling the zero-argument version of the function is defined to give the same result as\n calling the single-argument version with the context item (.). That is,\n fn:number() is equivalent to fn:number(.), as\n defined by the rules that follow.

    If $arg is the empty sequence or if $arg or the context item\n cannot be converted to an xs:double, the xs:double value\n NaN is returned.

    Otherwise, $arg , or the context item after atomization, is converted to an\n xs:double following the rules of . If\n the conversion to xs:double fails, the xs:double value\n NaN is returned.

    A dynamic error is raised if\n $arg is omitted and the context item is absent.

    As a consequence of the rules given above, a type error occurs if the context\n item cannot be atomized, or if the result of atomizing the context item is a sequence containing\n more than one atomic value.

    \n", "summary" : "

    Returns the value indicated by $arg or, if $arg is\n not specified, the context item after atomization, converted to an\n xs:double .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:double", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "number", "qname" : "fn:number", "signature" : "($arg as xs:anyAtomicType?) as xs:double external", "description" : "

    Returns the value indicated by $arg or, if $arg is\n not specified, the context item after atomization, converted to an\n xs:double.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    Calling the zero-argument version of the function is defined to give the same result as\n calling the single-argument version with the context item (.). That is,\n fn:number() is equivalent to fn:number(.), as\n defined by the rules that follow.

    If $arg is the empty sequence or if $arg or the context item\n cannot be converted to an xs:double, the xs:double value\n NaN is returned.

    Otherwise, $arg , or the context item after atomization, is converted to an\n xs:double following the rules of . If\n the conversion to xs:double fails, the xs:double value\n NaN is returned.

    A dynamic error is raised if\n $arg is omitted and the context item is absent.

    As a consequence of the rules given above, a type error occurs if the context\n item cannot be atomized, or if the result of atomizing the context item is a sequence containing\n more than one atomic value.

    \n", "summary" : "

    Returns the value indicated by $arg or, if $arg is\n not specified, the context item after atomization, converted to an\n xs:double .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:double", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "one-or-more", "qname" : "fn:one-or-more", "signature" : "($arg as item()*) as item()+ external", "description" : "

    Returns $arg if it contains one or more items. Otherwise, raises\n an error.

    This function is deterministic, context-independent, and focus-independent.

    Except in error cases, the function returns $arg unchanged.

    For detailed type semantics, see [Formal Semantics].

    A dynamic error is raised if $arg is an empty\n sequence.

    \n", "summary" : "

    Returns $arg if it contains one or more items.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "item()+", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "outermost", "qname" : "fn:outermost", "signature" : "($nodes as node()*) as node()* external", "description" : "

    Returns every node within the input sequence that has no ancestor that is itself a\n member of the input sequence; the nodes are returned in document order with duplicates\n eliminated.

    This function is deterministic, context-independent, and focus-independent.

    The effect of the function call fn:outermost($nodes) is defined to be\n equivalent to the result of the expression $nodes[not(ancestor::node() intersect\n $nodes)]/..

    That is, the function takes as input a sequence of nodes, and returns every node within\n the sequence that does not have another node within the sequence as an ancestor; the nodes are\n returned in document order with duplicates eliminated.

    The formulation $nodes except $nodes/descendant::node() might appear to be\n simpler, but does not correctly account for attribute nodes, as these are not\n descendants of their parent element.

    The motivation for the function was based on XSLT streaming use cases. There are cases\n where the streaming rules allow the construct\n outermost(//section) but do not allow //section; the\n function can therefore be useful in cases where it is known that sections will not be\n nested, as well as cases where the application actually wishes to process all sections\n except those that are nested within another.

    \n", "summary" : "

    Returns every node within the input sequence that has no ancestor that is itself a\n member of the input sequence; the nodes are returned in document order with duplicates\n eliminated.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "parse-xml-fragment", "qname" : "fn:parse-xml-fragment", "signature" : "($arg as xs:string?) as document(element(*,xs:untyped)) external", "description" : "

    This function takes as input an XML external entity represented as a string,\n and returns the document node at the root of an XDM tree representing the parsed\n document fragment.

    This function is nondeterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    If $arg is the empty sequence, the function returns the empty sequence.

    The input must be a namespace-well-formed external general parsed entity. More specifically,\n it must be a string conforming to the production rule extParsedEnt in , it must contain no entity references other\n than references to predefined entities,\n and it must satisfy all the rules\n of for namespace-well-formed documents with the exception\n that the rule requiring it to be a well-formed document is replaced by the rule requiring\n it to be a well-formed external general parsed entity.

    The string is parsed to form a sequence of nodes which\n become children of the new document node, in the same way as the content of any element\n is converted into a sequence of children for the resulting element node.

    Schema validation is not invoked, which means that the nodes in the\n returned document will all be untyped.

    The precise process used to construct the XDM instance is . In\n particular, it is implementation-defined whether an XML 1.0 or XML 1.1 parser is\n used.

    The Static Base URI from the static context of the fn:parse-xml-fragment function call\n is used as the base URI of the document node\n that is returned.

    The document URI of the returned node is absent.

    The function is not\n deterministic: that is, if the function is called\n twice with the same arguments, it is implementation-dependent whether the same node is returned on both\n occasions.

    A dynamic error is raised if the content of\n $arg is not a well-formed external general parsed entity,\n if it contains entity references other than references to predefined entities, or if a document that\n incorporates this well-formed parsed entity would not be namespace-well-formed.

    \n", "summary" : "

    This function takes as input an XML external entity represented as a string,\n and returns the document node at the root of an XDM tree representing the parsed\n document fragment.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "document(element(*,xs:untyped))", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "parse-xml", "qname" : "fn:parse-xml", "signature" : "($arg as xs:string?) as document(element(*,xs:untyped)) external", "description" : "

    This function takes as input an XML document represented as a string, and\n returns the document node at the root of an XDM tree representing the parsed\n document.

    This function is nondeterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    If $arg is the empty sequence, the function returns the\n empty sequence.

    The precise process used to construct the XDM instance is . In\n particular, it is implementation-defined whether DTD and/or schema validation is invoked, and it is\n implementation-defined whether an XML 1.0 or XML 1.1 parser is used.

    The Static Base URI property from the static context of the\n fn:parse-xml function call is used both as the base URI used by the XML parser to resolve\n relative entity references within the document, and as the base URI of the document node\n that is returned.

    The document URI of the returned node is absent.

    The function is not\n deterministic: that is, if the function is called\n twice with the same arguments, it is implementation-dependent whether the same node is returned on both\n occasions.

    A dynamic error is raised if the content of\n $arg is not a well-formed and namespace-well-formed XML document.

    A dynamic error is raised if DTD-based\n validation is carried out and the content of $arg is not valid against its\n DTD.

    \n", "summary" : "

    This function takes as input an XML document represented as a string, and\n returns the document node at the root of an XDM tree representing the parsed\n document.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "document(element(*,xs:untyped))", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "parse-xml", "qname" : "fn:parse-xml", "signature" : "($arg as xs:string?, $baseURI as xs:string) as document(element(*,xs:untyped)) external", "description" : "

    This function takes as input an XML document represented as a string, and\n returns the document node at the root of an XDM tree representing the parsed\n document.

    This function is nondeterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    If $arg is the empty sequence, the function returns the\n empty sequence.

    The precise process used to construct the XDM instance is . In\n particular, it is implementation-defined whether DTD and/or schema validation is invoked, and it is\n implementation-defined whether an XML 1.0 or XML 1.1 parser is used.

    The Static Base URI property from the static context of the\n fn:parse-xml function call is used both as the base URI used by the XML parser to resolve\n relative entity references within the document, and as the base URI of the document node\n that is returned.

    The document URI of the returned node is absent.

    The function is not\n deterministic: that is, if the function is called\n twice with the same arguments, it is implementation-dependent whether the same node is returned on both\n occasions.

    A dynamic error is raised if the content of\n $arg is not a well-formed and namespace-well-formed XML document.

    A dynamic error is raised if DTD-based\n validation is carried out and the content of $arg is not valid against its\n DTD.

    \n", "summary" : "

    This function takes as input an XML document represented as a string, and\n returns the document node at the root of an XDM tree representing the parsed\n document.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "baseURI", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "document(element(*,xs:untyped))", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "position", "qname" : "fn:position", "signature" : "() as xs:integer external", "description" : "

    Returns the context position from the dynamic context.

    This function is deterministic, context-dependent, and focus-dependent.

    Returns the context position from the dynamic context. (See .)

    A dynamic error is raised if the\n context item is absent.

    \n", "summary" : "

    Returns the context position from the dynamic context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "prefix-from-QName", "qname" : "fn:prefix-from-QName", "signature" : "($arg as xs:QName?) as xs:NCName? external", "description" : "

    Returns the prefix component of the supplied QName.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence the function returns the empty sequence.

    If $arg has no prefix component the function returns the empty\n sequence.

    Otherwise, the function returns an xs:NCName representing the prefix\n component of $arg.

    \n", "summary" : "

    Returns the prefix component of the supplied QName.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:QName", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:NCName?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "remove", "qname" : "fn:remove", "signature" : "($target as item()*, $position as xs:integer) as item()* external", "description" : "

    Returns a new sequence containing all the items of $target except\n the item at position $position.

    This function is deterministic, context-independent, and focus-independent.

    The function returns a sequence consisting of all items of $target whose\n index is less than $position, followed by all items of $target\n whose index is greater than $position.

    For detailed type semantics, see [Formal Semantics].

    If $position is less than 1 or greater than the number of items in\n $target, $target is returned.

    If $target is the empty sequence, the empty sequence is returned.

    \n", "summary" : "

    Returns a new sequence containing all the items of $target except\n the item at position $position .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "target", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "position", "type" : "xs:integer", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "replace", "qname" : "fn:replace", "signature" : "($input as xs:string?, $pattern as xs:string, $replacement as xs:string) as xs:string external", "description" : "

    Returns a string produced from the input string by replacing any substrings\n that match a given regular expression with a supplied replacement string.

    This function is deterministic, context-independent, and focus-independent.

    The effect of calling the first version of this function (omitting the argument\n $flags) is the same as the effect of calling the second version with the\n $flags argument set to a zero-length string. Flags are defined in\n .

    The $flags argument is interpreted in the same manner as for the\n fn:matches function.

    If $input is the empty sequence, it is interpreted as the zero-length\n string.

    The function returns the xs:string that is obtained by replacing each\n non-overlapping substring of $input that matches the given\n $pattern with an occurrence of the $replacement string.

    If two overlapping substrings of $input both match the\n $pattern, then only the first one (that is, the one whose first character comes first in the $input string) is\n replaced.

    If the q flag is present, the replacement string is used\n as is.

    Otherwise, within the $replacement\n string, a variable $N may be used to refer to the substring captured by the\n Nth parenthesized sub-expression in the regular expression. For each match of the\n pattern, these variables are assigned the value of the content matched by the relevant\n sub-expression, and the modified replacement string is then substituted for the characters in $input that matched the pattern.\n $0 refers to the substring captured by the regular expression as a\n whole.

    More specifically, the rules are as follows, where S is the number of\n parenthesized sub-expressions in the regular expression, and N is the\n decimal number formed by taking all the digits that consecutively follow the\n $ character:

    If N=0, then the variable is replaced by the substring\n matched by the regular expression as a whole.

    If 1<=N<=S, then the variable is\n replaced by the substring captured by the Nth parenthesized sub-expression. If the\n Nth parenthesized sub-expression was not matched, then the\n variable is replaced by the zero-length string.

    If S<N<=9, then the variable is\n replaced by the zero-length string.

    Otherwise (if N>S and\n N>9), the last digit of N is taken to\n be a literal character to be included \"as is\" in the replacement string, and the\n rules are reapplied using the number N formed by stripping off this\n last digit.

    For example, if the replacement string is \n $23\n and there are 5 substrings, the result contains the value of the substring that\n matches the second sub-expression, followed by the digit \n 3\n .

    Unless the q flag is used, a literal $\n character within the replacement string must be written as \\$, and a\n literal \\ character must be written as \\\\.

    If two alternatives within the pattern both match at the same position in the\n $input, then the match that is chosen is the one matched by the first\n alternative. For example:

    fn:replace(\"abcd\", \"(ab)|(a)\", \"[1=$1][2=$2]\") returns \"[1=ab][2=]cd\"

    A dynamic error is raised if the value of\n $pattern is invalid according to the rules described in section .

    A dynamic error is raised if the value of\n $flags is invalid according to the rules described in section .

    A dynamic error is raised if the pattern matches a\n zero-length string, that is, if the expression fn:matches(\"\", $pattern,\n $flags) returns true. It is not an error, however, if a captured\n substring is zero-length.

    A dynamic error is raised if the value of\n $replacement contains a \"$\" character that is not\n immediately followed by a digit 0-9 and not immediately preceded by a\n \"\\\".

    A dynamic error is raised if the value of\n $replacement contains a \"\\\" character that is not part of a\n \"\\\\\" pair, unless it is immediately followed by a \"$\"\n character.

    \n", "summary" : "

    Returns a string produced from the input string by replacing any substrings\n that match a given regular expression with a supplied replacement string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "replacement", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "replace", "qname" : "fn:replace", "signature" : "($input as xs:string?, $pattern as xs:string, $replacement as xs:string, $flags as xs:string) as xs:string external", "description" : "

    Returns a string produced from the input string by replacing any substrings\n that match a given regular expression with a supplied replacement string.

    This function is deterministic, context-independent, and focus-independent.

    The effect of calling the first version of this function (omitting the argument\n $flags) is the same as the effect of calling the second version with the\n $flags argument set to a zero-length string. Flags are defined in\n .

    The $flags argument is interpreted in the same manner as for the\n fn:matches function.

    If $input is the empty sequence, it is interpreted as the zero-length\n string.

    The function returns the xs:string that is obtained by replacing each\n non-overlapping substring of $input that matches the given\n $pattern with an occurrence of the $replacement string.

    If two overlapping substrings of $input both match the\n $pattern, then only the first one (that is, the one whose first character comes first in the $input string) is\n replaced.

    If the q flag is present, the replacement string is used\n as is.

    Otherwise, within the $replacement\n string, a variable $N may be used to refer to the substring captured by the\n Nth parenthesized sub-expression in the regular expression. For each match of the\n pattern, these variables are assigned the value of the content matched by the relevant\n sub-expression, and the modified replacement string is then substituted for the characters in $input that matched the pattern.\n $0 refers to the substring captured by the regular expression as a\n whole.

    More specifically, the rules are as follows, where S is the number of\n parenthesized sub-expressions in the regular expression, and N is the\n decimal number formed by taking all the digits that consecutively follow the\n $ character:

    If N=0, then the variable is replaced by the substring\n matched by the regular expression as a whole.

    If 1<=N<=S, then the variable is\n replaced by the substring captured by the Nth parenthesized sub-expression. If the\n Nth parenthesized sub-expression was not matched, then the\n variable is replaced by the zero-length string.

    If S<N<=9, then the variable is\n replaced by the zero-length string.

    Otherwise (if N>S and\n N>9), the last digit of N is taken to\n be a literal character to be included \"as is\" in the replacement string, and the\n rules are reapplied using the number N formed by stripping off this\n last digit.

    For example, if the replacement string is \n $23\n and there are 5 substrings, the result contains the value of the substring that\n matches the second sub-expression, followed by the digit \n 3\n .

    Unless the q flag is used, a literal $\n character within the replacement string must be written as \\$, and a\n literal \\ character must be written as \\\\.

    If two alternatives within the pattern both match at the same position in the\n $input, then the match that is chosen is the one matched by the first\n alternative. For example:

    fn:replace(\"abcd\", \"(ab)|(a)\", \"[1=$1][2=$2]\") returns \"[1=ab][2=]cd\"

    A dynamic error is raised if the value of\n $pattern is invalid according to the rules described in section .

    A dynamic error is raised if the value of\n $flags is invalid according to the rules described in section .

    A dynamic error is raised if the pattern matches a\n zero-length string, that is, if the expression fn:matches(\"\", $pattern,\n $flags) returns true. It is not an error, however, if a captured\n substring is zero-length.

    A dynamic error is raised if the value of\n $replacement contains a \"$\" character that is not\n immediately followed by a digit 0-9 and not immediately preceded by a\n \"\\\".

    A dynamic error is raised if the value of\n $replacement contains a \"\\\" character that is not part of a\n \"\\\\\" pair, unless it is immediately followed by a \"$\"\n character.

    \n", "summary" : "

    Returns a string produced from the input string by replacing any substrings\n that match a given regular expression with a supplied replacement string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "replacement", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "flags", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "resolve-QName", "qname" : "fn:resolve-QName", "signature" : "($qname as xs:string?, $element as element(*)) as xs:QName? external", "description" : "

    Returns an xs:QName value (that is, an expanded-QName) by taking\n an xs:string that has the lexical form of an xs:QName (a\n string in the form \"prefix:local-name\" or \"local-name\") and resolving it using the\n in-scope namespaces for a given element.

    This function is deterministic, context-independent, and focus-independent.

    If $qname is the empty sequence, returns the empty sequence.

    More specifically, the function searches the namespace bindings of $element\n for a binding whose name matches the prefix of $qname, or the zero-length\n string if it has no prefix, and constructs an expanded-QName whose local name is taken\n from the supplied $qname, and whose namespace URI is taken from the string\n value of the namespace binding.

    If the $qname has no prefix, and there is no namespace binding for\n $element corresponding to the default (unnamed) namespace, then the\n resulting expanded-QName has no namespace part.

    The prefix (or absence of a prefix) in the supplied $qname argument is\n retained in the returned expanded-QName, as discussed in .

    A dynamic error is raised if $qname does not\n have the correct lexical form for an instance of xs:QName.

    A dynamic error is raised if $qname has a\n prefix and there is no namespace binding for $element that matches this\n prefix.

    \n", "summary" : "

    Returns an xs:QName value (that is, an expanded-QName) by taking\n an xs:string that has the lexical form of an xs:QName (a\n string in the form \"prefix:local-name\" or \"local-name\") and resolving it using the\n in-scope namespaces for a given element.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "qname", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "element", "type" : "element(*)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:QName?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "resolve-uri", "qname" : "fn:resolve-uri", "signature" : "($relative as xs:string?) as xs:anyURI? external", "description" : "

    Resolves a relative IRI reference against an absolute IRI.

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    If the second argument is absent, the effect is the same as calling the two-argument\n function with the value of fn:static-base-uri() as the second argument.

    The function is defined to operate on IRI references as defined in , and the implementation must permit all arguments that are valid\n according to that specification. In addition, the implementation may\n accept some or all strings that conform to the rules for (absolute or relative) Legacy\n Extended IRI references as defined in . For the purposes of this\n section, the terms IRI and IRI reference include these extensions, insofar as the\n implementation chooses to support them.

    If $relative is the empty sequence, the function returns the empty\n sequence.

    If $relative is an absolute IRI (as defined above), then it is returned\n unchanged.

    Otherwise, the function resolves the relative IRI reference $relative\n against the base IRI $base using the algorithm defined in , adapted by treating any character\n that would not be valid in an RFC3986 URI or relative reference in the same way that\n RFC3986 treats unreserved characters. No percent-encoding takes place.

    The first form of this function resolves $relative against the value of the\n base-uri property from the static context. A dynamic error is raised if the base-uri property is not initialized in the static context.

    A dynamic error is raised if $relative is not a\n valid IRI according to the rules of RFC3987, extended with an implementation-defined\n subset of the extensions permitted in LEIRI, or if it is not a suitable relative\n reference to use as input to the RFC3986 resolution algorithm extended to handle\n additional unreserved characters.

    A dynamic error is raised if $base is not a\n valid IRI according to the rules of RFC3987, extended with an implementation-defined\n subset of the extensions permitted in LEIRI, or if it is not a suitable IRI to use as\n input to the chosen resolution algorithm (for example, if it is a relative IRI\n reference, if it is a non-hierarchic URI, or if it contains a fragment identifier).

    A dynamic error is raised if the chosen resolution algorithm\n fails for any other reason.

    \n", "summary" : "

    Resolves a relative IRI reference against an absolute IRI.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "relative", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:anyURI?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "resolve-uri", "qname" : "fn:resolve-uri", "signature" : "($relative as xs:string?, $base as xs:string) as xs:anyURI? external", "description" : "

    Resolves a relative IRI reference against an absolute IRI.

    The one-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The two-argument form of this function is deterministic, context-independent, and focus-independent.

    If the second argument is absent, the effect is the same as calling the two-argument\n function with the value of fn:static-base-uri() as the second argument.

    The function is defined to operate on IRI references as defined in , and the implementation must permit all arguments that are valid\n according to that specification. In addition, the implementation may\n accept some or all strings that conform to the rules for (absolute or relative) Legacy\n Extended IRI references as defined in . For the purposes of this\n section, the terms IRI and IRI reference include these extensions, insofar as the\n implementation chooses to support them.

    If $relative is the empty sequence, the function returns the empty\n sequence.

    If $relative is an absolute IRI (as defined above), then it is returned\n unchanged.

    Otherwise, the function resolves the relative IRI reference $relative\n against the base IRI $base using the algorithm defined in , adapted by treating any character\n that would not be valid in an RFC3986 URI or relative reference in the same way that\n RFC3986 treats unreserved characters. No percent-encoding takes place.

    The first form of this function resolves $relative against the value of the\n base-uri property from the static context. A dynamic error is raised if the base-uri property is not initialized in the static context.

    A dynamic error is raised if $relative is not a\n valid IRI according to the rules of RFC3987, extended with an implementation-defined\n subset of the extensions permitted in LEIRI, or if it is not a suitable relative\n reference to use as input to the RFC3986 resolution algorithm extended to handle\n additional unreserved characters.

    A dynamic error is raised if $base is not a\n valid IRI according to the rules of RFC3987, extended with an implementation-defined\n subset of the extensions permitted in LEIRI, or if it is not a suitable IRI to use as\n input to the chosen resolution algorithm (for example, if it is a relative IRI\n reference, if it is a non-hierarchic URI, or if it contains a fragment identifier).

    A dynamic error is raised if the chosen resolution algorithm\n fails for any other reason.

    \n", "summary" : "

    Resolves a relative IRI reference against an absolute IRI.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "relative", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "base", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:anyURI?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "reverse", "qname" : "fn:reverse", "signature" : "($arg as item()*) as item()* external", "description" : "

    Reverses the order of items in a sequence.

    This function is deterministic, context-independent, and focus-independent.

    The function returns a sequence containing the items in $arg in reverse\n order.

    For detailed type semantics, see [Formal Semantics].

    If $arg is the empty sequence, the empty sequence is returned.

    \n", "summary" : "

    Reverses the order of items in a sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "root", "qname" : "fn:root", "signature" : "() as node() external", "description" : "

    Returns the root of the tree to which $arg belongs. This will\n usually, but not necessarily, be a document node.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the function is called without an argument, the context item (.) is used\n as the default argument. The behavior of the function if the argument is omitted is\n exactly the same as if the context item had been passed as the argument.

    The function returns the value of the expression\n ($arg/ancestor-or-self::node())[1].

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the root of the tree to which $arg belongs.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "node()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "root", "qname" : "fn:root", "signature" : "($arg as node()?) as node()? external", "description" : "

    Returns the root of the tree to which $arg belongs. This will\n usually, but not necessarily, be a document node.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    If the function is called without an argument, the context item (.) is used\n as the default argument. The behavior of the function if the argument is omitted is\n exactly the same as if the context item had been passed as the argument.

    The function returns the value of the expression\n ($arg/ancestor-or-self::node())[1].

    The following errors may be raised when $arg is omitted:

    • If the context\n item is absent, dynamic error\n

    • If the context item is not a\n node, type error .

    \n", "summary" : "

    Returns the root of the tree to which $arg belongs.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "node()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "node()?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "round-half-to-even", "qname" : "fn:round-half-to-even", "signature" : "($arg as numeric?) as numeric? external", "description" : "

    Rounds a value to a specified number of decimal places, rounding to make the\n last digit even if two such values are equally near.

    This function is deterministic, context-independent, and focus-independent.

    General rules: see .

    The function returns the nearest (that is, numerically closest) value to\n $arg that is a multiple of ten to the power of minus\n $precision. If two such values are equally near (e.g. if the fractional\n part in $arg is exactly .500...), the function returns the one whose least\n significant digit is even.

    If the type of $arg is one of the four numeric types xs:float,\n xs:double, xs:decimal or xs:integer the type\n of the result is the same as the type of $arg. If the type of\n $arg is a type derived from one of the numeric types, the result is an\n instance of the base numeric type.

    The first signature of this function produces the same result as the second signature\n with $precision=0.

    For arguments of type xs:float and xs:double:

    If the argument is NaN, positive or negative zero, or positive or\n negative infinity, then the result is the same as the argument.

    In all other cases, the argument is cast to xs:decimal\n using an implementation of xs:decimal that imposes no\n limits on the number of digits that can be represented. The function\n is applied to this xs:decimal value, and the resulting\n xs:decimal is cast back to xs:float or\n xs:double as appropriate to form the function result. If the\n resulting xs:decimal value is zero, then positive or negative zero is\n returned according to the sign of the original argument.

    For detailed type semantics, see [Formal Semantics].

    This function is typically used in financial applications where the\n argument is of type xs:decimal. For arguments of type xs:float\n and xs:double the results may be counter-intuitive. For example, consider\n round-half-to-even(xs:float(150.015), 2). The result is not 150.02 as\n might be expected, but 150.01. This is because the conversion of the\n xs:float value represented by the literal 150.015 to an\n xs:decimal produces the xs:decimal value 150.014999389...,\n which is closer to 150.01 than to 150.02.

    \n", "summary" : "

    Rounds a value to a specified number of decimal places, rounding to make the\n last digit even if two such values are equally near.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "numeric", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "numeric?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "round-half-to-even", "qname" : "fn:round-half-to-even", "signature" : "($arg as numeric?, $precision as xs:integer) as numeric? external", "description" : "

    Rounds a value to a specified number of decimal places, rounding to make the\n last digit even if two such values are equally near.

    This function is deterministic, context-independent, and focus-independent.

    General rules: see .

    The function returns the nearest (that is, numerically closest) value to\n $arg that is a multiple of ten to the power of minus\n $precision. If two such values are equally near (e.g. if the fractional\n part in $arg is exactly .500...), the function returns the one whose least\n significant digit is even.

    If the type of $arg is one of the four numeric types xs:float,\n xs:double, xs:decimal or xs:integer the type\n of the result is the same as the type of $arg. If the type of\n $arg is a type derived from one of the numeric types, the result is an\n instance of the base numeric type.

    The first signature of this function produces the same result as the second signature\n with $precision=0.

    For arguments of type xs:float and xs:double:

    If the argument is NaN, positive or negative zero, or positive or\n negative infinity, then the result is the same as the argument.

    In all other cases, the argument is cast to xs:decimal\n using an implementation of xs:decimal that imposes no\n limits on the number of digits that can be represented. The function\n is applied to this xs:decimal value, and the resulting\n xs:decimal is cast back to xs:float or\n xs:double as appropriate to form the function result. If the\n resulting xs:decimal value is zero, then positive or negative zero is\n returned according to the sign of the original argument.

    For detailed type semantics, see [Formal Semantics].

    This function is typically used in financial applications where the\n argument is of type xs:decimal. For arguments of type xs:float\n and xs:double the results may be counter-intuitive. For example, consider\n round-half-to-even(xs:float(150.015), 2). The result is not 150.02 as\n might be expected, but 150.01. This is because the conversion of the\n xs:float value represented by the literal 150.015 to an\n xs:decimal produces the xs:decimal value 150.014999389...,\n which is closer to 150.01 than to 150.02.

    \n", "summary" : "

    Rounds a value to a specified number of decimal places, rounding to make the\n last digit even if two such values are equally near.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "numeric", "occurrence" : "?", "description" : "" }, { "name" : "precision", "type" : "xs:integer", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "numeric?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "round", "qname" : "fn:round", "signature" : "($arg as numeric?) as numeric? external", "description" : "

    Rounds a value to a specified number of decimal places, rounding upwards if two\n such values are equally near.

    This function is deterministic, context-independent, and focus-independent.

    General rules: see .

    The function returns the nearest (that is, numerically closest) value to\n $arg that is a multiple of ten to the power of minus\n $precision. If two such values are equally near (for example, if the\n fractional part in $arg is exactly .5), the function returns the one that\n is closest to positive infinity.

    If the type of $arg is one of the four numeric types xs:float,\n xs:double, xs:decimal or xs:integer the type\n of the result is the same as the type of $arg. If the type of\n $arg is a type derived from one of the numeric types, the result is an\n instance of the base numeric type.

    The single-argument version of this function produces the same result as the\n two-argument version with $precision=0 (that is, it rounds to a whole\n number).

    When $arg is of type xs:float and xs:double:

    If $arg is NaN, positive or negative zero, or positive or negative\n infinity, then the result is the same as the argument.

    For other values, the argument is cast to xs:decimal using an\n implementation of xs:decimal that imposes no limits on the number of\n digits that can be represented. The function is applied to this\n xs:decimal value, and the resulting xs:decimal is\n cast back to xs:float or xs:double as appropriate to\n form the function result. If the resulting xs:decimal value is zero,\n then positive or negative zero is returned according to the sign of\n $arg.

    For detailed type semantics, see [Formal Semantics].

    This function is typically used with a non-zero $precision in financial\n applications where the argument is of type xs:decimal. For arguments of\n type xs:float and xs:double the results may be\n counter-intuitive. For example, consider round(35.425e0, 2). The result is\n not 35.43, as might be expected, but 35.42. This is because the xs:double written as 35.425e0\n has an exact value equal to 35.42499999999..., which is closer\n to 35.42 than to 35.43.

    \n", "summary" : "

    Rounds a value to a specified number of decimal places, rounding upwards if two\n such values are equally near.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "numeric", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "numeric?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "round", "qname" : "fn:round", "signature" : "($arg as numeric?, $precision as xs:integer) as numeric? external", "description" : "

    Rounds a value to a specified number of decimal places, rounding upwards if two\n such values are equally near.

    This function is deterministic, context-independent, and focus-independent.

    General rules: see .

    The function returns the nearest (that is, numerically closest) value to\n $arg that is a multiple of ten to the power of minus\n $precision. If two such values are equally near (for example, if the\n fractional part in $arg is exactly .5), the function returns the one that\n is closest to positive infinity.

    If the type of $arg is one of the four numeric types xs:float,\n xs:double, xs:decimal or xs:integer the type\n of the result is the same as the type of $arg. If the type of\n $arg is a type derived from one of the numeric types, the result is an\n instance of the base numeric type.

    The single-argument version of this function produces the same result as the\n two-argument version with $precision=0 (that is, it rounds to a whole\n number).

    When $arg is of type xs:float and xs:double:

    If $arg is NaN, positive or negative zero, or positive or negative\n infinity, then the result is the same as the argument.

    For other values, the argument is cast to xs:decimal using an\n implementation of xs:decimal that imposes no limits on the number of\n digits that can be represented. The function is applied to this\n xs:decimal value, and the resulting xs:decimal is\n cast back to xs:float or xs:double as appropriate to\n form the function result. If the resulting xs:decimal value is zero,\n then positive or negative zero is returned according to the sign of\n $arg.

    For detailed type semantics, see [Formal Semantics].

    This function is typically used with a non-zero $precision in financial\n applications where the argument is of type xs:decimal. For arguments of\n type xs:float and xs:double the results may be\n counter-intuitive. For example, consider round(35.425e0, 2). The result is\n not 35.43, as might be expected, but 35.42. This is because the xs:double written as 35.425e0\n has an exact value equal to 35.42499999999..., which is closer\n to 35.42 than to 35.43.

    \n", "summary" : "

    Rounds a value to a specified number of decimal places, rounding upwards if two\n such values are equally near.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "numeric", "occurrence" : "?", "description" : "" }, { "name" : "precision", "type" : "xs:integer", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "numeric?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "seconds-from-dateTime", "qname" : "fn:seconds-from-dateTime", "signature" : "($arg as xs:dateTime?) as xs:decimal? external", "description" : "

    Returns the seconds component of an xs:dateTime.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:decimal value greater than or equal\n to zero and less than 60, representing the seconds and fractional seconds in the local\n value of $arg.

    The expression fn:seconds-from-dateTime(xs:dateTime(\"1999-05-31T13:20:00-05:00\")) returns 0.

    \n", "summary" : "

    Returns the seconds component of an xs:dateTime .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:dateTime", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:decimal?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "seconds-from-duration", "qname" : "fn:seconds-from-duration", "signature" : "($arg as xs:duration?) as xs:decimal? external", "description" : "

    Returns the number of seconds in a duration.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:decimal representing the seconds\n component in the value of $arg. The result is obtained by casting\n $arg to an xs:dayTimeDuration (see ) and then computing the seconds component as described\n in .

    If $arg is a negative duration then the result will be negative..

    If $arg is an xs:yearMonthDuration the function returns 0.

    The expression fn:seconds-from-duration(xs:dayTimeDuration(\"P3DT10H12.5S\")) returns 12.5.

    The expression fn:seconds-from-duration(xs:dayTimeDuration(\"-PT256S\")) returns -16.0.

    \n", "summary" : "

    Returns the number of seconds in a duration.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:duration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:decimal?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "seconds-from-time", "qname" : "fn:seconds-from-time", "signature" : "($arg as xs:time?) as xs:decimal? external", "description" : "

    Returns the seconds component of an xs:time.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:decimal value greater than or equal\n to zero and less than 60, representing the seconds and fractional seconds in the local\n value of $arg.

    The expression fn:seconds-from-time(xs:time(\"13:20:10.5\")) returns 10.5.

    \n", "summary" : "

    Returns the seconds component of an xs:time .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:time", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:decimal?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "serialize", "qname" : "fn:serialize", "signature" : "($arg as item()*) as xs:string external", "description" : "

    This function serializes the supplied input\n sequence\n $arg as described in ,\n returning the serialized representation of the\n sequence as a string.

    This function is deterministic, context-independent, and focus-independent.

    The value of $arg acts as the input sequence to the serialization process,\n which starts with sequence normalization.

    The single-argument version of this function has the same effect as\n the two-argument version called with $params set to an empty sequence. This\n in turn is the same as the effect of passing an\n output:serialization-parameters element with no child elements.

    The $params argument is used to identify a set of\n serialization parameters. These are supplied in the form of an\n output:serialization-parameters element, having the format described in\n .

    The final stage of serialization, that is, encoding, is skipped. If the serializer does\n not allow this phase to be skipped, then the sequence of octets returned by the\n serializer is decoded into a string by reversing the character encoding performed in the\n final stage.

    If the host language makes serialization an optional feature and\n the implementation does not support serialization, then a dynamic error\n is raised.

    The serialization process will raise an error if $arg is an attribute or\n namespace node.

    If any serialization error occurs, including the detection of an invalid value for a\n serialization parameter, this results in the fn:serialize call failing with\n a dynamic error.

    \n", "summary" : "

    This function serializes the supplied input\n sequence \n $arg as described in ,\n returning the serialized representation of the\n sequence as a string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "serialize", "qname" : "fn:serialize", "signature" : "($arg as item()*, $params as element(output:serialization-parameters)?) as xs:string external", "description" : "

    This function serializes the supplied input\n sequence\n $arg as described in ,\n returning the serialized representation of the\n sequence as a string.

    This function is deterministic, context-independent, and focus-independent.

    The value of $arg acts as the input sequence to the serialization process,\n which starts with sequence normalization.

    The single-argument version of this function has the same effect as\n the two-argument version called with $params set to an empty sequence. This\n in turn is the same as the effect of passing an\n output:serialization-parameters element with no child elements.

    The $params argument is used to identify a set of\n serialization parameters. These are supplied in the form of an\n output:serialization-parameters element, having the format described in\n .

    The final stage of serialization, that is, encoding, is skipped. If the serializer does\n not allow this phase to be skipped, then the sequence of octets returned by the\n serializer is decoded into a string by reversing the character encoding performed in the\n final stage.

    If the host language makes serialization an optional feature and\n the implementation does not support serialization, then a dynamic error\n is raised.

    The serialization process will raise an error if $arg is an attribute or\n namespace node.

    If any serialization error occurs, including the detection of an invalid value for a\n serialization parameter, this results in the fn:serialize call failing with\n a dynamic error.

    \n", "summary" : "

    This function serializes the supplied input\n sequence \n $arg as described in ,\n returning the serialized representation of the\n sequence as a string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "params", "type" : "element(output:serialization-parameters)", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "starts-with", "qname" : "fn:starts-with", "signature" : "($arg1 as xs:string?, $arg2 as xs:string?) as xs:boolean external", "description" : "

    Returns true if the string $arg1 contains $arg2 as a\n leading substring, taking collations into account.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri.\n \t

    If the value of $arg1 or $arg2 is the empty sequence, or\n contains only ignorable collation units, it is interpreted as the zero-length\n string.

    If the value of $arg2 is the zero-length string, then the function returns\n true. If the value of $arg1 is the zero-length string and\n the value of $arg2 is not the zero-length string, then the function returns\n false.

    The collation used by this function is determined according to the rules in .

    The function returns an xs:boolean indicating whether or not the value of\n $arg1 starts with a sequence of collation units that provides a\n match to the collation units of $arg2 according to the\n collation that is used.

    Match is defined in .

    A dynamic error may be raised if the\n specified collation does not support collation units.

    \n", "summary" : "

    Returns true if the string $arg1 contains $arg2 as a\n leading substring, taking collations into account.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "arg2", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "starts-with", "qname" : "fn:starts-with", "signature" : "($arg1 as xs:string?, $arg2 as xs:string?, $collation as xs:string) as xs:boolean external", "description" : "

    Returns true if the string $arg1 contains $arg2 as a\n leading substring, taking collations into account.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri.\n \t

    If the value of $arg1 or $arg2 is the empty sequence, or\n contains only ignorable collation units, it is interpreted as the zero-length\n string.

    If the value of $arg2 is the zero-length string, then the function returns\n true. If the value of $arg1 is the zero-length string and\n the value of $arg2 is not the zero-length string, then the function returns\n false.

    The collation used by this function is determined according to the rules in .

    The function returns an xs:boolean indicating whether or not the value of\n $arg1 starts with a sequence of collation units that provides a\n match to the collation units of $arg2 according to the\n collation that is used.

    Match is defined in .

    A dynamic error may be raised if the\n specified collation does not support collation units.

    \n", "summary" : "

    Returns true if the string $arg1 contains $arg2 as a\n leading substring, taking collations into account.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "arg2", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "collation", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "static-base-uri", "qname" : "fn:static-base-uri", "signature" : "() as xs:anyURI? external", "description" : "

    This function returns the value of the Static Base URI property from the static context.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The function returns the value of the Static Base URI property from the static context. If the\n property is absent, the empty sequence is returned.

    Components of the static context are discussed in .

    XQuery 3.0 and XSLT 3.0 give an implementation freedom to use different base URIs during the\n static analysis phase and the dynamic evaluation phase, that is, for compile-time and run-time resources respectively.\n In this situation, the fn:static-base-uri function should return a URI suitable for locating resources needed\n during dynamic evaluation.

    \n", "summary" : "

    This function returns the value of the Static Base URI property from the static context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:anyURI?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "string-join", "qname" : "fn:string-join", "signature" : "($arg1 as xs:string*) as xs:string external", "description" : "

    Returns a string created by concatenating the items in a sequence, with a\n defined separator between adjacent items.

    This function is deterministic, context-independent, and focus-independent.

    The effect of calling the single-argument version of this function is\n the same as calling the two-argument version with $arg2 set to a\n zero-length string.

    The function returns an xs:string created by concatenating the items in the\n sequence $arg1, in order, using the value of $arg2 as a\n separator between adjacent items. If the value of $arg2 is the zero-length\n string, then the members of $arg1 are concatenated without a separator.

    If the value of $arg1 is the empty sequence, the function returns the\n zero-length string.

    \n", "summary" : "

    Returns a string created by concatenating the items in a sequence, with a\n defined separator between adjacent items.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:string", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "string-join", "qname" : "fn:string-join", "signature" : "($arg1 as xs:string*, $arg2 as xs:string) as xs:string external", "description" : "

    Returns a string created by concatenating the items in a sequence, with a\n defined separator between adjacent items.

    This function is deterministic, context-independent, and focus-independent.

    The effect of calling the single-argument version of this function is\n the same as calling the two-argument version with $arg2 set to a\n zero-length string.

    The function returns an xs:string created by concatenating the items in the\n sequence $arg1, in order, using the value of $arg2 as a\n separator between adjacent items. If the value of $arg2 is the zero-length\n string, then the members of $arg1 are concatenated without a separator.

    If the value of $arg1 is the empty sequence, the function returns the\n zero-length string.

    \n", "summary" : "

    Returns a string created by concatenating the items in a sequence, with a\n defined separator between adjacent items.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:string", "occurrence" : "*", "description" : "" }, { "name" : "arg2", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "string-length", "qname" : "fn:string-length", "signature" : "() as xs:integer external", "description" : "

    Returns the number of characters in a\n string.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    The function returns an xs:integer equal to the length in characters of the value of $arg.

    Calling the zero-argument version of the function is equivalent to calling\n fn:string-length(fn:string(.)).

    If the value of $arg is the empty sequence, the function returns the\n xs:integer value zero (0).

    If $arg is not specified and the context item is absent, a dynamic error is raised: .

    \n", "summary" : "

    Returns the number of characters in a\n string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "string-length", "qname" : "fn:string-length", "signature" : "($arg as xs:string?) as xs:integer external", "description" : "

    Returns the number of characters in a\n string.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    The function returns an xs:integer equal to the length in characters of the value of $arg.

    Calling the zero-argument version of the function is equivalent to calling\n fn:string-length(fn:string(.)).

    If the value of $arg is the empty sequence, the function returns the\n xs:integer value zero (0).

    If $arg is not specified and the context item is absent, a dynamic error is raised: .

    \n", "summary" : "

    Returns the number of characters in a\n string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "string-to-codepoints", "qname" : "fn:string-to-codepoints", "signature" : "($arg as xs:string?) as xs:integer* external", "description" : "

    Returns the sequence of codepoints that\n constitute an xs:string value.

    This function is deterministic, context-independent, and focus-independent.

    The function returns a sequence of integers, each integer being the Unicode codepoints of the corresponding character in $arg.

    If $arg is a zero-length string or the empty sequence, the function returns\n the empty sequence.

    The expression fn:string-to-codepoints(\"Thérèse\") returns (84, 104, 233, 114, 232, 115, 101).

    \n", "summary" : "

    Returns the sequence of codepoints that\n constitute an xs:string value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "string-to-codepoints", "qname" : "fn:string-to-codepoints", "signature" : "($arg as xs:string?) as xs:integer* external", "description" : "

    Returns the sequence of codepoints that\n constitute an xs:string value.

    This function is deterministic, context-independent, and focus-independent.

    The function returns a sequence of integers, each integer being the Unicode codepoints of the corresponding character in $arg.

    If $arg is a zero-length string or the empty sequence, the function returns\n the empty sequence.

    The expression fn:string-to-codepoints(\"Thérèse\") returns (84, 104, 233, 114, 232, 115, 101).

    \n", "summary" : "

    Returns the sequence of codepoints that\n constitute an xs:string value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "string", "qname" : "fn:string", "signature" : "() as xs:string external", "description" : "

    Returns the value of $arg represented as an\n xs:string.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    In the zero-argument version of the function, $arg defaults to the context\n item. That is, calling fn:string() is equivalent to calling\n fn:string(.).

    If $arg is the empty sequence, the function returns the zero-length\n string.

    If $arg is a node, the function returns the string-value of the node, as\n obtained using the dm:string-value accessor defined in (see ).

    If $arg is an atomic value, the function returns the result of the\n expression $arg cast as xs:string (see ).

    A dynamic error is raised by the\n zero-argument version of the function if the context item is absent.

    A type error is raised if\n $arg is a function item.

    \n", "summary" : "

    Returns the value of $arg represented as an\n xs:string .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "string", "qname" : "fn:string", "signature" : "($arg as item()?) as xs:string external", "description" : "

    Returns the value of $arg represented as an\n xs:string.

    The zero-argument form of this function is deterministic, context-dependent, and focus-dependent.

    The one-argument form of this function is deterministic, context-independent, and focus-independent.

    In the zero-argument version of the function, $arg defaults to the context\n item. That is, calling fn:string() is equivalent to calling\n fn:string(.).

    If $arg is the empty sequence, the function returns the zero-length\n string.

    If $arg is a node, the function returns the string-value of the node, as\n obtained using the dm:string-value accessor defined in (see ).

    If $arg is an atomic value, the function returns the result of the\n expression $arg cast as xs:string (see ).

    A dynamic error is raised by the\n zero-argument version of the function if the context item is absent.

    A type error is raised if\n $arg is a function item.

    \n", "summary" : "

    Returns the value of $arg represented as an\n xs:string .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "subsequence", "qname" : "fn:subsequence", "signature" : "($sourceSeq as item()*, $startingLoc as xs:double) as item()* external", "description" : "

    Returns the contiguous sequence of items in the value of\n $sourceSeq beginning at the position indicated by the value of\n $startingLoc and continuing for the number of items indicated by the\n value of $length.

    This function is deterministic, context-independent, and focus-independent.

    In the two-argument case, returns:

    $sourceSeq[fn:round($startingLoc) le position()]

    In the three-argument case, returns:

    $sourceSeq[fn:round($startingLoc) le position()\n and position() lt fn:round($startingLoc) + fn:round($length)]

    For detailed type semantics, see [Formal Semantics].

    The first item of a sequence is located at position 1, not position 0.

    If $sourceSeq is the empty sequence, the empty sequence is returned.

    If $startingLoc is zero or negative, the subsequence includes items from\n the beginning of the $sourceSeq.

    If $length is not specified, the subsequence includes items to the end of\n $sourceSeq.

    If $length is greater than the number of items in the value of\n $sourceSeq following $startingLoc, the subsequence includes\n items to the end of $sourceSeq.

    As an exception to the previous two notes, if\n $startingLoc is -INF and $length is\n +INF, then fn:round($startingLoc) + fn:round($length) is\n NaN; since position() lt NaN is always false, the result is\n an empty sequence.

    The reason the function accepts arguments of type xs:double is that many\n computations on untyped data return an xs:double result; and the reason for\n the rounding rules is to compensate for any imprecision in these floating-point\n computations.

    \n", "summary" : "

    Returns the contiguous sequence of items in the value of\n $sourceSeq beginning at the position indicated by the value of\n $startingLoc and continuing for the number of items indicated by the\n value of $length .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "sourceSeq", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "startingLoc", "type" : "xs:double", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "subsequence", "qname" : "fn:subsequence", "signature" : "($sourceSeq as item()*, $startingLoc as xs:double, $length as xs:double) as item()* external", "description" : "

    Returns the contiguous sequence of items in the value of\n $sourceSeq beginning at the position indicated by the value of\n $startingLoc and continuing for the number of items indicated by the\n value of $length.

    This function is deterministic, context-independent, and focus-independent.

    In the two-argument case, returns:

    $sourceSeq[fn:round($startingLoc) le position()]

    In the three-argument case, returns:

    $sourceSeq[fn:round($startingLoc) le position()\n and position() lt fn:round($startingLoc) + fn:round($length)]

    For detailed type semantics, see [Formal Semantics].

    The first item of a sequence is located at position 1, not position 0.

    If $sourceSeq is the empty sequence, the empty sequence is returned.

    If $startingLoc is zero or negative, the subsequence includes items from\n the beginning of the $sourceSeq.

    If $length is not specified, the subsequence includes items to the end of\n $sourceSeq.

    If $length is greater than the number of items in the value of\n $sourceSeq following $startingLoc, the subsequence includes\n items to the end of $sourceSeq.

    As an exception to the previous two notes, if\n $startingLoc is -INF and $length is\n +INF, then fn:round($startingLoc) + fn:round($length) is\n NaN; since position() lt NaN is always false, the result is\n an empty sequence.

    The reason the function accepts arguments of type xs:double is that many\n computations on untyped data return an xs:double result; and the reason for\n the rounding rules is to compensate for any imprecision in these floating-point\n computations.

    \n", "summary" : "

    Returns the contiguous sequence of items in the value of\n $sourceSeq beginning at the position indicated by the value of\n $startingLoc and continuing for the number of items indicated by the\n value of $length .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "sourceSeq", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "startingLoc", "type" : "xs:double", "occurrence" : null, "description" : "" }, { "name" : "length", "type" : "xs:double", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "substring-after", "qname" : "fn:substring-after", "signature" : "($arg1 as xs:string?, $arg2 as xs:string?) as xs:string external", "description" : "

    Returns the part of $arg1 that follows the first occurrence of\n $arg2, taking collations into account.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri.\n \t

    If the value of $arg1 or $arg2 is the empty sequence, or\n contains only ignorable collation units, it is interpreted as the zero-length\n string.

    If the value of $arg2 is the zero-length string, then the function returns\n the value of $arg1.

    If the value of $arg1 does not contain a string that is equal to the value\n of $arg2, then the function returns the zero-length string.

    The collation used by this function is determined according to the rules in .

    The function returns the substring of the value of $arg1 that follows in\n the value of $arg1 the first occurrence of a sequence of collation units\n that provides a minimal match to the collation units of $arg2\n according to the collation that is used.

    Minimal match is defined in .

    A dynamic error may be raised if the\n specified collation does not support collation units.

    \n", "summary" : "

    Returns the part of $arg1 that follows the first occurrence of\n $arg2 , taking collations into account.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "arg2", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "substring-after", "qname" : "fn:substring-after", "signature" : "($arg1 as xs:string?, $arg2 as xs:string?, $collation as xs:string) as xs:string external", "description" : "

    Returns the part of $arg1 that follows the first occurrence of\n $arg2, taking collations into account.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri.\n \t

    If the value of $arg1 or $arg2 is the empty sequence, or\n contains only ignorable collation units, it is interpreted as the zero-length\n string.

    If the value of $arg2 is the zero-length string, then the function returns\n the value of $arg1.

    If the value of $arg1 does not contain a string that is equal to the value\n of $arg2, then the function returns the zero-length string.

    The collation used by this function is determined according to the rules in .

    The function returns the substring of the value of $arg1 that follows in\n the value of $arg1 the first occurrence of a sequence of collation units\n that provides a minimal match to the collation units of $arg2\n according to the collation that is used.

    Minimal match is defined in .

    A dynamic error may be raised if the\n specified collation does not support collation units.

    \n", "summary" : "

    Returns the part of $arg1 that follows the first occurrence of\n $arg2 , taking collations into account.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "arg2", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "collation", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "substring-before", "qname" : "fn:substring-before", "signature" : "($arg1 as xs:string?, $arg2 as xs:string?) as xs:string external", "description" : "

    Returns the part of $arg1 that precedes the first occurrence of\n $arg2, taking collations into account.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri.\n \t

    If the value of $arg1 or $arg2 is the empty sequence, or\n contains only ignorable collation units, it is interpreted as the zero-length\n string.

    If the value of $arg2 is the zero-length string, then the function returns\n the zero-length string.

    If the value of $arg1 does not contain a string that is equal to the value\n of $arg2, then the function returns the zero-length string.

    The collation used by this function is determined according to the rules in .

    The function returns the substring of the value of $arg1 that precedes in\n the value of $arg1 the first occurrence of a sequence of collation units\n that provides a minimal match to the collation units of $arg2\n according to the collation that is used.

    Minimal match is defined in .

    A dynamic error may be raised if the\n specified collation does not support collation units.

    \n", "summary" : "

    Returns the part of $arg1 that precedes the first occurrence of\n $arg2 , taking collations into account.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "arg2", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "substring-before", "qname" : "fn:substring-before", "signature" : "($arg1 as xs:string?, $arg2 as xs:string?, $collation as xs:string) as xs:string external", "description" : "

    Returns the part of $arg1 that precedes the first occurrence of\n $arg2, taking collations into account.

    The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations.\n \t

    The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tcollations, and static base uri.\n \t

    If the value of $arg1 or $arg2 is the empty sequence, or\n contains only ignorable collation units, it is interpreted as the zero-length\n string.

    If the value of $arg2 is the zero-length string, then the function returns\n the zero-length string.

    If the value of $arg1 does not contain a string that is equal to the value\n of $arg2, then the function returns the zero-length string.

    The collation used by this function is determined according to the rules in .

    The function returns the substring of the value of $arg1 that precedes in\n the value of $arg1 the first occurrence of a sequence of collation units\n that provides a minimal match to the collation units of $arg2\n according to the collation that is used.

    Minimal match is defined in .

    A dynamic error may be raised if the\n specified collation does not support collation units.

    \n", "summary" : "

    Returns the part of $arg1 that precedes the first occurrence of\n $arg2 , taking collations into account.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "arg2", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "collation", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "substring", "qname" : "fn:substring", "signature" : "($sourceString as xs:string?, $start as xs:double) as xs:string external", "description" : "

    Returns the portion of the value of $sourceString beginning at the\n position indicated by the value of $start and continuing for the number of\n characters indicated by the value of\n $length.

    This function is deterministic, context-independent, and focus-independent.

    If the value of $sourceString is the empty sequence, the function returns\n the zero-length string.

    Otherwise, the function returns a string comprising those characters of $sourceString whose index position (counting\n from one) is greater than or equal to the value of $start (rounded to an\n integer), and (if $length is specified) less than the sum of\n $start and $length (both rounded to integers).

    The characters returned do not extend beyond $sourceString. If\n $start is zero or negative, only those characters in positions greater\n than zero are returned.

    More specifically, the three argument version of the function returns the characters in\n $sourceString whose position $p satisfies:

    \n fn:round($start) <= $p < fn:round($start) + fn:round($length)\n

    The two argument version of the function assumes that $length is infinite\n and thus returns the characters in\n $sourceString whose position $p satisfies:

    \n fn:round($start) <= $p\n

    In the above computations, the rules for op:numeric-less-than and\n op:numeric-greater-than apply.

    The first character of a string is located at position 1, not position 0.

    \n", "summary" : "

    Returns the portion of the value of $sourceString beginning at the\n position indicated by the value of $start and continuing for the number of\n characters indicated by the value of\n $length .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "sourceString", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "start", "type" : "xs:double", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "substring", "qname" : "fn:substring", "signature" : "($sourceString as xs:string?, $start as xs:double, $length as xs:double) as xs:string external", "description" : "

    Returns the portion of the value of $sourceString beginning at the\n position indicated by the value of $start and continuing for the number of\n characters indicated by the value of\n $length.

    This function is deterministic, context-independent, and focus-independent.

    If the value of $sourceString is the empty sequence, the function returns\n the zero-length string.

    Otherwise, the function returns a string comprising those characters of $sourceString whose index position (counting\n from one) is greater than or equal to the value of $start (rounded to an\n integer), and (if $length is specified) less than the sum of\n $start and $length (both rounded to integers).

    The characters returned do not extend beyond $sourceString. If\n $start is zero or negative, only those characters in positions greater\n than zero are returned.

    More specifically, the three argument version of the function returns the characters in\n $sourceString whose position $p satisfies:

    \n fn:round($start) <= $p < fn:round($start) + fn:round($length)\n

    The two argument version of the function assumes that $length is infinite\n and thus returns the characters in\n $sourceString whose position $p satisfies:

    \n fn:round($start) <= $p\n

    In the above computations, the rules for op:numeric-less-than and\n op:numeric-greater-than apply.

    The first character of a string is located at position 1, not position 0.

    \n", "summary" : "

    Returns the portion of the value of $sourceString beginning at the\n position indicated by the value of $start and continuing for the number of\n characters indicated by the value of\n $length .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "sourceString", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "start", "type" : "xs:double", "occurrence" : null, "description" : "" }, { "name" : "length", "type" : "xs:double", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sum", "qname" : "fn:sum", "signature" : "($arg as xs:anyAtomicType*) as xs:anyAtomicType external", "description" : "

    Returns a value obtained by adding together the values in\n $arg.

    This function is deterministic, context-independent, and focus-independent.

    Any values of type xs:untypedAtomic in $arg are cast to\n xs:double. The items in the resulting sequence may be reordered in an\n arbitrary order. The resulting sequence is referred to below as the converted\n sequence.

    If the converted sequence is empty, then the single-argument form of the function\n returns the xs:integer value 0; the two-argument form returns\n the value of the argument $zero.

    If the converted sequence contains the value NaN, NaN is\n returned.

    All items in $arg must be numeric or derived from a single base type. In\n addition, the type must support addition. Duration values must either all be\n xs:yearMonthDuration values or must all be\n xs:dayTimeDuration values. For numeric values, the numeric promotion\n rules defined in are used to promote all values to a single\n common type. The sum of a sequence of integers will therefore be an integer, while the\n sum of a numeric sequence that includes at least one xs:double will be an\n xs:double.

    The result of the function, using the second signature, is the result of the\n expression:

    \n if (fn:count($c) eq 0) then\n $zero\n else if (fn:count($c) eq 1) then\n $c[1]\n else\n $c[1] + fn:sum(subsequence($c, 2))

    where $c is the converted sequence.

    The result of the function, using the first signature, is the result of the expression:\n fn:sum($arg, 0).

    For detailed type semantics, see [Formal Semantics].

    A type error is raised if the input sequence contains\n items of incompatible types, as described above.

    \n", "summary" : "

    Returns a value obtained by adding together the values in\n $arg .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "sum", "qname" : "fn:sum", "signature" : "($arg as xs:anyAtomicType*, $zero as xs:anyAtomicType?) as xs:anyAtomicType? external", "description" : "

    Returns a value obtained by adding together the values in\n $arg.

    This function is deterministic, context-independent, and focus-independent.

    Any values of type xs:untypedAtomic in $arg are cast to\n xs:double. The items in the resulting sequence may be reordered in an\n arbitrary order. The resulting sequence is referred to below as the converted\n sequence.

    If the converted sequence is empty, then the single-argument form of the function\n returns the xs:integer value 0; the two-argument form returns\n the value of the argument $zero.

    If the converted sequence contains the value NaN, NaN is\n returned.

    All items in $arg must be numeric or derived from a single base type. In\n addition, the type must support addition. Duration values must either all be\n xs:yearMonthDuration values or must all be\n xs:dayTimeDuration values. For numeric values, the numeric promotion\n rules defined in are used to promote all values to a single\n common type. The sum of a sequence of integers will therefore be an integer, while the\n sum of a numeric sequence that includes at least one xs:double will be an\n xs:double.

    The result of the function, using the second signature, is the result of the\n expression:

    \n if (fn:count($c) eq 0) then\n $zero\n else if (fn:count($c) eq 1) then\n $c[1]\n else\n $c[1] + fn:sum(subsequence($c, 2))

    where $c is the converted sequence.

    The result of the function, using the first signature, is the result of the expression:\n fn:sum($arg, 0).

    For detailed type semantics, see [Formal Semantics].

    A type error is raised if the input sequence contains\n items of incompatible types, as described above.

    \n", "summary" : "

    Returns a value obtained by adding together the values in\n $arg .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "" }, { "name" : "zero", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:anyAtomicType?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "tail", "qname" : "fn:tail", "signature" : "($arg as item()*) as item()* external", "description" : "

    Returns all but the first item in a sequence.

    This function is deterministic, context-independent, and focus-independent.

    The function returns the value of the expression subsequence($arg, 2)

    If $arg is the empty sequence, or a sequence containing a single item, then\n the empty sequence is returned.

    \n", "summary" : "

    Returns all but the first item in a sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "timezone-from-date", "qname" : "fn:timezone-from-date", "signature" : "($arg as xs:date?) as xs:dayTimeDuration? external", "description" : "

    Returns the timezone component of an xs:date.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns the timezone component of $arg, if any. If\n $arg has a timezone component, then the result is an\n xs:dayTimeDuration that indicates deviation from UTC; its value may\n range from +14:00 to -14:00 hours, both inclusive. If $arg has no timezone\n component, the result is the empty sequence.

    The expression fn:timezone-from-date(xs:date(\"1999-05-31-05:00\")) returns xs:dayTimeDuration(\"-PT5H\").

    The expression fn:timezone-from-date(xs:date(\"2000-06-12Z\")) returns xs:dayTimeDuration(\"PT0S\").

    \n", "summary" : "

    Returns the timezone component of an xs:date .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:date", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:dayTimeDuration?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "timezone-from-dateTime", "qname" : "fn:timezone-from-dateTime", "signature" : "($arg as xs:dateTime?) as xs:dayTimeDuration? external", "description" : "

    Returns the timezone component of an xs:dateTime.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns the timezone component of $arg, if any. If\n $arg has a timezone component, then the result is an\n xs:dayTimeDuration that indicates deviation from UTC; its value may\n range from +14:00 to -14:00 hours, both inclusive. If $arg has no timezone\n component, the result is the empty sequence.

    The expression fn:timezone-from-dateTime(xs:dateTime(\"1999-05-31T13:20:00-05:00\")) returns xs:dayTimeDuration(\"-PT5H\").

    The expression fn:timezone-from-dateTime(xs:dateTime(\"2000-06-12T13:20:00Z\")) returns xs:dayTimeDuration(\"PT0S\").

    The expression fn:timezone-from-dateTime(xs:dateTime(\"2004-08-27T00:00:00\")) returns ().

    \n", "summary" : "

    Returns the timezone component of an xs:dateTime .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:dateTime", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:dayTimeDuration?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "timezone-from-time", "qname" : "fn:timezone-from-time", "signature" : "($arg as xs:time?) as xs:dayTimeDuration? external", "description" : "

    Returns the timezone component of an xs:time.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns the timezone component of $arg, if any. If\n $arg has a timezone component, then the result is an\n xs:dayTimeDuration that indicates deviation from UTC; its value may\n range from +14:00 to -14:00 hours, both inclusive. If $arg has no timezone\n component, the result is the empty sequence.

    The expression fn:timezone-from-time(xs:time(\"13:20:00-05:00\")) returns xs:dayTimeDuration(\"-PT5H\").

    The expression fn:timezone-from-time(xs:time(\"13:20:00\")) returns ().

    \n", "summary" : "

    Returns the timezone component of an xs:time .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:time", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:dayTimeDuration?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "tokenize", "qname" : "fn:tokenize", "signature" : "($input as xs:string?, $pattern as xs:string) as xs:string* external", "description" : "

    Returns a sequence of strings constructed by splitting the input wherever a\n separator is found; the separator is any substring that matches a given regular\n expression.

    This function is deterministic, context-independent, and focus-independent.

    The effect of calling the first version of this function (omitting the argument\n $flags) is the same as the effect of calling the second version with the\n $flags argument set to a zero-length string. Flags are defined in\n .

    The $flags argument is interpreted in the same way as for the\n fn:matches function.

    If $input is the empty sequence, or if $input is the\n zero-length string, the function returns the empty sequence.

    The function returns a sequence of strings formed by breaking the $input\n string into a sequence of strings, treating any substring that matches\n $pattern as a separator. The separators themselves are not returned.

    If a separator occurs at the start of the $input string, the result\n sequence will start with a zero-length string. Zero-length strings will also occur in\n the result sequence if a separator occurs at the end of the $input string,\n or if two adjacent substrings match the supplied $pattern.

    If two alternatives within the supplied $pattern both match at the same\n position in the $input string, then the match that is chosen is the first.\n For example:

    fn:tokenize(\"abracadabra\", \"(ab)|(a)\") returns (\"\", \"r\", \"c\", \"d\", \"r\", \"\")

    A dynamic error is raised if the value of\n $pattern is invalid according to the rules described in section .

    A dynamic error is raised if the value of\n $flags is invalid according to the rules described in section .

    A dynamic error is raised if the supplied\n $pattern matches a zero-length string, that is, if fn:matches(\"\",\n $pattern, $flags) returns true.

    \n", "summary" : "

    Returns a sequence of strings constructed by splitting the input wherever a\n separator is found; the separator is any substring that matches a given regular\n expression.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "tokenize", "qname" : "fn:tokenize", "signature" : "($input as xs:string?, $pattern as xs:string, $flags as xs:string) as xs:string* external", "description" : "

    Returns a sequence of strings constructed by splitting the input wherever a\n separator is found; the separator is any substring that matches a given regular\n expression.

    This function is deterministic, context-independent, and focus-independent.

    The effect of calling the first version of this function (omitting the argument\n $flags) is the same as the effect of calling the second version with the\n $flags argument set to a zero-length string. Flags are defined in\n .

    The $flags argument is interpreted in the same way as for the\n fn:matches function.

    If $input is the empty sequence, or if $input is the\n zero-length string, the function returns the empty sequence.

    The function returns a sequence of strings formed by breaking the $input\n string into a sequence of strings, treating any substring that matches\n $pattern as a separator. The separators themselves are not returned.

    If a separator occurs at the start of the $input string, the result\n sequence will start with a zero-length string. Zero-length strings will also occur in\n the result sequence if a separator occurs at the end of the $input string,\n or if two adjacent substrings match the supplied $pattern.

    If two alternatives within the supplied $pattern both match at the same\n position in the $input string, then the match that is chosen is the first.\n For example:

    fn:tokenize(\"abracadabra\", \"(ab)|(a)\") returns (\"\", \"r\", \"c\", \"d\", \"r\", \"\")

    A dynamic error is raised if the value of\n $pattern is invalid according to the rules described in section .

    A dynamic error is raised if the value of\n $flags is invalid according to the rules described in section .

    A dynamic error is raised if the supplied\n $pattern matches a zero-length string, that is, if fn:matches(\"\",\n $pattern, $flags) returns true.

    \n", "summary" : "

    Returns a sequence of strings constructed by splitting the input wherever a\n separator is found; the separator is any substring that matches a given regular\n expression.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "flags", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "trace", "qname" : "fn:trace", "signature" : "($value as item()*, $label as xs:string) as item()* external", "description" : "

    Provides an execution trace intended to be used in debugging queries.

    This function is deterministic, context-independent, and focus-independent.

    The function returns the value of $value, unchanged.

    In addition, the values of $value, converted to an xs:string,\n and $label\n may be directed to a trace data set. The destination of the trace\n output is . The format of the trace output is\n . The ordering of output from calls of the\n fn:trace function is .

    Consider a situation in which a user wants to investigate the actual value passed to\n a function. Assume that in a particular execution, $v is an\n xs:decimal with value 124.84. Writing fn:trace($v,\n 'the value of $v is:') will put the strings \"124.84\" and\n \"the value of $v is:\" in the trace data set in implementation\n dependent order.

    \n", "summary" : "

    Provides an execution trace intended to be used in debugging queries.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "label", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "translate", "qname" : "fn:translate", "signature" : "($arg as xs:string?, $mapString as xs:string, $transString as xs:string) as xs:string external", "description" : "

    Returns the value of $arg modified by replacing or removing\n individual characters.

    This function is deterministic, context-independent, and focus-independent.

    If the value of $arg is the empty sequence, the function returns the\n zero-length string.

    Otherwise, the function returns a result string constructed by processing each character in the value of $arg, in order,\n according to the following rules:

    If the character does not appear in the value of $mapString then it\n is added to the result string unchanged.

    If the character first appears in the value of $mapString at some\n position M, where the value of $transString is\n M or more characters in length, then the character at position\n M in $transString is added to the result string.

    If the character first appears in the value of $mapString at some\n position M, where the value of $transString is less than\n M characters in length, then the character is omitted from the\n result string.

    If $mapString is the zero-length string then the function returns\n $arg unchanged.

    If a character occurs more than once in $mapString, then the first\n occurrence determines the action taken.

    If $transString is longer than $mapString, the excess\n characters are ignored.

    \n", "summary" : "

    Returns the value of $arg modified by replacing or removing\n individual characters.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "mapString", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "transString", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "true", "qname" : "fn:true", "signature" : "() as xs:boolean external", "description" : "

    Returns the xs:boolean value true.

    This function is deterministic, context-independent, and focus-independent.

    The result is equivalent to xs:boolean(\"1\").

    The expression fn:true() returns xs:boolean(1).

    \n", "summary" : "

    Returns the xs:boolean value true .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "unordered", "qname" : "fn:unordered", "signature" : "($sourceSeq as item()*) as item()* external", "description" : "

    Returns the items of $sourceSeq in an order.

    This function is deterministic, context-independent, and focus-independent.

    The function returns the items of $sourceSeq in an order.

    Query optimizers may be able to do a better job if the order of the output sequence is\n not specified. For example, when retrieving prices from a purchase order, if an index\n exists on prices, it may be more efficient to return the prices in index order rather\n than in document order.

    \n", "summary" : "

    Returns the items of $sourceSeq in an order.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "sourceSeq", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "unparsed-text-available", "qname" : "fn:unparsed-text-available", "signature" : "($href as xs:string?) as xs:boolean external", "description" : "

    Because errors in evaluating the fn:unparsed-text function are\n non-recoverable, these two functions are provided to allow an application to determine\n whether a call with particular arguments would succeed.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The fn:unparsed-text-available function determines whether a call\n on the fn:unparsed-text function with identical arguments would\n return a string.

    If the first argument is an empty sequence, the function returns false. If the second\n argument is an empty sequence, the function behaves as if the second argument were\n omitted.

    In other cases, the function returns true if a call on\n fn:unparsed-text with the same arguments would succeed, and\n false if a call on fn:unparsed-text with the same arguments would\n fail with a non-recoverable dynamic error.

    The functions fn:unparsed-text and\n fn:unparsed-text-available have the same requirement for\n determinism as the functions\n fn:doc and fn:doc-available. This means that unless the\n user has explicitly stated a requirement for a reduced level of determinism, either of\n these functions if called twice with the same arguments during the course of a\n transformation must return the same results each time; moreover, the\n results of a call on fn:unparsed-text-available\n must be consistent with the results of a subsequent call on\n unparsed-text with the same arguments.

    This requires that the unparsed-text-available function should\n actually attempt to read the resource identified by the URI, and check that it is\n correctly encoded and contains no characters that are invalid in XML. Implementations\n may avoid the cost of repeating these checks for example by caching the validated\n contents of the resource, to anticipate a subsequent call on the\n unparsed-text\n or unparsed-text-lines\n function. Alternatively, implementations may be able to rewrite an expression\n such as if (unparsed-text-available(A)) then unparsed-text(A) else ... to\n generate a single call internally.

    \n", "summary" : "

    Because errors in evaluating the fn:unparsed-text function are\n non-recoverable, these two functions are provided to allow an application to determine\n whether a call with particular arguments would succeed.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "unparsed-text-available", "qname" : "fn:unparsed-text-available", "signature" : "($href as xs:string?) as xs:boolean external", "description" : "

    Because errors in evaluating the fn:unparsed-text function are\n non-recoverable, these two functions are provided to allow an application to determine\n whether a call with particular arguments would succeed.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The fn:unparsed-text-available function determines whether a call\n on the fn:unparsed-text function with identical arguments would\n return a string.

    If the first argument is an empty sequence, the function returns false. If the second\n argument is an empty sequence, the function behaves as if the second argument were\n omitted.

    In other cases, the function returns true if a call on\n fn:unparsed-text with the same arguments would succeed, and\n false if a call on fn:unparsed-text with the same arguments would\n fail with a non-recoverable dynamic error.

    The functions fn:unparsed-text and\n fn:unparsed-text-available have the same requirement for\n determinism as the functions\n fn:doc and fn:doc-available. This means that unless the\n user has explicitly stated a requirement for a reduced level of determinism, either of\n these functions if called twice with the same arguments during the course of a\n transformation must return the same results each time; moreover, the\n results of a call on fn:unparsed-text-available\n must be consistent with the results of a subsequent call on\n unparsed-text with the same arguments.

    This requires that the unparsed-text-available function should\n actually attempt to read the resource identified by the URI, and check that it is\n correctly encoded and contains no characters that are invalid in XML. Implementations\n may avoid the cost of repeating these checks for example by caching the validated\n contents of the resource, to anticipate a subsequent call on the\n unparsed-text\n or unparsed-text-lines\n function. Alternatively, implementations may be able to rewrite an expression\n such as if (unparsed-text-available(A)) then unparsed-text(A) else ... to\n generate a single call internally.

    \n", "summary" : "

    Because errors in evaluating the fn:unparsed-text function are\n non-recoverable, these two functions are provided to allow an application to determine\n whether a call with particular arguments would succeed.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "unparsed-text-available", "qname" : "fn:unparsed-text-available", "signature" : "($href as xs:string?, $encoding as xs:string) as xs:boolean external", "description" : "

    Because errors in evaluating the fn:unparsed-text function are\n non-recoverable, these two functions are provided to allow an application to determine\n whether a call with particular arguments would succeed.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The fn:unparsed-text-available function determines whether a call\n on the fn:unparsed-text function with identical arguments would\n return a string.

    If the first argument is an empty sequence, the function returns false. If the second\n argument is an empty sequence, the function behaves as if the second argument were\n omitted.

    In other cases, the function returns true if a call on\n fn:unparsed-text with the same arguments would succeed, and\n false if a call on fn:unparsed-text with the same arguments would\n fail with a non-recoverable dynamic error.

    The functions fn:unparsed-text and\n fn:unparsed-text-available have the same requirement for\n determinism as the functions\n fn:doc and fn:doc-available. This means that unless the\n user has explicitly stated a requirement for a reduced level of determinism, either of\n these functions if called twice with the same arguments during the course of a\n transformation must return the same results each time; moreover, the\n results of a call on fn:unparsed-text-available\n must be consistent with the results of a subsequent call on\n unparsed-text with the same arguments.

    This requires that the unparsed-text-available function should\n actually attempt to read the resource identified by the URI, and check that it is\n correctly encoded and contains no characters that are invalid in XML. Implementations\n may avoid the cost of repeating these checks for example by caching the validated\n contents of the resource, to anticipate a subsequent call on the\n unparsed-text\n or unparsed-text-lines\n function. Alternatively, implementations may be able to rewrite an expression\n such as if (unparsed-text-available(A)) then unparsed-text(A) else ... to\n generate a single call internally.

    \n", "summary" : "

    Because errors in evaluating the fn:unparsed-text function are\n non-recoverable, these two functions are provided to allow an application to determine\n whether a call with particular arguments would succeed.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "unparsed-text-available", "qname" : "fn:unparsed-text-available", "signature" : "($href as xs:string?, $encoding as xs:string) as xs:boolean external", "description" : "

    Because errors in evaluating the fn:unparsed-text function are\n non-recoverable, these two functions are provided to allow an application to determine\n whether a call with particular arguments would succeed.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The fn:unparsed-text-available function determines whether a call\n on the fn:unparsed-text function with identical arguments would\n return a string.

    If the first argument is an empty sequence, the function returns false. If the second\n argument is an empty sequence, the function behaves as if the second argument were\n omitted.

    In other cases, the function returns true if a call on\n fn:unparsed-text with the same arguments would succeed, and\n false if a call on fn:unparsed-text with the same arguments would\n fail with a non-recoverable dynamic error.

    The functions fn:unparsed-text and\n fn:unparsed-text-available have the same requirement for\n determinism as the functions\n fn:doc and fn:doc-available. This means that unless the\n user has explicitly stated a requirement for a reduced level of determinism, either of\n these functions if called twice with the same arguments during the course of a\n transformation must return the same results each time; moreover, the\n results of a call on fn:unparsed-text-available\n must be consistent with the results of a subsequent call on\n unparsed-text with the same arguments.

    This requires that the unparsed-text-available function should\n actually attempt to read the resource identified by the URI, and check that it is\n correctly encoded and contains no characters that are invalid in XML. Implementations\n may avoid the cost of repeating these checks for example by caching the validated\n contents of the resource, to anticipate a subsequent call on the\n unparsed-text\n or unparsed-text-lines\n function. Alternatively, implementations may be able to rewrite an expression\n such as if (unparsed-text-available(A)) then unparsed-text(A) else ... to\n generate a single call internally.

    \n", "summary" : "

    Because errors in evaluating the fn:unparsed-text function are\n non-recoverable, these two functions are provided to allow an application to determine\n whether a call with particular arguments would succeed.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "unparsed-text-lines", "qname" : "fn:unparsed-text-lines", "signature" : "($href as xs:string?) as xs:string* external", "description" : "

    The fn:unparsed-text-lines function reads an external resource (for\n example, a file) and returns its contents as a sequence of strings, one for each line of\n text in the string representation of the resource.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The unparsed-text-lines function reads an external resource (for example, a\n file) and returns its string representation as a sequence of strings, separated at newline\n boundaries.

    The result of the single-argument function is the same as the result of the expression\n fn:tokenize(fn:unparsed-text($href), '\\r\\n|\\r|\\n')[not(position()=last() and\n .='')]. The result of the two-argument function is the same as the result of\n the expression fn:tokenize(fn:unparsed-text($href, $encoding),\n '\\r\\n|\\r|\\n'))[not(position()=last() and .='')].

    The result is a thus a sequence of strings containing the text of the resource retrieved\n using the URI, each string representing one line of text. Lines are separated by one of\n the sequences x0A, x0D, or x0Dx0A. The characters representing the newline are not\n included in the returned strings. If there are two adjacent newline sequences, a\n zero-length string will be returned to represent the empty line; but if the external\n resource ends with a newline sequence, no zero-length string will be returned as the\n last item in the result.

    Error conditions are the same as for the fn:unparsed-text function.

    \n", "summary" : "

    The fn:unparsed-text-lines function reads an external resource (for\n example, a file) and returns its contents as a sequence of strings, one for each line of\n text in the string representation of the resource.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "unparsed-text-lines", "qname" : "fn:unparsed-text-lines", "signature" : "($href as xs:string?, $encoding as xs:string) as xs:string* external", "description" : "

    The fn:unparsed-text-lines function reads an external resource (for\n example, a file) and returns its contents as a sequence of strings, one for each line of\n text in the string representation of the resource.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The unparsed-text-lines function reads an external resource (for example, a\n file) and returns its string representation as a sequence of strings, separated at newline\n boundaries.

    The result of the single-argument function is the same as the result of the expression\n fn:tokenize(fn:unparsed-text($href), '\\r\\n|\\r|\\n')[not(position()=last() and\n .='')]. The result of the two-argument function is the same as the result of\n the expression fn:tokenize(fn:unparsed-text($href, $encoding),\n '\\r\\n|\\r|\\n'))[not(position()=last() and .='')].

    The result is a thus a sequence of strings containing the text of the resource retrieved\n using the URI, each string representing one line of text. Lines are separated by one of\n the sequences x0A, x0D, or x0Dx0A. The characters representing the newline are not\n included in the returned strings. If there are two adjacent newline sequences, a\n zero-length string will be returned to represent the empty line; but if the external\n resource ends with a newline sequence, no zero-length string will be returned as the\n last item in the result.

    Error conditions are the same as for the fn:unparsed-text function.

    \n", "summary" : "

    The fn:unparsed-text-lines function reads an external resource (for\n example, a file) and returns its contents as a sequence of strings, one for each line of\n text in the string representation of the resource.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "unparsed-text-lines", "qname" : "fn:unparsed-text-lines", "signature" : "($href as xs:string?, $encoding as xs:string) as xs:string* external", "description" : "

    The fn:unparsed-text-lines function reads an external resource (for\n example, a file) and returns its contents as a sequence of strings, one for each line of\n text in the string representation of the resource.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The unparsed-text-lines function reads an external resource (for example, a\n file) and returns its string representation as a sequence of strings, separated at newline\n boundaries.

    The result of the single-argument function is the same as the result of the expression\n fn:tokenize(fn:unparsed-text($href), '\\r\\n|\\r|\\n')[not(position()=last() and\n .='')]. The result of the two-argument function is the same as the result of\n the expression fn:tokenize(fn:unparsed-text($href, $encoding),\n '\\r\\n|\\r|\\n'))[not(position()=last() and .='')].

    The result is a thus a sequence of strings containing the text of the resource retrieved\n using the URI, each string representing one line of text. Lines are separated by one of\n the sequences x0A, x0D, or x0Dx0A. The characters representing the newline are not\n included in the returned strings. If there are two adjacent newline sequences, a\n zero-length string will be returned to represent the empty line; but if the external\n resource ends with a newline sequence, no zero-length string will be returned as the\n last item in the result.

    Error conditions are the same as for the fn:unparsed-text function.

    \n", "summary" : "

    The fn:unparsed-text-lines function reads an external resource (for\n example, a file) and returns its contents as a sequence of strings, one for each line of\n text in the string representation of the resource.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "unparsed-text", "qname" : "fn:unparsed-text", "signature" : "($href as xs:string?) as xs:string? external", "description" : "

    The fn:unparsed-text function reads an external resource (for example, a\n file) and returns a string representation of the resource.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The $href argument must be a string in the form of a URI\n reference, which must contain no fragment identifier, and\n must identify a resource\n for which a string representation is available. If the URI is a\n relative URI reference, then it is resolved relative to the\n Static Base URI property from the static context.

    The mapping of URIs to the string representation of a resource is the mapping defined\n in the available text resources\n component of the dynamic context.

    If the value of the $href argument is an empty sequence, the function\n returns an empty sequence.

    The $encoding argument, if present, is the name of an encoding. The values\n for this attribute follow the same rules as for the encoding attribute in\n an XML declaration. The only values which every implementation is required to recognize are\n utf-8 and utf-16.

    The encoding of the external resource is determined as follows:

    external encoding information is used if available, otherwise

    if the media type of the resource is text/xml or\n application/xml (see ), or if it matches\n the conventions text/*+xml or application/*+xml (see\n and/or its successors), then the encoding is recognized\n as specified in , otherwise

    the value of the $encoding argument is used if present, otherwise

    the processor may use implementation-defined heuristics to determine the likely encoding,\n otherwise

    UTF-8 is assumed.

    The result of the function is a string containing the\n string representation of the resource retrieved\n using the URI.

    A dynamic error is raised if $href\n contains a fragment identifier, or if it cannot be used to retrieve the\n string representation of a resource.

    A dynamic error is raised if the value\n of the $encoding argument is not a valid encoding name, if the processor does not support the specified encoding,\n if the string representation of the retrieved\n resource contains octets that cannot be decoded into Unicode characters using the specified encoding, or if the resulting characters\n are not permitted XML characters.

    A dynamic error is raised if\n $encoding is absent and the processor cannot infer the encoding using external information and the\n encoding is not UTF-8.

    \n", "summary" : "

    The fn:unparsed-text function reads an external resource (for example, a\n file) and returns a string representation of the resource .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "unparsed-text", "qname" : "fn:unparsed-text", "signature" : "($href as xs:string?) as xs:string? external", "description" : "

    The fn:unparsed-text function reads an external resource (for example, a\n file) and returns a string representation of the resource.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The $href argument must be a string in the form of a URI\n reference, which must contain no fragment identifier, and\n must identify a resource\n for which a string representation is available. If the URI is a\n relative URI reference, then it is resolved relative to the\n Static Base URI property from the static context.

    The mapping of URIs to the string representation of a resource is the mapping defined\n in the available text resources\n component of the dynamic context.

    If the value of the $href argument is an empty sequence, the function\n returns an empty sequence.

    The $encoding argument, if present, is the name of an encoding. The values\n for this attribute follow the same rules as for the encoding attribute in\n an XML declaration. The only values which every implementation is required to recognize are\n utf-8 and utf-16.

    The encoding of the external resource is determined as follows:

    external encoding information is used if available, otherwise

    if the media type of the resource is text/xml or\n application/xml (see ), or if it matches\n the conventions text/*+xml or application/*+xml (see\n and/or its successors), then the encoding is recognized\n as specified in , otherwise

    the value of the $encoding argument is used if present, otherwise

    the processor may use implementation-defined heuristics to determine the likely encoding,\n otherwise

    UTF-8 is assumed.

    The result of the function is a string containing the\n string representation of the resource retrieved\n using the URI.

    A dynamic error is raised if $href\n contains a fragment identifier, or if it cannot be used to retrieve the\n string representation of a resource.

    A dynamic error is raised if the value\n of the $encoding argument is not a valid encoding name, if the processor does not support the specified encoding,\n if the string representation of the retrieved\n resource contains octets that cannot be decoded into Unicode characters using the specified encoding, or if the resulting characters\n are not permitted XML characters.

    A dynamic error is raised if\n $encoding is absent and the processor cannot infer the encoding using external information and the\n encoding is not UTF-8.

    \n", "summary" : "

    The fn:unparsed-text function reads an external resource (for example, a\n file) and returns a string representation of the resource .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "unparsed-text", "qname" : "fn:unparsed-text", "signature" : "($href as xs:string?, $encoding as xs:string) as xs:string? external", "description" : "

    The fn:unparsed-text function reads an external resource (for example, a\n file) and returns a string representation of the resource.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The $href argument must be a string in the form of a URI\n reference, which must contain no fragment identifier, and\n must identify a resource\n for which a string representation is available. If the URI is a\n relative URI reference, then it is resolved relative to the\n Static Base URI property from the static context.

    The mapping of URIs to the string representation of a resource is the mapping defined\n in the available text resources\n component of the dynamic context.

    If the value of the $href argument is an empty sequence, the function\n returns an empty sequence.

    The $encoding argument, if present, is the name of an encoding. The values\n for this attribute follow the same rules as for the encoding attribute in\n an XML declaration. The only values which every implementation is required to recognize are\n utf-8 and utf-16.

    The encoding of the external resource is determined as follows:

    external encoding information is used if available, otherwise

    if the media type of the resource is text/xml or\n application/xml (see ), or if it matches\n the conventions text/*+xml or application/*+xml (see\n and/or its successors), then the encoding is recognized\n as specified in , otherwise

    the value of the $encoding argument is used if present, otherwise

    the processor may use implementation-defined heuristics to determine the likely encoding,\n otherwise

    UTF-8 is assumed.

    The result of the function is a string containing the\n string representation of the resource retrieved\n using the URI.

    A dynamic error is raised if $href\n contains a fragment identifier, or if it cannot be used to retrieve the\n string representation of a resource.

    A dynamic error is raised if the value\n of the $encoding argument is not a valid encoding name, if the processor does not support the specified encoding,\n if the string representation of the retrieved\n resource contains octets that cannot be decoded into Unicode characters using the specified encoding, or if the resulting characters\n are not permitted XML characters.

    A dynamic error is raised if\n $encoding is absent and the processor cannot infer the encoding using external information and the\n encoding is not UTF-8.

    \n", "summary" : "

    The fn:unparsed-text function reads an external resource (for example, a\n file) and returns a string representation of the resource .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "unparsed-text", "qname" : "fn:unparsed-text", "signature" : "($href as xs:string?, $encoding as xs:string) as xs:string? external", "description" : "

    The fn:unparsed-text function reads an external resource (for example, a\n file) and returns a string representation of the resource.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tstatic base uri.\n \t

    The $href argument must be a string in the form of a URI\n reference, which must contain no fragment identifier, and\n must identify a resource\n for which a string representation is available. If the URI is a\n relative URI reference, then it is resolved relative to the\n Static Base URI property from the static context.

    The mapping of URIs to the string representation of a resource is the mapping defined\n in the available text resources\n component of the dynamic context.

    If the value of the $href argument is an empty sequence, the function\n returns an empty sequence.

    The $encoding argument, if present, is the name of an encoding. The values\n for this attribute follow the same rules as for the encoding attribute in\n an XML declaration. The only values which every implementation is required to recognize are\n utf-8 and utf-16.

    The encoding of the external resource is determined as follows:

    external encoding information is used if available, otherwise

    if the media type of the resource is text/xml or\n application/xml (see ), or if it matches\n the conventions text/*+xml or application/*+xml (see\n and/or its successors), then the encoding is recognized\n as specified in , otherwise

    the value of the $encoding argument is used if present, otherwise

    the processor may use implementation-defined heuristics to determine the likely encoding,\n otherwise

    UTF-8 is assumed.

    The result of the function is a string containing the\n string representation of the resource retrieved\n using the URI.

    A dynamic error is raised if $href\n contains a fragment identifier, or if it cannot be used to retrieve the\n string representation of a resource.

    A dynamic error is raised if the value\n of the $encoding argument is not a valid encoding name, if the processor does not support the specified encoding,\n if the string representation of the retrieved\n resource contains octets that cannot be decoded into Unicode characters using the specified encoding, or if the resulting characters\n are not permitted XML characters.

    A dynamic error is raised if\n $encoding is absent and the processor cannot infer the encoding using external information and the\n encoding is not UTF-8.

    \n", "summary" : "

    The fn:unparsed-text function reads an external resource (for example, a\n file) and returns a string representation of the resource .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "upper-case", "qname" : "fn:upper-case", "signature" : "($arg as xs:string?) as xs:string external", "description" : "

    Converts a string to upper case.

    This function is deterministic, context-independent, and focus-independent.

    If the value of $arg is the empty sequence, the zero-length string is\n returned.

    Otherwise, the function returns the value of $arg after translating every\n character to its upper-case correspondent as\n defined in the appropriate case mappings section in the Unicode standard . For versions of Unicode beginning with the 2.1.8 update, only\n locale-insensitive case mappings should be applied. Beginning with version 3.2.0 (and\n likely future versions) of Unicode, precise mappings are described in default case\n operations, which are full case mappings in the absence of tailoring for particular\n languages and environments. Every lower-case character that does not have an upper-case\n correspondent, as well as every upper-case character, is included in the returned value\n in its original form.

    Case mappings may change the length of a string. In general, the\n fn:upper-case and fn:lower-case functions are not inverses\n of each other: fn:lower-case(fn:upper-case($arg)) is not guaranteed to\n return $arg, nor is fn:upper-case(fn:lower-case($arg)). The\n Latin small letter dotless i (as used in Turkish) is perhaps the most prominent\n lower-case letter which will not round-trip. The Latin capital letter i with dot above\n is the most prominent upper-case letter which will not round trip; there are others,\n such as Latin capital letter Sharp S (#1E9E) which is introduced in Unicode 5.1.

    These functions may not always be linguistically appropriate (e.g. Turkish i without\n dot) or appropriate for the application (e.g. titlecase). In cases such as Turkish, a\n simple translation should be used first.

    Because the function is not sensitive to locale, results will not always match user\n expectations. In Quebec, for example, the standard uppercase equivalent of \"è\" is \"È\",\n while in metropolitan France it is more commonly \"E\"; only one of these is supported by\n the functions as defined.

    Many characters of class Ll lack uppercase equivalents in the Unicode case mapping\n tables; many characters of class Lu lack lowercase equivalents.

    \n", "summary" : "

    Converts a string to upper case.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "uri-collection", "qname" : "fn:uri-collection", "signature" : "() as xs:anyURI* external", "description" : "

    Returns a sequence of xs:anyURI values representing the URIs in a resource collection.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tavailable resource collections, and static base uri.\n \t

    The zero-argument form of the function returns the URIs in the Default resource collection\n described in .

    If the value of $arg is a relative xs:anyURI, it is resolved\n against the value of the base-URI property from the static context.

    If $arg is the empty sequence, the function behaves as if it had been\n called without an argument. See above.

    The single-argument form of the function returns the sequence of URIs corresponding to the\n supplied URI in the Available resource collections described in\n .

    A dynamic error is raised if no URI is supplied (that is, if the\n the function is called with no arguments, or with a single argument that evaluates to an empty sequence), and the\n value of the default resource collection is absent.

    A dynamic error is raised \n if available resource collections provides no mapping for the absolutized URI.

    A dynamic error is raised if $arg is not a\n valid xs:anyURI.

    \n", "summary" : "

    Returns a sequence of xs:anyURI values representing the URIs in a resource collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:anyURI*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "uri-collection", "qname" : "fn:uri-collection", "signature" : "() as xs:anyURI* external", "description" : "

    Returns a sequence of xs:anyURI values representing the URIs in a resource collection.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tavailable resource collections, and static base uri.\n \t

    The zero-argument form of the function returns the URIs in the Default resource collection\n described in .

    If the value of $arg is a relative xs:anyURI, it is resolved\n against the value of the base-URI property from the static context.

    If $arg is the empty sequence, the function behaves as if it had been\n called without an argument. See above.

    The single-argument form of the function returns the sequence of URIs corresponding to the\n supplied URI in the Available resource collections described in\n .

    A dynamic error is raised if no URI is supplied (that is, if the\n the function is called with no arguments, or with a single argument that evaluates to an empty sequence), and the\n value of the default resource collection is absent.

    A dynamic error is raised \n if available resource collections provides no mapping for the absolutized URI.

    A dynamic error is raised if $arg is not a\n valid xs:anyURI.

    \n", "summary" : "

    Returns a sequence of xs:anyURI values representing the URIs in a resource collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:anyURI*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "uri-collection", "qname" : "fn:uri-collection", "signature" : "($arg as xs:string?) as xs:anyURI* external", "description" : "

    Returns a sequence of xs:anyURI values representing the URIs in a resource collection.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tavailable resource collections, and static base uri.\n \t

    The zero-argument form of the function returns the URIs in the Default resource collection\n described in .

    If the value of $arg is a relative xs:anyURI, it is resolved\n against the value of the base-URI property from the static context.

    If $arg is the empty sequence, the function behaves as if it had been\n called without an argument. See above.

    The single-argument form of the function returns the sequence of URIs corresponding to the\n supplied URI in the Available resource collections described in\n .

    A dynamic error is raised if no URI is supplied (that is, if the\n the function is called with no arguments, or with a single argument that evaluates to an empty sequence), and the\n value of the default resource collection is absent.

    A dynamic error is raised \n if available resource collections provides no mapping for the absolutized URI.

    A dynamic error is raised if $arg is not a\n valid xs:anyURI.

    \n", "summary" : "

    Returns a sequence of xs:anyURI values representing the URIs in a resource collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:anyURI*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "uri-collection", "qname" : "fn:uri-collection", "signature" : "($arg as xs:string?) as xs:anyURI* external", "description" : "

    Returns a sequence of xs:anyURI values representing the URIs in a resource collection.

    This function is deterministic, context-dependent, and focus-independent. It depends on\n \t\tavailable resource collections, and static base uri.\n \t

    The zero-argument form of the function returns the URIs in the Default resource collection\n described in .

    If the value of $arg is a relative xs:anyURI, it is resolved\n against the value of the base-URI property from the static context.

    If $arg is the empty sequence, the function behaves as if it had been\n called without an argument. See above.

    The single-argument form of the function returns the sequence of URIs corresponding to the\n supplied URI in the Available resource collections described in\n .

    A dynamic error is raised if no URI is supplied (that is, if the\n the function is called with no arguments, or with a single argument that evaluates to an empty sequence), and the\n value of the default resource collection is absent.

    A dynamic error is raised \n if available resource collections provides no mapping for the absolutized URI.

    A dynamic error is raised if $arg is not a\n valid xs:anyURI.

    \n", "summary" : "

    Returns a sequence of xs:anyURI values representing the URIs in a resource collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:anyURI*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "year-from-date", "qname" : "fn:year-from-date", "signature" : "($arg as xs:date?) as xs:integer? external", "description" : "

    Returns the year component of an xs:date.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:integer representing the year in the\n local value of $arg. The value may be negative.

    The expression fn:year-from-date(xs:date(\"1999-05-31\")) returns 1999.

    The expression fn:year-from-date(xs:date(\"2000-01-01+05:00\")) returns 2000.

    \n", "summary" : "

    Returns the year component of an xs:date .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:date", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "years-from-duration", "qname" : "fn:years-from-duration", "signature" : "($arg as xs:duration?) as xs:integer? external", "description" : "

    Returns the number of years in a duration.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise, the function returns an xs:integer representing the years\n component in the value of $arg. The result is obtained by casting\n $arg to an xs:yearMonthDuration (see ) and then computing the years component as described in\n .

    If $arg is a negative duration then the result will be negative..

    If $arg is an xs:dayTimeDuration the function returns 0.

    The expression fn:years-from-duration(xs:yearMonthDuration(\"P20Y15M\")) returns 21.

    The expression fn:years-from-duration(xs:yearMonthDuration(\"-P15M\")) returns -1.

    The expression fn:years-from-duration(xs:dayTimeDuration(\"-P2DT15H\")) returns 0.

    \n", "summary" : "

    Returns the number of years in a duration.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:duration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "zero-or-one", "qname" : "fn:zero-or-one", "signature" : "($arg as item()*) as item()? external", "description" : "

    Returns $arg if it contains zero or one items. Otherwise, raises\n an error.

    This function is deterministic, context-independent, and focus-independent.

    Except in error cases, the function returns $arg unchanged.

    For detailed type semantics, see [Formal Semantics].

    A dynamic error is raised if $arg contains more\n than one item.

    \n", "summary" : "

    Returns $arg if it contains zero or one items.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "item()?", "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/csv" : { "ns" : "http://zorba.io/modules/csv", "description" : " Function library providing converters from CSV/TXT to XML and back.\n The functions are optimized to work with large amounts of data, in a streaming way.\n", "sees" : [ ], "authors" : [ "Daniel Turcanu" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/csv", "prefix" : "csv" }, { "uri" : "http://zorba.io/modules/csv-options", "prefix" : "csv-options" }, { "uri" : "http://zorba.io/modules/schema", "prefix" : "schemaOptions" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "parse", "qname" : "csv:parse", "signature" : "($csv as xs:string, $options as element(csv-options:options)?) as element(*)*", "description" : " Parse a CSV or fixed size text and convert to XML.
    \n By default each line is converted to a <row> element, and each field to a <column> element inside <row>.
    \n The format of the param $options is:
    \n
    \n    <csv-options:options>\n        <csv  [separator=\"default comma ,\"] ?\n          [quote-char=\"default double quotes &quote;\"]?\n          [quote-escape=\"default double double quotes &quote;&quote;\"]? />\n        or\n        <column-widths>\n          <column-width>[column fixed width, unsigned int]<column-width>*\n        </column-widths>\n        or\n        <column-positions>\n          <column-position>[column position on line, unsigned int]<column-position>*\n        </column-positions>\n        <first-row-is-header [line=\"first_line[-last_line]?\"]?/>?\n        <start-from-row line=\"first_line[-last_line]?\"/>?\n        <add-last-void-columns/>?\n        <xml-nodes>\n          [<row-name>\n            [<column-name/>]?\n          </row-name>]?\n        </xml-nodes>?\n    </csv-options:options>\n  
    \n All the parameters are optional and can appear in any order.
    \n All the parameters are case sensitive. The namespace used is \"http://zorba.io/modules/csv-options\".
    \n All strings must have UTF-8 encoding.
    \n Parameters csv, column-widths, column-positions are mutually exclusive. If none is specified,\n the input string is assumed to be csv.
    \n Description of parameters:\n
    \n
    csv
    \n
    Specifies the parameters for parsing a csv string.
    \n
    \n
    separator
    \n
    The character or group of characters used to separating fields in a row.\n If it is not specified, it defaults to comma ','.\n
    \n
    quote-char
    \n
    The character or group of characters used for quoting the fields that may contain special characters,\n like separator, new line or this quote char. The default value is double quote \".
    \n
    \n
    quote-escape
    \n
    The group of characters used for escaping the quote char inside a field. The whole quote escape group\n is translated to a quote char during parsing. The default value is double double quotes \"\".
    \n
    \n
    \n
    \n
    \n
    column-widths
    \n
    Specifies the column widths for fixed size text. It contains multiple column-width child elements\n specifying the fixed width of each column, from left to right.
    \n If the line has more fields than specified, they are ignored.\n
    \n
    column-positions
    \n
    This is an alternative to column-widths, and specifies instead the starting position of each column.\n Column positions are 1 based, and are specified in order from left to right.\n The last column is read until end of line. The first column position can be greater than 1, if you want\n to parse only a part of the input text.\n
    \n
    first-row-is-header
    \n
    The presence of this element indicates that the first row is to be treated as the name of the columns.\n If it is not present, then each field is enclosed in a <column> element,\n or how it is specified in <xml-nodes> parameter.
    \n If the first row is the header, then each field is enclosed in an element with the corresponding name from the header.
    \n For example, the csv:\n
    \n        ID,Name,Occupation\n        1,John,student\n        
    \n is parsed into:\n
    \n        <row>\n        <ID>1</ID>\n        <Name>John</Name>\n        <Occupation>student</Occupation>\n        </row>\n        
    \n If the header names contain characters that cannot be used in a QName, they are replaced with underscore '_'.
    \n The namespace for the header QNames is taken from the column name specified in xml-nodes parameter, or from\n the row name, or if that doesn't exist either then empty namespace is used.
    \n If the header is not the first line in the input string, the starting line can be specified in the line attribute.
    \n If a column does not have a name, a new name is constructed in the form columnN where N is the position of the column,\n starting from 1.
    \n Subheaders
    \n If the header consists of more than one line, this can be specified in the line attribute in the form\n \"first_line - last_line\". Having more lines as the header translates into a hierarchy of elements in the xml.
    \n For example, the csv:\n
    \n        ID,Name,,Occupation\n        ,First Name,Last Name,\n        1,John,Howard,student\n        
    \n is parsed into:\n
    \n        <row>\n        <ID>1</ID>\n        <Name>\n          <First_Name>John</First_Name>\n          <Last_Name>Howard</Last_Name>\n        </Name>\n        <Occupation>student</Occupation>\n        </row>\n        
    \n This element can have an attribute \"accept-all-lines\" with values \"false\" or \"true\" (default \"false\").\n When set to true it tells the parser to not report lines that do not have the same number of items as\n the header. If set to false, the parser will raise a csv:WrongInput error for these lines.
    \n
    \n
    start-from-row
    \n
    If the data does not start from line 1 or immediately after the header,\n you can specify the starting line in the line attribute.
    \n Also you can use this attribute in the form \"first_line - last_line\" to specify also the last line\n if you don't want the whole csv to be parsed.\n
    \n
    add-last-void-columns
    \n
    In the case when using headers and some data lines are shorter than the header, by default the excess columns are ignored\n for those lines. You can set the add-last-void-columns parameter to make all the columns appear in xml even if they are void.\n
    \n
    xml-nodes
    \n
    With this parameter you can specify the names for the row element and for the column element if there is no header.
    \n The first element child of this element specifies the desired QName of the row element in the output xml.\n The name of this element will be used as the name of the row element.
    \n The element child of this row element is the column element, and its name will be used as the name of the column elements\n that enclose the fields in the output xml if there is no header.
    \n If the csv has a header, only the namespace is used from the column element.
    \n For example, with parameter:\n
    \n        <xml-nodes>\n        <r>\n          <c/>\n        </r>\n        </xml-nodes>\n        
    \n the output for each line will look like:\n
    \n        <r>\n          <c>field1</c>\n          <c>field2</c>\n          .......\n        </r>\n        
    \n
    \n
    \n", "summary" : "

    Parse a CSV or fixed size text and convert to XML.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "csv", "type" : "xs:string", "occurrence" : null, "description" : "
    the string containing the csv or fixed size text.
    " }, { "name" : "options", "type" : "element(csv-options:options)", "occurrence" : "?", "description" : "
    this parameter is validated against \"http://zorba.io/modules/csv-options\" schema. If this parameter is not specified, the row name is by default \"row\" and the column name is by default \"column\".
    " } ], "returns" : { "type" : "element(*)*", "description" : "a sequence of row elements, one for each line in csv" }, "errors" : [ "csv:CSV001 if the input string is streamable string and cannot be rewinded", "csv:WrongInput if the input string has lines with variable number of items, and the csv has headers and the options do not specify the ignore-foreign-input attribute", "err:XQDY0027 if $options can not be validated against the csv-options schema", "err:XQDY0084 if the options parameter doesn't have the name \"csv-options:options\"." ] }, { "isDocumented" : true, "arity" : 2, "name" : "serialize", "qname" : "csv:serialize", "signature" : "($xml as element(*)*, $options as element(csv-options:options)?) as xs:string", "description" : " Convert XML into CSV or fixed size text.\n Note: if you want to serialize out the result, make sure that the serializer method is set to \"text\".\n For example, in zorba command line, you have to set the param --serialize-text.\n When using the
    file:write(...)
    function, you have to set the\n method serialization parameter to \"text\":\n
    \n <output:serialization-parameters<\n   <output:method value=\"text\"/<\n </output:serialization-parameters<\n 
    \n The
    $options
    parameter must have the following format:\n
    \n    <csv-options:options>
    \n <csv [separator=\"default comma ,\"] ?
    \n [quote-char=\"default double quotes &quote;\"]?
    \n [quote-escape=\"default double double quotes &quote;&quote;\"]? />
    \n
    \n or
    \n <column-widths [align=\"left|right\"]?>
    \n <column-width [align=\"left|right\"]?>[column fixed width, unsigned int]<column-width>*
    \n </column-widths>
    \n
    \n or
    \n <column-positions [align=\"left|right\"]?>
    \n <column-position [align=\"left|right\"]?>[column position on line, unsigned int]<column-position>*
    \n </column-positions>
    \n
    \n <first-row-is-header/>?
    \n </csv-options:options>\n
    \n All the parameters are optional and can appear in any order.
    \n All the parameters are case sensitive. The namespace used is \"http://zorba.io/modules/csv-options\".
    \n All strings must have UTF-8 encoding.
    \n Parameters csv, column-widths, column-positions are mutually exclusive.\n If none is specified, the xml is converted to csv.\n Description of parameters:\n
    \n
    csv
    \n
    Specifies the parameters for converting to csv.
    \n
    \n
    separator
    \n
    The character or group of characters used to separating fields in a row.\n If it is not specified, it defaults to comma ','.\n
    \n
    quote-char
    \n
    The character or group of characters used for quoting the fields that may contain special characters,\n like separator, new line or this quote char. The default value is double quote \".
    \n
    \n
    quote-escape
    \n
    The group of characters used for escaping the quote char inside a field. The whole quote escape group\n is translated to a quote char during parsing. The default value is double double quotes \"\".
    \n
    \n
    \n
    \n
    \n
    column-widths
    \n
    Specifies the column widths for fixed size text. It contains multiple column-width child elements\n specifying the fixed width of each column, from left to right.
    \n With the attribute align you can specify how to align fields that are smaller than the column width.\n The default alignment is left.
    \n
    \n
    column-positions
    \n
    This is an alternative to column-widths, and specifies instead the starting position of each column.\n Column positions are 1 based, and are specified in order from left to right.\n The last column has a variable length.
    \n With the attribute align you can specify how to align fields that are smaller than the column width.\n The default alignment is left. The last column does not need alignment.
    \n
    \n
    first-row-is-header
    \n
    The presence of this element indicates that the first row will contain the header, that is, the names of\n the column elements. Only the column names from the first row element are taken into account.
    \n For example, the row xml:
    \n <row>
    \n <ID>1</ID>
    \n <Name>John</Name>
    \n <Occupation>student</Occupation>
    \n </row>

    \n
    \n is converted to
    \n ID,Name,Occupation
    \n 1,John,student

    \n
    \n The header names are the localnames of the column elements, and the namespace is ignored.
    \n Subheaders
    \n If the row-column hierarchy is more complex, then subheaders are also generated on subsequent lines.\n The number of subheaders depends on the depth of the column hierarchy.
    \n When generating the subheaders, the non-whitespace text nodes are also taken into account,\n and a separate column is generated for them too.
    \n For example, the xml row element:
    \n <row>
    \n <ID>1</ID>
    \n <Name>
    \n Mr.
    \n <First_Name>John</First_Name>
    \n <Last_Name>Howard</Last_Name>
    \n </Name>
    \n <Occupation>student</Occupation>
    \n </row>

    \n is converted to
    \n ID,Name,,Occupation
    \n ,,First Name,Last Name,
    \n 1,Mr.,John,Howard,student

    \n
    \n If first-row-is-header is not specified and the columns have a deeper hierarchy,\n only the first layer of columns is processed, and the fields are the string values of each column.
    \n This element can have an attribute \"ignore-foreign-input\" with values \"false\" or \"true\" (default \"false\").\n When set to true it tells the serializer to ignore elements that to not match the header names.\n If set to false, the serializer will raise a csv:ForeignInput error for these elements.
    \n
    \n
    \n", "summary" : "

    Convert XML into CSV or fixed size text.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "xml", "type" : "element(*)", "occurrence" : "*", "description" : "
    a sequence of elements, each element representing a row. The name of each row element is ignored. The childs of each row are the column fields.
    " }, { "name" : "options", "type" : "element(csv-options:options)", "occurrence" : "?", "description" : "
    The options parameter. See the function description for details. This parameter is validated against \"http://zorba.io/modules/csv-options\" schema.
    " } ], "returns" : { "type" : "xs:string", "description" : "the csv or fixed size text as string containing all the lines" }, "errors" : [ "csv:CSV003 if the serialize output is streamable string and cannot be reset", "csv:ForeignInput if there are input elements in subsequent rows that do not match the headers, and the options specify first-row-is-header and do not specify the ignore-foreign-input attribute", "err:XQDY0027 if $options can not be validated against csv-options schema", "err:XQDY0084 if the options parameter doesn't have the name \"csv-options:options\"." ] } ], "variables" : [ ] }, "http://zorba.io/modules/reference" : { "ns" : "http://zorba.io/modules/reference", "description" : " The module provides functions to compute an immutable and opaque reference\n for nodes, objects, or arrays and to retrieve such items given their\n identifier, respectively.\n The identifiers are immutable, i.e. a identifier does not change\n during the items lifetime and cannot be reused for another item after the\n original item gets deleted.\n Identifiers are unique, in that, two different items will never have the same\n identifier. A item, at any time during its lifetime, can be retrieved by its\n identifier.\n", "sees" : [ ], "authors" : [ "Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/reference", "prefix" : "ref" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "dereference", "qname" : "ref:dereference", "signature" : "($arg as xs:string) as item()? external", "description" : "

    Returns the node, object, or array identified by the given reference.

    \n

    The function returns the empty sequence if the item\n that is referenced does not exist.

    \n", "summary" : "

    Returns the node, object, or array identified by the given reference.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : null, "description" : "
    the URI of the item to retrieve.
    " } ], "returns" : { "type" : "item()?", "description" : "the item identified by the URI passed as parameter or the empty-sequence if no item with that URI is found." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "reference", "qname" : "ref:reference", "signature" : "($arg as item()) as xs:string external", "description" : "

    Returns an immutable and opaque reference (with type xs:anyURI) for\n a given node, object, or array.

    \n

    The generated identifier is immutable, i.e. a identifier does not\n change during the item's lifetime and cannot be reused for another node after\n the original item gets deleted.

    \n

    Identifiers are also unique, in that, two different items will never\n have the same identifier.

    \n A item, at any time during its lifetime, can be retrieved by its\n identifier, using the ref:dereference function.\n Please note that a reference can only be retrieved for a JSON object or JSON\n array if the item is a member of a collection.\n", "summary" : "

    Returns an immutable and opaque reference (with type xs:anyURI) for\n a given node, object, or array.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : null, "description" : "
    the node, object, or array for which the URI should be computed
    " } ], "returns" : { "type" : "xs:string", "description" : "the opaque URI of the item." }, "errors" : [ "zerr::ZAPI0080 is raised if the object or array passed as argument is not a member of a collection." ] } ], "variables" : [ ] }, "http://zorba.io/modules/dctx" : { "ns" : "http://zorba.io/modules/dctx", "description" : " This module provides functions that gets components of the dynamic context.\n", "sees" : [ ], "authors" : [ "Federico Cavalieri" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/dctx", "prefix" : "dctx" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "snapshot-id", "qname" : "dctx:snapshot-id", "signature" : "() as xs:unsignedLong external", "description" : "

    Retrieves the current snapshot id.

    \n

    The returned id is opaque and should not be used for reasoning about time.\n The only guarantee is that the value returned by this function increases each\n time a snapshot finishes.

    \n", "summary" : "

    Retrieves the current snapshot id.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:unsignedLong", "description" : "the current snapshot id." }, "errors" : [ ] } ], "variables" : [ ] }, "http://xbrl.io/modules/bizql/facts" : { "ns" : "http://xbrl.io/modules/bizql/facts", "description" : "

    This module provides functions for retrieving facts.

    \n

    Facts are the smallest reportable piece of information.

    \n

    Facts have a certain number of characteristics: the archive in\n which they were reported, a number of XBRL aspects (concept, entity, period,\n unit, further XBRL dimensions), as well as profile-specific information.

    \n

    With this module, you can retrieve facts by picking the characteristics\n you would like your results to have. You can retrieve a fact with its FID\n (Fact ID). You can extract information about facts (period, entity, etc).\n You can perform a full-text search on fact values, and obtain footnotes.

    \n

    If you are interested in the structures in which facts can be organized (such\n as hypercubes), look at the components module.

    \n

    Facts are stored in a MongoDB datasource called xbrl.

    \n

    Standard $options Parameter

    \n

    Most functions in the BizQL package allow an additional $options\n parameter. The options parameter is a JSON object allowing the following\n fields:

    \n
      \n
    • Hypercube: a hypercube object can be passed with the options to apply\n implicit filtering for it. Only facts belonging to this hypercube will be\n returned. Hypercube semantics (such as default dimension values) apply.\n By default, the dimensionless hypercube is used (no dimensions allowed, no filtering).\n You can override Hypercube with null to bypass hypercube semantics.
    • \n
    • Filter: an object specifying the fields to filter for. Filtering fields\n can be any field contained in facts, including profile specific fields, e.g.:\n
      \n   {\n     Filter:\n       {\n         Archive: \"0000034088-13-000011\",\n         Aspects:\n         {\n           \"us-gaap:DefinedBenefitPlansDisclosuresDefinedBenefitPlansAxis\" :\n             \"us-gaap:ForeignPensionPlansDefinedBenefitMember\"\n         },\n         Profiles: {\n           SEC: {\n             Fiscal: {\n               Year: [2011, 2012]\n             }\n           }\n         }\n       }\n   }\n   
      \n A filter must contain at least on of the fields Archive, Aspects.xbrl:Concept,\n Aspects.xbrl:Period, or Aspects.xbrl:Entity.
    • \n
    • concept-maps:\n
      1. a string which is a name of a report schema that is stored in the\n reportschemas collection and from which to load a ConceptMap
      2. \n
      3. an object which is a ConceptMap network object
      4. \n
      5. an array of ConceptMap network objects (to learn more about concept-maps\n refer to the concept-maps module documentation)
      6. \n
    • \n
    • Rules:\n
      1. a string which is a name of a report schema that is stored in the\n reportschemas collection and from which to load Rules
      2. \n
      3. an object which is a Rule object
      4. \n
      5. an array of Rule objects
      6. \n
    • \n
    • include-footnotes: include XBRL Footnotes in each fact (true | false)
    • \n
    • Lang: language identifier according to http://www.ietf.org/rfc/rfc3066.txt,\n i.e. only return footnotes etc. for this specific language
    • \n
    • audit-trail: if set to \"debug\" the audit trails will be more verbose
    • \n
    • facts-for-archives-and-concept: to override how underlying facts are\n resolved, for example with finer-grained, profile-specific filtering (option value\n must be a function item). facts:facts-for-archives-and-concepts#3 is used by\n default, but it is possible to supply another function that, for examples, filters\n irrelevant facts out.
    • \n
    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/archives", "prefix" : "archives" }, { "uri" : "http://xbrl.io/modules/bizql/concept-maps", "prefix" : "concept-maps" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://xbrl.io/modules/bizql/entities", "prefix" : "entities" }, { "uri" : "http://xbrl.io/modules/bizql/facts", "prefix" : "facts" }, { "uri" : "http://xbrl.io/modules/bizql/footnotes", "prefix" : "footnotes" }, { "uri" : "http://xbrl.io/modules/bizql/hypercubes", "prefix" : "hypercubes" }, { "uri" : "http://jsoniq.org/function-library", "prefix" : "j" }, { "uri" : "http://www.28msec.com/modules/mongodb", "prefix" : "mongo" }, { "uri" : "http://zorba.io/modules/reflection", "prefix" : "reflection" }, { "uri" : "http://xbrl.io/modules/bizql/rules", "prefix" : "rules" }, { "uri" : "http://zorba.io/modules/string", "prefix" : "string" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/modules/zorba-query", "prefix" : "zq" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "concept-for-fact", "qname" : "facts:concept-for-fact", "signature" : "($fact-or-id as item()) as string", "description" : "

    Retrieves the concept against which a fact is reported.

    \n", "summary" : "

    Retrieves the concept against which a fact is reported.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "fact-or-id", "type" : "item()", "occurrence" : null, "description" : "
    a fact or its FID.
    " } ], "returns" : { "type" : "string", "description" : "the concept name." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "decimal-value", "qname" : "facts:decimal-value", "signature" : "($facts as object()*) as decimal", "description" : "

    Returns the value of the given facts in case that it\n is castable to decimal. If no facts are given or a fact value\n is not castable to decimal 0 is returned instead.

    \n", "summary" : "

    Returns the value of the given facts in case that it\n is castable to decimal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "facts", "type" : "object()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "decimal", "description" : "the decimal value of the facts or 0." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "duration-for-fact", "qname" : "facts:duration-for-fact", "signature" : "($fact-or-id as item()) as object()?", "description" : "

    Retrieves the duration period for which a fact was reported.

    \n", "summary" : "

    Retrieves the duration period for which a fact was reported.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "fact-or-id", "type" : "item()", "occurrence" : null, "description" : "
    a fact or its FID.
    " } ], "returns" : { "type" : "object()?", "description" : "the duration period as an object with Start and End, or the empty sequence if it is not instant." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "entity-for-fact", "qname" : "facts:entity-for-fact", "signature" : "($fact-or-id as item()) as string", "description" : "

    Retrieves the eid of the entity who reported a fact.

    \n", "summary" : "

    Retrieves the eid of the entity who reported a fact.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "fact-or-id", "type" : "item()", "occurrence" : null, "description" : "
    a fact or its FID.
    " } ], "returns" : { "type" : "string", "description" : "the eid." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "facts-for-archives-and-aspects", "qname" : "facts:facts-for-archives-and-aspects", "signature" : "($archives-or-ids as item()*, $aspects as object()) as object()*", "description" : "

    Return all facts reported in a given archive, and associated with a\n given entity, concept, period and/or other aspects.

    \n", "summary" : "

    Return all facts reported in a given archive, and associated with a\n given entity, concept, period and/or other aspects.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archive or archive IDs to filter (or $facts:ALL_OF_THEM to do not filter on archives).
    " }, { "name" : "aspects", "type" : "object()", "occurrence" : null, "description" : "
    an object containing aspects to filter, among which xbrl:Concept, xbrl:Entity and xbrl:Period (at least one of them is mandatory).
    " } ], "returns" : { "type" : "object()*", "description" : "all facts satisfying all supplied conditions." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "facts-for-archives-and-aspects", "qname" : "facts:facts-for-archives-and-aspects", "signature" : "($archives-or-ids as item()*, $aspects as object(), $options as object()?) as object()*", "description" : "

    Return all facts associated with a given entity, concept, period\n and/or other aspects.

    \n", "summary" : "

    Return all facts associated with a given entity, concept, period\n and/or other aspects.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archive or archive IDs to filter (or $facts:ALL_OF_THEM to do not filter on archives).
    " }, { "name" : "aspects", "type" : "object()", "occurrence" : null, "description" : "
    an object containing aspects to filter, among which xbrl:Concept, xbrl:Entity and xbrl:Period (all optional).
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "all facts satisfying all supplied conditions." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "facts-for-archives-and-concepts", "qname" : "facts:facts-for-archives-and-concepts", "signature" : "($archives-or-ids as item()*, $concepts as item()*) as object()*", "description" : "

    Return facts associated with given concepts and archives.

    \n", "summary" : "

    Return facts associated with given concepts and archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archive or archive IDs to filter (or $facts:ALL_OF_THEM to do not filter on archives).
    " }, { "name" : "concepts", "type" : "item()", "occurrence" : "*", "description" : "
    the concepts (or $facts:ALL_OF_THEM to do no filter on concepts).
    " } ], "returns" : { "type" : "object()*", "description" : "facts associated with these concepts and archives." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "facts-for-archives-and-concepts", "qname" : "facts:facts-for-archives-and-concepts", "signature" : "($archives-or-ids as item()*, $concepts as item()*, $options as object()?) as object()*", "description" : "

    Return facts associated with given concepts and archives.

    \n", "summary" : "

    Return facts associated with given concepts and archives.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : "item()", "occurrence" : "*", "description" : "" }, { "name" : "concepts", "type" : "item()", "occurrence" : "*", "description" : "
    the concepts (or $facts:ALL_OF_THEM to do no filter on concepts).
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "facts associated with these concepts." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "facts-for-archives", "qname" : "facts:facts-for-archives", "signature" : "($archives-or-ids as item()*) as object()*", "description" : "

    Return all facts reported within a given archive.

    \n", "summary" : "

    Return all facts reported within a given archive.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archives-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or AIDs to filter.
    " } ], "returns" : { "type" : "object()*", "description" : "all facts reported in these archives." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "facts-for-aspects", "qname" : "facts:facts-for-aspects", "signature" : "($aspects as object()) as object()*", "description" : "

    Return all facts associated with the given aspects.

    \n", "summary" : "

    Return all facts associated with the given aspects.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "aspects", "type" : "object()", "occurrence" : null, "description" : "
    an object containing aspects to filter, among which xbrl:Concept, xbrl:Entity and xbrl:Period (at least one of them is mandatory).
    " } ], "returns" : { "type" : "object()*", "description" : "all facts associated with these aspects." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "facts-for-aspects", "qname" : "facts:facts-for-aspects", "signature" : "($aspects as object(), $options as object()?) as object()*", "description" : "

    Return all facts associated with the given aspects.

    \n", "summary" : "

    Return all facts associated with the given aspects.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "aspects", "type" : "object()", "occurrence" : null, "description" : "
    an object containing aspects to filter, among which xbrl:Concept, xbrl:Entity and xbrl:Period (at least one of them is mandatory).
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "all facts associated with these aspects." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "facts-for-concepts", "qname" : "facts:facts-for-concepts", "signature" : "($concepts as string*) as object()*", "description" : "

    Return facts associated with given concepts.

    \n", "summary" : "

    Return facts associated with given concepts.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "concepts", "type" : "string", "occurrence" : "*", "description" : "
    the concepts.
    " } ], "returns" : { "type" : "object()*", "description" : "facts associated with these concepts." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "facts-for-concepts", "qname" : "facts:facts-for-concepts", "signature" : "($concepts as string*, $options as object()?) as object()*", "description" : "

    Return facts associated with given concepts.

    \n", "summary" : "

    Return facts associated with given concepts.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "concepts", "type" : "string", "occurrence" : "*", "description" : "
    the concepts.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "facts associated with these concepts." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "facts-for-entities", "qname" : "facts:facts-for-entities", "signature" : "($entities-or-ids as item()*) as object()*", "description" : "

    Return facts reported by the given entities.

    \n", "summary" : "

    Return facts reported by the given entities.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "entities-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    the entities or EIDs.
    " } ], "returns" : { "type" : "object()*", "description" : "facts reported by the given entities." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "facts-for", "qname" : "facts:facts-for", "signature" : "($options as object()?) as object()*", "description" : "

    Return all facts that match a given filter object optionally interpreted\n in the context of an optionally given hypercube.

    \n", "summary" : "

    Return all facts that match a given filter object optionally interpreted\n in the context of an optionally given hypercube.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "all facts satisfying the filter and options." }, "errors" : [ "facts:FILTER-TOO-GENERIC The filter object must have at least one of the fields Archive, Aspects.xbrl:Concept, Aspects.xbrl:Period, or Aspects.xbrl:Entity." ] }, { "isDocumented" : true, "arity" : 1, "name" : "facts-search", "qname" : "facts:facts-search", "signature" : "($search as string) as object()*", "description" : "

    Return all facts that match the given search term.

    \n", "summary" : "

    Return all facts that match the given search term.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "search", "type" : "string", "occurrence" : null, "description" : "
    the search query
    " } ], "returns" : { "type" : "object()*", "description" : "all facts matching the given search query" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "facts", "qname" : "facts:facts", "signature" : "($fact-or-ids as item()*) as object()*", "description" : "

    Return the fact with the given FIDs.

    \n", "summary" : "

    Return the fact with the given FIDs.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "fact-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    the FIDs or the facts themselves.
    " } ], "returns" : { "type" : "object()*", "description" : "the facts with the given FIDs the empty sequence if no fact was found or if the input is an empty sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "fid", "qname" : "facts:fid", "signature" : "($facts-or-ids as item()*) as atomic*", "description" : "

    Converts the input to a normalized fact id (FID). The input\n can be either an FID, or a fact object which contains an _id.

    \n", "summary" : "

    Converts the input to a normalized fact id (FID).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "facts-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of fact objects or FIDs.
    " } ], "returns" : { "type" : "atomic*", "description" : "the normalized FIDs." }, "errors" : [ "facts:INVALID-PARAMETER if the FID or fact is not valid." ] }, { "isDocumented" : true, "arity" : 1, "name" : "instant-for-fact", "qname" : "facts:instant-for-fact", "signature" : "($fact-or-id as item()) as atomic?", "description" : "

    Retrieves the instant period for which a fact was reported.

    \n", "summary" : "

    Retrieves the instant period for which a fact was reported.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "fact-or-id", "type" : "item()", "occurrence" : null, "description" : "
    a fact or its FID.
    " } ], "returns" : { "type" : "atomic?", "description" : "the instance period, or the empty sequence if it is not instant." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-fact-forever", "qname" : "facts:is-fact-forever", "signature" : "($fact-or-id as item()) as boolean", "description" : "

    Tests whether a fact is reported forever.

    \n", "summary" : "

    Tests whether a fact is reported forever.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "fact-or-id", "type" : "item()", "occurrence" : null, "description" : "
    a fact or its FID.
    " } ], "returns" : { "type" : "boolean", "description" : "true if its period is forever, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "merge-objects", "qname" : "facts:merge-objects", "signature" : "($o1 as object()?, $o2 as object()?, $prioritize-first-object as boolean) as object()?", "description" : "

    Helper function to deep-merge two objects. If the two given objects have\n fields with the same name they are merged, which means:\n 1. if the values of the fields are objects then these are merged\n 2. in any other case the fields are accumulated into an array.

    \n

    The third parameter can be used to priotitize the first object. If the first\n object is prioritized and both objects contain fields with the same name,\n the fields are either merged (in case of two object values) or the value of\n the first object is taken.

    \n", "summary" : "

    Helper function to deep-merge two objects.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "o1", "type" : "object()", "occurrence" : "?", "description" : "
    first object
    " }, { "name" : "o2", "type" : "object()", "occurrence" : "?", "description" : "
    second object
    " }, { "name" : "prioritize-first-object", "type" : "boolean", "occurrence" : null, "description" : "
    boolean flag to give the first object higher priority in the merge
    " } ], "returns" : { "type" : "object()?", "description" : "one merge object or an empty-sequence (in case both input objects are empty)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "populate-with-footnotes", "qname" : "facts:populate-with-footnotes", "signature" : "($fact-or-ids as item()*) as object()*", "description" : "

    Populates a sequence of facts with their associated footnotes.\n More in detail, in each returned fact object an additional field\n Footnotes is added which contains all connected footnotes in an\n array.

    \n", "summary" : "

    Populates a sequence of facts with their associated footnotes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "fact-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    the FIDs or the facts themselves.
    " } ], "returns" : { "type" : "object()*", "description" : "a sequence of facts with populated Footnotes field." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "populate-with-footnotes", "qname" : "facts:populate-with-footnotes", "signature" : "($fact-or-ids as item()*, $options as object()?) as object()*", "description" : "

    Populates a sequence of facts with their associated footnotes.\n More in detail, in each returned fact object an additional field\n Footnotes is added which contains all connected footnotes in an\n array.

    \n", "summary" : "

    Populates a sequence of facts with their associated footnotes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "fact-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    the FIDs or the facts themselves.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "a sequence of facts with populated Footnotes field." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "prefix-from-fact-concept", "qname" : "facts:prefix-from-fact-concept", "signature" : "($fact as object()) as string?", "description" : "

    Helper function to get the prefix of a given fact`s xbrl:Concept aspect.

    \n", "summary" : "

    Helper function to get the prefix of a given fact`s xbrl:Concept aspect.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "fact", "type" : "object()", "occurrence" : null, "description" : "
    a fact object.
    " } ], "returns" : { "type" : "string?", "description" : "the prefix of the fact's xbrl:Concept aspect or empty sequence if the concept doesn't have a prefix." }, "errors" : [ ] } ], "variables" : [ { "name" : "facts:col", "type" : "string", "description" : " Name of the collection the facts are stored in.\n" }, { "name" : "facts:ID", "type" : "string", "description" : " Name of the field that points to the facts FID.\n" }, { "name" : "facts:ARCHIVE", "type" : "string", "description" : " Name of the field that points to the archive.\n" }, { "name" : "facts:ASPECTS", "type" : "string", "description" : " Name of the field that stores the aspects.\n" }, { "name" : "facts:CONCEPT", "type" : "string", "description" : " Name of the concept aspect.\n" }, { "name" : "facts:PERIOD", "type" : "string", "description" : " Name of the period aspect.\n" }, { "name" : "facts:ENTITY", "type" : "string", "description" : " Name of the entity aspect.\n" }, { "name" : "facts:UNIT", "type" : "string", "description" : " Name of the unit aspect.\n" }, { "name" : "facts:FOOTNOTES", "type" : "string", "description" : " Name of the field that stores the Footnotes (if populated).\n" }, { "name" : "facts:ALL_OF_THEM", "type" : "boolean", "description" : " Joker for all archives or all concepts.\n" } ] }, "http://www.w3.org/2005/xqt-errors" : { "ns" : "http://www.w3.org/2005/xqt-errors", "description" : " This module contains one variable declaration for each diagnostic of the\n http://www.w3.org/2005/xqt-errors namespace.\n The variables serves as documentation for the errors but can also\n be used in the code. For example, one useful scenario is to compare\n an error caught in the catch clause of a try-catch expression with one of\n the variables.\n", "sees" : [ ], "authors" : [ "Carlos Lopez" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" } ], "functions" : [ ], "variables" : [ { "name" : "err:FORG0006", "type" : "xs:QName", "description" : " Invalid argument type.\n" }, { "name" : "err:FODF1280", "type" : "xs:QName", "description" : " Invalid decimal format name supplied to \\c fn:format-number().\n" }, { "name" : "err:FODF1310", "type" : "xs:QName", "description" : " Invalid decimal/integer format picture string.\n" }, { "name" : "err:FODT0001", "type" : "xs:QName", "description" : " Overflow/underflow in date/time operation.\n" }, { "name" : "err:FODT0002", "type" : "xs:QName", "description" : " Overflow/underflow in duration operation.\n" }, { "name" : "err:FODT0003", "type" : "xs:QName", "description" : " Invalid timezone value.\n" }, { "name" : "err:FONS0004", "type" : "xs:QName", "description" : " No namespace found for prefix.\n" }, { "name" : "err:FONS0005", "type" : "xs:QName", "description" : " Base-URI not defined in static context.\n" }, { "name" : "err:FORG0001", "type" : "xs:QName", "description" : " Invalid value for cast/constructor.\n" }, { "name" : "err:FORG0002", "type" : "xs:QName", "description" : " Invalid argument to \\c fn:resolve-uri().\n" }, { "name" : "err:FORG0003", "type" : "xs:QName", "description" : " \\c fn:zero-or-one() called with a sequence containing more than one\n item.\n" }, { "name" : "err:FORG0004", "type" : "xs:QName", "description" : " \\c fn:one-or-more() called with a sequence containing no items.\n" }, { "name" : "err:FORG0005", "type" : "xs:QName", "description" : " \\c fn:exactly-one() called with a sequence containing zero or more\n than one item.\n" }, { "name" : "err:FODC0007", "type" : "xs:QName", "description" : " Base URI passed to \\c fn:parse() is not a valid absolute URI.\n" }, { "name" : "err:FORG0008", "type" : "xs:QName", "description" : " The two arguments to fn:dateTime() have inconsistent timezones.\n" }, { "name" : "err:FORG0009", "type" : "xs:QName", "description" : " Error in resolving a relative URI against a base URI in\n \\c fn:resolve-uri().\n" }, { "name" : "err:FORX0001", "type" : "xs:QName", "description" : " Invalid regular expression flags.\n" }, { "name" : "err:FORX0002", "type" : "xs:QName", "description" : " Invalid regular expression.\n" }, { "name" : "err:FORX0003", "type" : "xs:QName", "description" : " Regular expression matches zero-length string.\n" }, { "name" : "err:FORX0004", "type" : "xs:QName", "description" : " Invalid replacement string.\n" }, { "name" : "err:FOTY0012", "type" : "xs:QName", "description" : " Argument node does not have a typed value.\n" }, { "name" : "err:FOTY0013", "type" : "xs:QName", "description" : " An argument to \\c fn:data() contains a node that does not have a typed\n value.\n" }, { "name" : "err:FOTY0014", "type" : "xs:QName", "description" : " The argument to \\c fn:string() is a function item.\n" }, { "name" : "err:FOTY0015", "type" : "xs:QName", "description" : " An argument to \\c fn:deep-equal() contains a function item.\n" }, { "name" : "err:FOUT1170", "type" : "xs:QName", "description" : " Identifier cannot be used to retrive a resource containing text\n" }, { "name" : "err:FOCA0005", "type" : "xs:QName", "description" : " NaN supplied as float/double value.\n" }, { "name" : "err:FTDY0016", "type" : "xs:QName", "description" : " It is a dynamic error if a weight value is not within the required range\n of values; it is also a dynamic error if an implementation that does not\n support negative weights encounters a negative weight value.\n" }, { "name" : "err:FTDY0017", "type" : "xs:QName", "description" : " It is a dynamic error if an implementation encounters a mild not\n selection, one of whose operands evaluates to an AllMatches that\n contains a StringExclude.\n" }, { "name" : "err:FTST0018", "type" : "xs:QName", "description" : " It is a static error if, during the static analysis phase, the query is\n found to contain a thesaurus option that refers to a thesaurus that is\n not found in the statically known thesauri.\n" }, { "name" : "err:FTST0019", "type" : "xs:QName", "description" : " It is a static error if, within a single FTMatchOptions, there is more\n than one match option of any given match option group.\n" }, { "name" : "err:FTDY0020", "type" : "xs:QName", "description" : " It is a dynamic error if, when \"wildcards\" is in effect, a query string\n violates wildcard syntax.\n" }, { "name" : "err:FOER0000", "type" : "xs:QName", "description" : " Unidentified error.\n" }, { "name" : "err:FOAR0001", "type" : "xs:QName", "description" : " Division by zero.\n" }, { "name" : "err:FOAR0002", "type" : "xs:QName", "description" : " Numeric operation overflow/underflow.\n" }, { "name" : "err:FOCA0001", "type" : "xs:QName", "description" : " Input value too large for decimal.\n" }, { "name" : "err:FOCA0002", "type" : "xs:QName", "description" : " Invalid lexical value.\n" }, { "name" : "err:FOCA0003", "type" : "xs:QName", "description" : " Input value too large for integer.\n" }, { "name" : "err:FOUT1190", "type" : "xs:QName", "description" : " Retrieved resource contains octets that cannot be decoded into Unicode\n using the specified encoding, the resulting characters are not\n permitted XML characters or requested encoding not supported\n" }, { "name" : "err:FOCA0006", "type" : "xs:QName", "description" : " Raised when casting a string to xs:decimal if the string has more\n digits of precision than the implementation can represent (the\n implementation also has the option of rounding).\n" }, { "name" : "err:FOCH0001", "type" : "xs:QName", "description" : " Code point not valid.\n" }, { "name" : "err:FOCH0002", "type" : "xs:QName", "description" : " Unsupported collation.\n" }, { "name" : "err:FOCH0003", "type" : "xs:QName", "description" : " Unsupported normalization form.\n" }, { "name" : "err:FOCH0004", "type" : "xs:QName", "description" : " Collation does not support collation units.\n" }, { "name" : "err:FODC0001", "type" : "xs:QName", "description" : " No context document.\n" }, { "name" : "err:FODC0002", "type" : "xs:QName", "description" : " Error retrieving resource.\n" }, { "name" : "err:FODC0003", "type" : "xs:QName", "description" : " Raised by fn:doc, fn:collection to indicate that it is not possible to\n return a result that is guaranteed deterministic.\n" }, { "name" : "err:FODC0004", "type" : "xs:QName", "description" : " Invalid argument to \\c fn:collection().\n" }, { "name" : "err:FODC0005", "type" : "xs:QName", "description" : " Invalid argument to \\c fn:doc() or \\c fn:doc-available().\n" }, { "name" : "err:FODC0006", "type" : "xs:QName", "description" : " Invalid content passed to \\c fn:parse().\n" }, { "name" : "err:SERE0005", "type" : "xs:QName", "description" : " It is an error if the serialized result would contain an NCName Names\n that contains a character that is not permitted by the version of\n Namespaces in XML specified by the version parameter.\n" }, { "name" : "err:XUDY0024", "type" : "xs:QName", "description" : " It is a dynamic error if the effect of a set of updating expressions is\n to introduce conflicting namespace bindings into an element node.\n" }, { "name" : "err:XUDY0027", "type" : "xs:QName", "description" : " It is a dynamic error if the target expression of an insert, replace, or\n rename expression evaluates to an empty sequence.\n" }, { "name" : "err:XUST0028", "type" : "xs:QName", "description" : " It is a static error if a function declaration specifies both \\c updating\n and a return type.\n" }, { "name" : "err:XUDY0029", "type" : "xs:QName", "description" : " In an insert expression where \\c before or \\c after is specified, it is\n a dynamic error if the node returned by the target expression does not\n have a parent.\n" }, { "name" : "err:XUDY0030", "type" : "xs:QName", "description" : " It is a dynamic error if an insert expression specifies the insertion of\n an attribute node before or after a child of a document node.\n" }, { "name" : "err:XUDY0031", "type" : "xs:QName", "description" : " It is a dynamic error if multiple calls to \\c fn:put() in the same\n snapshot specify the same URI (after resolution of relative URIs).\n" }, { "name" : "err:FOUP0001", "type" : "xs:QName", "description" : " It is a dynamic error if the first operand of \\c fn:put() is not a node\n of a supported kind.\n" }, { "name" : "err:FOUP0002", "type" : "xs:QName", "description" : " It is a dynamic error if the second operand of \\c fn:put() is not a valid\n lexical representation of the \\c xs:anyURI type.\n" }, { "name" : "err:SENR0001", "type" : "xs:QName", "description" : " It is an error if an item in S6 in sequence normalization is an attribute\n node or a namespace node.\n" }, { "name" : "err:SERE0003", "type" : "xs:QName", "description" : " It is an error if the serializer is unable to satisfy the rules for\n either a well-formed XML document entity or a well-formed XML external\n general parsed entity, or both, except for content modified by the\n character expansion phase of serialization.\n" }, { "name" : "err:SEPM0004", "type" : "xs:QName", "description" : " It is an error to specify the doctype-system parameter, or to specify\n the standalone parameter with a value other than omit, if the instance\n of the data model contains text nodes or multiple element nodes as\n children of the root node.\n" }, { "name" : "err:XUDY0023", "type" : "xs:QName", "description" : " It is a dynamic error if an insert, replace, or rename expression\n affects an element node by introducing a new namespace binding that\n conflicts with one of its existing namespace bindings.\n" }, { "name" : "err:SERE0006", "type" : "xs:QName", "description" : " It is an error if the serialized result would contain a character that is\n not permitted by the version of XML specified by the version parameter.\n" }, { "name" : "err:SESU0007", "type" : "xs:QName", "description" : " It is an error if an output encoding other than UTF-8 or UTF-16 is\n requested and the serializer does not support that encoding.\n" }, { "name" : "err:SERE0008", "type" : "xs:QName", "description" : " It is an error if a character that cannot be represented in the encoding\n that the serializer is using for output appears in a context where\n character references are not allowed (for example if the character\n occurs in the name of an element).\n" }, { "name" : "err:SEPM0009", "type" : "xs:QName", "description" : " It is an error if the omit-xml-declaration parameter has the value yes,\n and the standalone attribute has a value other than omit; or the version\n parameter has a value other than 1.0 and the doctype-system parameter is\n specified.\n" }, { "name" : "err:SEPM0010", "type" : "xs:QName", "description" : " It is an error if the output method is xml, the value of the\n undeclare-prefixes parameter is yes, and the value of the version\n parameter is 1.0.\n" }, { "name" : "err:SESU0011", "type" : "xs:QName", "description" : " It is an error if the value of the normalization-form parameter\n specifies a normalization form that is not supported by the serializer.\n" }, { "name" : "err:SERE0012", "type" : "xs:QName", "description" : " It is an error if the value of the normalization-form parameter is\n fully-normalized and any relevant construct of the result begins with a\n combining character.\n" }, { "name" : "err:SESU0013", "type" : "xs:QName", "description" : " It is an error if the serializer does not support the version of XML or\n HTML specified by the version parameter.\n" }, { "name" : "err:SERE0014", "type" : "xs:QName", "description" : " It is an error to use the HTML output method when characters which are\n legal in XML but not in HTML, specifically the control characters\n #x7F-#x9F, appear in the instance of the data model.\n" }, { "name" : "err:SERE0015", "type" : "xs:QName", "description" : " It is an error to use the HTML output method when \\c > appears within a\n processing instruction in the data model instance being serialized.\n" }, { "name" : "err:SEPM0016", "type" : "xs:QName", "description" : " It is a an error if a parameter value is invalid for the defined domain.\n" }, { "name" : "err:XUTY0010", "type" : "xs:QName", "description" : " In a replace expression where value of is not specified and\n the target is an element, text, comment, or processing instruction node,\n it is a type error if the replacement sequence does not consist of zero\n or more element, text, comment, or processing instruction nodes.\n" }, { "name" : "err:FOFL0001", "type" : "xs:QName", "description" : " This error is raised if the fn:function-lookup returns a context-dependent function and the context-dependent function is then called.\n" }, { "name" : "err:FOCZ0001", "type" : "xs:QName", "description" : " Invalid content passed to \\c x:canonicalize().\n" }, { "name" : "err:XUST0001", "type" : "xs:QName", "description" : " It is a static error if an updating expression is used in any position\n other than one of the following:\n - The topmost expression in the body of a query.\n - The \\c modify clause of a transform expression.\n - The \\c return clause of a FLWOR expression.\n - The \\c return clauses of a typeswitch expression in which every \\c\n return clause contains an updating expression or a vacuous expression.\n - The \\c then and \\c else clauses of a conditional statement in which\n both the \\c then and \\c else clauses contain either an updating\n expression or a vacuous expression.\n - An operand of a comma expression in which each operand is either an\n updating expression or a vacuous expression.\n - The content of a parenthesized expression.\n - The body of a function declaration in which the keyword \\c updating is\n specified.\n" }, { "name" : "err:XUST0002", "type" : "xs:QName", "description" : " It is a static error if a simple expression that is not a vacuous\n expression is used in one of the following positions:\n - The \\c modify clause of a transform expression.\n - The top-level expression in the body of a function declaration in\n which the keyword \\c updating is specified.\n" }, { "name" : "err:XUST0003", "type" : "xs:QName", "description" : " It is a static error if a Prolog contains more than one revalidation\n declaration.\n" }, { "name" : "err:XUTY0004", "type" : "xs:QName", "description" : " It is a type error if the insertion sequence of an insert expression\n contains an attribute node following a node that is not an attribute\n node.\n" }, { "name" : "err:XUTY0005", "type" : "xs:QName", "description" : " In an insert expression where into, as first\n into, or as last into is specified, it is a type\n error if the target expression returns a non-empty result that does not\n consist of a single element or document node.\n" }, { "name" : "err:XUTY0006", "type" : "xs:QName", "description" : " In an insert expression where \\c before or \\c after is specified, it is\n a type error if the target expression returns a non-empty result that\n does not consist of a single element, text, comment, or processing\n instruction node.\n" }, { "name" : "err:XUTY0007", "type" : "xs:QName", "description" : " It is a type error if the target expression of a delete expression does\n not return a sequence of zero or more nodes.\n" }, { "name" : "err:XUTY0008", "type" : "xs:QName", "description" : " In a replace expression, it is a type error if the target expression\n returns a non-empty result that does not consist of a single element,\n attribute, text, comment, or processing instruction node.\n" }, { "name" : "err:XUDY0009", "type" : "xs:QName", "description" : " In a replace expression where value of is not specified, it\n is a dynamic error if the node returned by the target expression does\n not have a parent.\n" }, { "name" : "err:FTST0009", "type" : "xs:QName", "description" : " It may be a static error if, during the static analysis phase, the query\n is found to contain a language identifier in a language option that the\n implementation does not support. The implementation may choose not to\n raise this error and instead provide some other implementation-defined\n behavior.\n" }, { "name" : "err:XUTY0011", "type" : "xs:QName", "description" : " In a replace expression where value of is not specified and\n the target is an attribute node, it is a type error if the replacement\n sequence does not consist of zero or more attribute nodes.\n" }, { "name" : "err:XUTY0012", "type" : "xs:QName", "description" : " In a rename expression, it is a type error if the target expression\n returns a non-empty result that does not consist of a single element,\n attribute, or processing instruction node.\n" }, { "name" : "err:XUTY0013", "type" : "xs:QName", "description" : " In a transform expression, it is a type error if a source expression in\n the \\c copy clause does not return a single node.\n" }, { "name" : "err:XUDY0014", "type" : "xs:QName", "description" : " In a transform expression, it is a dynamic error if the \\c modify clause\n modifies any node that was not created by the \\c copy clause.\n" }, { "name" : "err:XUDY0015", "type" : "xs:QName", "description" : " It is a dynamic error if any node is the target of more than one \\c\n rename expression within the same query.\n" }, { "name" : "err:XUDY0016", "type" : "xs:QName", "description" : " It is a dynamic error if any node is the target of more than one \\c\n replace expression (without value of being specified)\n within the same query.\n" }, { "name" : "err:XUDY0017", "type" : "xs:QName", "description" : " It is a dynamic error if any node is the target of more than one\n replace value of expression within the same query.\n" }, { "name" : "err:XUDY0018", "type" : "xs:QName", "description" : " It is a dynamic error if a function that was declared to be \\c external\n but not \\c updating returns a non-empty pending update list.\n" }, { "name" : "err:XUDY0019", "type" : "xs:QName", "description" : " It is a dynamic error if a function that was declared to be both \\c\n external and \\c updating returns a non-empty data model instance.\n" }, { "name" : "err:XUDY0021", "type" : "xs:QName", "description" : " It is a dynamic error if the XDM instance that would result from\n applying all the updates in a query violates any constraint specified in\n [XQuery 1.0 and XPath 2.0 Data Model]. In this case, none of the updates\n in the query are made effective.\n" }, { "name" : "err:XUTY0022", "type" : "xs:QName", "description" : " It is a type error if an insert expression specifies the insertion of an\n attribute node into a document node.\n" }, { "name" : "err:XQST0052", "type" : "xs:QName", "description" : " The type must be the name of a type defined in the in-scope schema types,\n and the {variety} of the type must be simple.\n" }, { "name" : "err:XQST0033", "type" : "xs:QName", "description" : " It is a static error if a module contains multiple bindings for the same\n namespace prefix.\n" }, { "name" : "err:XQST0034", "type" : "xs:QName", "description" : " It is a static error if multiple functions declared or imported by a\n module have the same number of arguments and their expanded QNames are\n equal (as defined by the eq operator).\n" }, { "name" : "err:XQST0035", "type" : "xs:QName", "description" : " It is a static error to import two schema components that both define the\n same name in the same symbol space and in the same scope.\n" }, { "name" : "err:XQST0036", "type" : "xs:QName", "description" : " It is a static error to import a module if the in-scope schema\n definitions of the importing module do not include all of the following:\n -# An in-scope schema type for each type-name that appears:\n - in the type of a variable that is declared in the imported module\n and referenced in the importing module, OR\n - in a parameter-type or result-type of a function that is declared in\n the imported module and referenced in the importing module.\n -# An in-scope element declaration for each element-name \\c EN such that:\n - \\c schema-element(EN) appears in the declared type of a variable in\n the imported module, and that variable is referenced in the\n importing module, OR\n - \\c schema-element(EN) appears in a parameter-type or result-type\n of a function declared in the imported module, and that function is\n referenced in the importing module.\n -# An in-scope attribute declaration for each attribute-name \\c AN such\n that:\n - \\c schema-attribute(AN) appears in the declared type of a variable\n in the imported module, and that variable is referenced in the\n importing module, OR\n - \\c schema-attribute(AN) appears in a parameter-type or result-type\n of a function declared in the imported module, and that function is\n referenced in the importing module.\n" }, { "name" : "err:XQST0038", "type" : "xs:QName", "description" : " It is a static error if a Prolog contains more than one default collation\n declaration, or the value specified by a default collation declaration is\n not present in statically known collations.\n" }, { "name" : "err:XQST0039", "type" : "xs:QName", "description" : " It is a static error for a function declaration to have more than one\n parameter with the same name.\n" }, { "name" : "err:XQST0040", "type" : "xs:QName", "description" : " It is a static error if the attributes specified by a direct element\n constructor do not have distinct expanded QNames.\n" }, { "name" : "err:XQST0045", "type" : "xs:QName", "description" : " It is a static error if the function name in a function declaration is in\n one of the following namespaces:\n http://www.w3.org/XML/1998/namespace,\n http://www.w3.org/2001/XMLSchema,\n http://www.w3.org/2001/XMLSchema-instance,\n http://www.w3.org/2005/xpath-functions.\n" }, { "name" : "err:XQST0046", "type" : "xs:QName", "description" : " An implementation MAY raise a static error if the value of a URILiteral\n is of nonzero length and is not in the lexical space of \\c xs:anyURI.\n" }, { "name" : "err:XQST0047", "type" : "xs:QName", "description" : " It is a static error if multiple module imports in the same Prolog\n specify the same target namespace.\n" }, { "name" : "err:XQST0048", "type" : "xs:QName", "description" : " It is a static error if a function or variable declared in a library\n module is not in the target namespace of the library module.\n" }, { "name" : "err:XQST0049", "type" : "xs:QName", "description" : " It is a static error if two or more variables declared or imported by a\n module have equal expanded QNames (as defined by the eq operator.)\n" }, { "name" : "err:XQST0032", "type" : "xs:QName", "description" : " A static error is raised if a Prolog contains more than one base URI\n declaration.\n" }, { "name" : "err:XQST0054", "type" : "xs:QName", "description" : " It is a static error if a variable depends on itself.\n" }, { "name" : "err:XQST0055", "type" : "xs:QName", "description" : " It is a static error if a Prolog contains more than one copy-namespaces\n declaration.\n" }, { "name" : "err:XQST0057", "type" : "xs:QName", "description" : " It is a static error if a schema import binds a namespace prefix but\n does not specify a target namespace other than a zero-length string.\n" }, { "name" : "err:XQST0058", "type" : "xs:QName", "description" : " It is a static error if multiple schema imports specify the same target\n namespace.\n" }, { "name" : "err:XQST0059", "type" : "xs:QName", "description" : " It is a static error if an implementation is unable to process a schema\n or module import by finding a schema or module with the specified\n target namespace.\n" }, { "name" : "err:XQST0060", "type" : "xs:QName", "description" : " It is a static error if the name of a function in a function declaration\n is not in a namespace (expanded QName has a null namespace URI).\n" }, { "name" : "err:XQST0065", "type" : "xs:QName", "description" : " A static error is raised if a Prolog contains more than one ordering mode\n declaration.\n" }, { "name" : "err:XQST0066", "type" : "xs:QName", "description" : " A static error is raised if a Prolog contains more than one default\n element/type namespace declaration, or more than one default function\n namespace declaration.\n" }, { "name" : "err:XQST0067", "type" : "xs:QName", "description" : " A static error is raised if a Prolog contains more than one construction\n declaration.\n" }, { "name" : "err:XQST0068", "type" : "xs:QName", "description" : " A static error is raised if a Prolog contains more than one\n boundary-space declaration.\n" }, { "name" : "err:XQST0069", "type" : "xs:QName", "description" : " A static error is raised if a Prolog contains more than one empty order\n declaration.\n" }, { "name" : "err:XPTY0019", "type" : "xs:QName", "description" : " It is a type error if the result of a step (other than the last step) in a\n path expression contains an atomic value.\n" }, { "name" : "err:XPST0001", "type" : "xs:QName", "description" : " It is a static error if analysis of an expression relies on some\n component of the static context that has not been assigned a value.\n" }, { "name" : "err:XPST0003", "type" : "xs:QName", "description" : " It is a static error if an expression is not a valid instance of the\n grammar.\n" }, { "name" : "err:XPST0005", "type" : "xs:QName", "description" : " During the analysis phase, it is a static error if the static type\n assigned to an expression other than the expression \\c () or \\c data(())\n is \\c empty-sequence().\n" }, { "name" : "err:XPST0008", "type" : "xs:QName", "description" : " It is a static error if an expression refers to an element name,\n attribute name, schema type name, namespace prefix, or variable name\n that is not defined in the static context, except for an ElementName in\n an ElementTest or an AttributeName in an AttributeTest.\n" }, { "name" : "err:XPST0017", "type" : "xs:QName", "description" : " It is a static error if the expanded QName and number of arguments in a\n function call do not match the name and arity of a function signature in\n the static context.\n" }, { "name" : "err:XPST0051", "type" : "xs:QName", "description" : " It is a static error if a QName that is used as an AtomicType in a\n SequenceType is not defined in the in-scope schema types as an atomic\n type.\n" }, { "name" : "err:XPST0080", "type" : "xs:QName", "description" : " It is a static error if the target type of a \\c cast or \\c castable\n expression is \\c xs:NOTATION or \\c xs:anyAtomicType.\n" }, { "name" : "err:XPST0081", "type" : "xs:QName", "description" : " It is a static error if a QName used in a query contains a namespace\n prefix that cannot be expanded into a namespace URI by using the\n statically known namespaces.\n" }, { "name" : "err:XPST0083", "type" : "xs:QName", "description" : " It is a static error if the target type of a \\c cast expression or\n constructor function is \\c xs:QName or a type derived from \\c xs:QName\n or \\c xs:NOTATION, and the argument of the cast expression or\n constructor function is not a string literal.\n" }, { "name" : "err:XPTY0004", "type" : "xs:QName", "description" : " It is a type error if, during the static analysis phase, an expression\n is found to have a static type that is not appropriate for the context\n in which the expression occurs, or during the dynamic evaluation phase,\n the dynamic type of a value does not match a required type as specified\n by the matching rules in 2.5.4 SequenceType Matching.\n" }, { "name" : "err:XPTY0018", "type" : "xs:QName", "description" : " It is a type error if the result of the last step in a path expression\n contains both nodes and non-nodes.\n" }, { "name" : "err:XQST0070", "type" : "xs:QName", "description" : " A static error is raised if one of the predefined prefixes \\c xml or \\c\n xmlns appears in a namespace declaration, or if any of the following\n conditions is statically detected in any expression or declaration:\n - The prefix \\c xml is bound to some namespace URI other than\n http://www.w3.org/XML/1998/namespace.\n - A prefix other than \\c xml is bound to the namespace URI\n http://www.w3.org/XML/1998/namespace.\n - The prefix \\c xmlns is bound to any namespace URI.\n - A prefix other than \\c xmlns is bound to the namespace URI\n http://www.w3.org/2000/xmlns/.\n" }, { "name" : "err:XPTY0020", "type" : "xs:QName", "description" : " It is a type error if, in an axis step, the context item is not a node.\n" }, { "name" : "err:XPTY0117", "type" : "xs:QName", "description" : " Attempt to cast to a namespace-sensitive type failed because the namespace\n bindings for the result can not be determined.\n" }, { "name" : "err:XQTY0024", "type" : "xs:QName", "description" : " It is a type error if the content sequence in an element constructor\n contains an attribute node following a node that is not an attribute node.\n" }, { "name" : "err:XQTY0030", "type" : "xs:QName", "description" : " It is a type error if the argument of a validate expression does not\n evaluate to exactly one document or element node.\n" }, { "name" : "err:XQTY0086", "type" : "xs:QName", "description" : " It is a type error if the typed value of a copied element or attribute\n node is namespace-sensitive when construction mode is \\c preserve and\n copy-namespaces mode is \\c no-preserve.\n" }, { "name" : "err:XQTY0105", "type" : "xs:QName", "description" : " It is a type error if the content sequence in an element constructor contains a function item.\n" }, { "name" : "err:XQST0009", "type" : "xs:QName", "description" : " An implementation that does not support the Schema Import Feature must\n raise a static error if a Prolog contains a schema import.\n" }, { "name" : "err:XQST0012", "type" : "xs:QName", "description" : " It is a static error if the set of definitions contained in all schemas\n imported by a Prolog do not satisfy the conditions for schema validity\n specified in Sections 3 and 5 of [XML Schema] Part 1--i.e., each\n definition must be valid, complete, and unique.\n" }, { "name" : "err:XQST0013", "type" : "xs:QName", "description" : " It is a static error if an implementation recognizes a pragma but\n determines that its content is invalid.\n" }, { "name" : "err:XQST0022", "type" : "xs:QName", "description" : " It is a static error if the value of a namespace declaration attribute is\n not a URILiteral.\n" }, { "name" : "err:XQST0031", "type" : "xs:QName", "description" : " It is a static error if the version number specified in a version\n declaration is not supported by the implementation.\n" }, { "name" : "err:XQDY0072", "type" : "xs:QName", "description" : " It is a dynamic error if the result of the content expression of a\n computed comment constructor contains two adjacent hyphens or ends with\n a hyphen.\n" }, { "name" : "err:XQST0128", "type" : "xs:QName", "description" : " It is a static error if a feature name that an implementation supports appears\n in a prohibit-feature option declaration, and the implementation is unable to\n disable the feature.\n" }, { "name" : "err:XPDY0002", "type" : "xs:QName", "description" : " It is a dynamic error if evaluation of an expression relies on some part\n of the dynamic context that has not been assigned a value.\n" }, { "name" : "err:XPDY0050", "type" : "xs:QName", "description" : " It is a dynamic error if the dynamic type of the operand of a treat\n expression does not match the sequence type specified by the treat\n expression. This error might also be raised by a path expression\n beginning with \"/\" or \"//\" if the context node\n is not in a tree that is rooted at a document node. This is because a\n leading \"/\" or \"//\" in a path expression is an\n abbreviation for an initial step that includes the clause \\c treat as \\c\n document-node().\n" }, { "name" : "err:XQDY0025", "type" : "xs:QName", "description" : " It is a dynamic error if any attribute of a constructed element does not\n have a name that is distinct from the names of all other attributes of\n the constructed element.\n" }, { "name" : "err:XQDY0026", "type" : "xs:QName", "description" : " It is a dynamic error if the result of the content expression of a\n computed processing instruction constructor contains the string \"?>\".\n" }, { "name" : "err:XQDY0027", "type" : "xs:QName", "description" : " In a validate expression, it is a dynamic error if the root element\n information item in the PSVI resulting from validation does not have the\n expected validity property: \\c valid if validation mode is \\c strict, or\n either \\c valid or \\c notKnown if validation mode is \\c lax.\n" }, { "name" : "err:XQDY0041", "type" : "xs:QName", "description" : " It is a dynamic error if the value of the name expression in a computed\n processing instruction constructor cannot be cast to the type\n \\c xs:NCName.\n" }, { "name" : "err:XQDY0044", "type" : "xs:QName", "description" : " It is a static error the node-name of a node constructed by a computed\n attribute constructor has any of the following properties:\n - Its namespace prefix is \\c xmlns.\n - It has no namespace prefix and its local name is \\c xmlns.\n - Its namespace URI is http://www.w3.org/2000/xmlns/.\n - Its namespace prefix is \\c xml and its namespace URI is not\n http://www.w3.org/XML/1998/namespace.\n - Its namespace prefix is other than \\c xml and its namespace URI is\n http://www.w3.org/XML/1998/namespace.\n" }, { "name" : "err:XQDY0054", "type" : "xs:QName", "description" : " It is a dynamic error if a cycle is encountered in the definition of a\n module's dynamic context components, for example because of a cycle in\n variable declarations.\n" }, { "name" : "err:XQDY0061", "type" : "xs:QName", "description" : " It is a dynamic error if the operand of a validate expression is a\n document node whose children do not consist of exactly one element node\n and zero or more comment and processing instruction nodes, in any order.\n" }, { "name" : "err:XQDY0064", "type" : "xs:QName", "description" : " It is a dynamic error if the value of the name expression in a computed\n processing instruction constructor is equal to \"XML\" (in any combination\n of upper and lower case).\n" }, { "name" : "err:XQST0127", "type" : "xs:QName", "description" : " It is a static error if a given feature is both required and prohibited, directly or indirectly, in a module.\n" }, { "name" : "err:XQDY0074", "type" : "xs:QName", "description" : " It is a dynamic error if the value of the name expression in a computed\n element or attribute constructor cannot be converted to an expanded\n QName (for example, because it contains a namespace prefix not found in\n statically known namespaces).\n" }, { "name" : "err:XQDY0084", "type" : "xs:QName", "description" : " It is a dynamic error if the element validated by a \\c validate statement\n does not have a top-level element declaration in the in-scope element\n declarations, if validation mode is \\c strict.\n" }, { "name" : "err:XQDY0091", "type" : "xs:QName", "description" : " An implementation MAY raise a dynamic error if an \\c xml:id error, as\n defined in [XML ID], is encountered during construction of an attribute\n named \\c xml:id.\n" }, { "name" : "err:XQDY0092", "type" : "xs:QName", "description" : " An implementation MAY raise a dynamic error if a constructed attribute\n named \\c xml:space has a value other than \\c preserve or \\c default.\n" }, { "name" : "err:XQDY0096", "type" : "xs:QName", "description" : " It is a dynamic error the node-name of a node constructed by a computed\n element constructor has any of the following properties:\n - Its namespace prefix is \\c xmlns.\n - Its namespace URI is http://www.w3.org/2000/xmlns/.\n - Its namespace prefix is \\c xml and its namespace URI is not\n http://www.w3.org/XML/1998/namespace.\n - Its namespace prefix is other than \\c xml and its namespace URI is\n http://www.w3.org/XML/1998/namespace.\n" }, { "name" : "err:XQDY0101", "type" : "xs:QName", "description" : " Invalid prefix and/or uri in computed namespace constructor\n" }, { "name" : "err:XQDY0102", "type" : "xs:QName", "description" : " In an element constructor, if two or more namespace bindings in the in-scope bindings would have the same prefix, then an error is raised if they have different URIs; if they would have the same prefix and URI, duplicate bindings are ignored.\n" }, { "name" : "err:XTDE1310", "type" : "xs:QName", "description" : " It is a non-recoverable dynamic error if the picture string does not\n satisfy the format-number function rules.\n" }, { "name" : "err:FOFD1340", "type" : "xs:QName", "description" : " It is a non-recoverable dynamic error if the $picture, $language,\n $calendar, or $place argument for fn:format-date, fn:format-time, or\n fn:format-dateTime is invalid.\n" }, { "name" : "err:FOFD1350", "type" : "xs:QName", "description" : " It is a non-recoverable dynamic error if a component specifier within\n the picture refers to components that are not available in the given\n type of $value.\n" }, { "name" : "err:FTST0008", "type" : "xs:QName", "description" : " It is a static error if, during the static analysis phase, the query is\n found to contain a stop word option that refers to a stop word list that\n is not found in the statically known stop word lists.\n" }, { "name" : "err:XQST0098", "type" : "xs:QName", "description" : " It is a static error if, for any named or unnamed decimal format, the\n properties representing characters used in a picture string do not each\n have distinct values. These properties are decimal-separator-sign,\n grouping-separator, percent-sign, per-mille-sign, zero-digit,\n digit-sign, and pattern-separator-sign.\n" }, { "name" : "err:XQST0071", "type" : "xs:QName", "description" : " A static error is raised if the namespace declaration attributes of a\n direct element constructor do not have distinct names.\n" }, { "name" : "err:XQST0076", "type" : "xs:QName", "description" : " It is a static error if a \\c collation subclause in an order by clause\n of a FLWOR expression does not identify a collation that is present in\n statically known collations.\n" }, { "name" : "err:XQST0079", "type" : "xs:QName", "description" : " It is a static error if an extension expression contains neither a\n pragma that is recognized by the implementation nor an expression\n enclosed in curly braces.\n" }, { "name" : "err:XQST0085", "type" : "xs:QName", "description" : " It is a static error if the namespace URI in a namespace declaration\n attribute is a zero-length string, and the implementation does not\n support [XML Names 1.1].\n" }, { "name" : "err:XQST0087", "type" : "xs:QName", "description" : " It is a static error if the encoding specified in a Version Declaration\n does not conform to the definition of \\c EncName specified in [XML 1.0]\n" }, { "name" : "err:XQST0088", "type" : "xs:QName", "description" : " It is a static error if the literal that specifies the target namespace\n in a module import or a module declaration is of zero length.\n" }, { "name" : "err:XQST0089", "type" : "xs:QName", "description" : " It is a static error if a variable bound in a \\c for or \\c window clause\n of a FLWOR expression, and its associated positional variable, do not\n have distinct names (expanded QNames).\n" }, { "name" : "err:XQST0090", "type" : "xs:QName", "description" : " It is a static error if a character reference does not identify a valid\n character in the version of XML that is in use.\n" }, { "name" : "err:XQST0093", "type" : "xs:QName", "description" : " It is a static error to import a module M1 if there exists a sequence of\n modules M1 ... Mi ... M1 such that each module directly depends on the\n next module in the sequence (informally, if M1 depends on itself through\n some chain of module dependencies.)\n" }, { "name" : "err:XQST0094", "type" : "xs:QName", "description" : " In the group by clause of a FLWOR expression, it is a static error if the\n name of a grouping variable is not equal (by the eq operator on expanded\n QNames) to the name of a variable that is bound by a for or let clause\n that precedes the group by clause.\n" }, { "name" : "err:XQST0097", "type" : "xs:QName", "description" : " It is a static error for a decimal-format to specify a value that is\n not valid for a given property.\n" }, { "name" : "err:NS", "type" : "item()*", "description" : "" }, { "name" : "err:XQST0099", "type" : "xs:QName", "description" : " If a module contains more than one context item declaration, a static error is raised [err:XQST0099].\n" }, { "name" : "err:XQST0103", "type" : "xs:QName", "description" : " All variables in a window clause must have distinct names.\n" }, { "name" : "err:XQST0106", "type" : "xs:QName", "description" : " It is a static error if a function's annotations contain more than one\n annotation named \\c private or \\c public. It is a static error if a\n function's annotations contain more than one annotation named \\c\n deterministic or \\c nondeterministic.\n" }, { "name" : "err:XQST0111", "type" : "xs:QName", "description" : " It is a static error for a query prolog to contain two decimal formats\n with the same name, or to contain two default decimal formats.\n" }, { "name" : "err:XQST0113", "type" : "xs:QName", "description" : " Specifying a VarValue or VarDefaultValue for a context item declaration\n in a library module is a static error.\n" }, { "name" : "err:XQST0114", "type" : "xs:QName", "description" : " It is a static error for a decimal format declaration to define the\n same property more than once.\n" }, { "name" : "err:XQST0116", "type" : "xs:QName", "description" : " It is a static error if a variable declaration contains both a %private\n and a %public annotation, more than one %private annotation, or more\n than one %public annotation.\n" }, { "name" : "err:XQST0120", "type" : "xs:QName", "description" : " It is a static error if a feature required by require-feature is not\n supported by the implementation.\n" }, { "name" : "err:XQST0122", "type" : "xs:QName", "description" : " It is a static error if the name of a feature in require-feature or\n prohibit-feature is not in the lexical space of QName.\n" }, { "name" : "err:XQST0123", "type" : "xs:QName", "description" : " It is a static error if the name of a feature in require-feature is not\n recognized by the implementation.\n" }, { "name" : "err:XQST0126", "type" : "xs:QName", "description" : " It is a static error if all-extensions appears in a require-feature option declaration.\n" } ] }, "http://zorba.io/modules/excel/math" : { "ns" : "http://zorba.io/modules/excel/math", "description" : " This is a library module offering a part of the set of functions\n defined by Microsoft Excel 2003.\n", "sees" : [ "Excel 2003 Documentation: Math Functions" ], "authors" : [ "Daniel Turcanu" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/excel/math", "prefix" : "excel" }, { "uri" : "http://zorba.io/modules/excel/errors", "prefix" : "excel-err" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "abs", "qname" : "excel:abs", "signature" : "($arg as xs:anyAtomicType) as xs:anyAtomicType", "description" : " Compute the abs of a numeric value.\n The value can also be a string and it will be casted to the appropriate numeric first.\n", "summary" : "

    Compute the abs of a numeric value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The parameter can be a number, string, boolean value.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The abs value as a numeric type." }, "errors" : [ "excel-err:Value if arg cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 1, "name" : "cast-as-numeric", "qname" : "excel:cast-as-numeric", "signature" : "($number as xs:anyAtomicType) as xs:anyAtomicType", "description" : " Cast the xs:anyAtomicType to a numeric type.\n If the value is already of a numeric type then nothing is changed.\n Otherwise the value is casted to the numeric type that is most appropriate.\n", "summary" : "

    Cast the xs:anyAtomicType to a numeric type.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The parameter can be a number, string, boolean value.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The casted value." }, "errors" : [ "excel-err:Value if the value cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 2, "name" : "ceiling", "qname" : "excel:ceiling", "signature" : "($number as xs:anyAtomicType, $significance as xs:anyAtomicType) as xs:anyAtomicType", "description" : " Returns number rounded up, away from zero, to the nearest multiple of significance.\n Significance must have the same sign as number.\n Number and significance must be of a numeric type or castable to numeric.\n Significance must not be zero.\n", "summary" : "

    Returns number rounded up, away from zero, to the nearest multiple of significance.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The value you want to round.
    " }, { "name" : "significance", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The multiple to which you want to round.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The rounded value." }, "errors" : [ "excel-err:Value if parameters cannot be casted to numeric type.", "excel-err:Num if significance is zero or it doesn't have the same sign as number." ] }, { "isDocumented" : true, "arity" : 1, "name" : "degrees", "qname" : "excel:degrees", "signature" : "($radian as xs:double) as xs:integer", "description" : " Converts radians into degrees.\n", "summary" : "

    Converts radians into degrees.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "radian", "type" : "xs:double", "occurrence" : null, "description" : "
    The value in radians.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The value in degrees 0 .. 360 or 0 .. -360." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "even", "qname" : "excel:even", "signature" : "($number as xs:anyAtomicType) as xs:anyAtomicType", "description" : " Returns number rounded up to the nearest even integer.\n Regardless of the sign of number, a value is rounded up when adjusted away from zero.\n", "summary" : "

    Returns number rounded up to the nearest even integer.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The value to round.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The rounded value casted as numeric type." }, "errors" : [ "excel-err:Value if parameters cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 1, "name" : "fact", "qname" : "excel:fact", "signature" : "($number as xs:anyAtomicType) as xs:integer", "description" : " Returns the factorial of a number.\n", "summary" : "

    Returns the factorial of a number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The nonnegative number you want the factorial of. If number is not an integer, it is truncated.
    " } ], "returns" : { "type" : "xs:integer", "description" : "Returns the factorial of a number. The factorial of a number is equal to 1*2*3*...* number." }, "errors" : [ "excel-err:Num if the number is smaller than zero" ] }, { "isDocumented" : true, "arity" : 1, "name" : "factdouble", "qname" : "excel:factdouble", "signature" : "($number as xs:integer) as xs:integer", "description" : " Returns the double factorial of a number.\n Computes the double factorial of n as n(n-2)(n-4)...\n", "summary" : "

    Returns the double factorial of a number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:integer", "occurrence" : null, "description" : "
    The positive integer value.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The result as integer." }, "errors" : [ "excel-err:Num if the number is negative." ] }, { "isDocumented" : true, "arity" : 2, "name" : "floor", "qname" : "excel:floor", "signature" : "($number as xs:anyAtomicType, $significance as xs:anyAtomicType) as xs:anyAtomicType", "description" : " Rounds number down, toward zero, to the nearest multiple of significance.\n Significance must have the same sign as number.\n", "summary" : "

    Rounds number down, toward zero, to the nearest multiple of significance.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The value you want to round. The value is casted to numeric.
    " }, { "name" : "significance", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The multiple to which you want to round.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The rounded value as numeric type." }, "errors" : [ "excel-err:Value if parameters cannot be casted to numeric type.", "excel-err:Num if significance is zero or it doesn't have the same sign as number." ] }, { "isDocumented" : true, "arity" : 1, "name" : "gcd", "qname" : "excel:gcd", "signature" : "($numbers as xs:integer+) as xs:integer", "description" : " Returns the greatest common divisor GCD of a sequence of integers.\n The sequence can have one or more positive integers.\n", "summary" : "

    Returns the greatest common divisor GCD of a sequence of integers.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:integer", "occurrence" : "+", "description" : "
    The sequence of positive integers.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The GCD as integer." }, "errors" : [ "excel-err:Num if any number is smaller than zero." ] }, { "isDocumented" : true, "arity" : 1, "name" : "int", "qname" : "excel:int", "signature" : "($number as xs:anyAtomicType) as xs:integer", "description" : " Rounds a number down to the nearest integer.\n Positive numbers are rounded toward zero, negative numbers are rounded away from zero.\n", "summary" : "

    Rounds a number down to the nearest integer.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The value to be rounded.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The rounded integer." }, "errors" : [ "excel-err:Value if parameter cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-a-number", "qname" : "excel:is-a-number", "signature" : "($value as xs:anyAtomicType) as xs:boolean", "description" : " Checks if the xs:anyAtomicType argument is actually a numeric type\n or can be converted to numeric.\n", "summary" : "

    Checks if the xs:anyAtomicType argument is actually a numeric type\n or can be converted to numeric.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    Parameter to be checked.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the value can be casted to numeric." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "lcm", "qname" : "excel:lcm", "signature" : "($numbers as xs:integer+) as xs:integer", "description" : " Returns the least common multiple of integers.

    \n LCM for two numbers is computed by multiplying them and dividing with GCD.

    \n The function is applied recursively replacing the first two numbers in the sequence with their LCM.\n", "summary" : "

    Returns the least common multiple of integers.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:integer", "occurrence" : "+", "description" : "
    The sequence of one or more positive integers.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The LCM as integer." }, "errors" : [ "excel-err:Num if any number is smaller than zero." ] }, { "isDocumented" : true, "arity" : 2, "name" : "mod", "qname" : "excel:mod", "signature" : "($number as xs:anyAtomicType, $divisor as xs:anyAtomicType) as xs:anyAtomicType", "description" : " Returns the remainder after number is divided by divisor.\n The result has the same sign as divisor.\n", "summary" : "

    Returns the remainder after number is divided by divisor.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The number for which you want to find the remainder.
    " }, { "name" : "divisor", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The number by which you want to divide number. This cannot be zero.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The remainder from division as numeric type." }, "errors" : [ "excel-err:Value if parameters cannot be casted to numeric type.", "excel-err:Div0 if divisor is zero after casting to numeric." ] }, { "isDocumented" : true, "arity" : 2, "name" : "mround", "qname" : "excel:mround", "signature" : "($number as xs:anyAtomicType, $multiple as xs:anyAtomicType) as xs:anyAtomicType", "description" : " Returns a number rounded to the desired multiple.\n MROUND rounds up, away from zero, if the remainder of dividing number by multiple\n is greater than or equal to half the value of multiple.\n MROUND is computed through floor function.\n", "summary" : "

    Returns a number rounded to the desired multiple.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The value to round, castable to numeric type.
    " }, { "name" : "multiple", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The multiple to which you want to round number.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The rounded number up to the desired multiple." }, "errors" : [ "excel-err:Value if parameters cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 1, "name" : "odd", "qname" : "excel:odd", "signature" : "($number as xs:anyAtomicType) as xs:integer", "description" : " Returns number rounded up to the nearest odd integer, away from zero.\n", "summary" : "

    Returns number rounded up to the nearest odd integer, away from zero.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The value to round.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The odd integer." }, "errors" : [ "excel-err:Value if parameter cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 0, "name" : "pi", "qname" : "excel:pi", "signature" : "() as xs:decimal", "description" : " Return the value of PI as decimal with 15 digits.\n", "summary" : "

    Return the value of PI as decimal with 15 digits.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:decimal", "description" : "The value of PI with 15 digits." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "power", "qname" : "excel:power", "signature" : "($number as xs:anyAtomicType, $power as xs:integer) as xs:anyAtomicType", "description" : " Returns the result of a number raised to a power.\n The result is computed through successive multiplications.\n", "summary" : "

    Returns the result of a number raised to a power.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The base number.
    " }, { "name" : "power", "type" : "xs:integer", "occurrence" : null, "description" : "
    The exponent as integer (cannot be floating point like in Excel).
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The result as numeric type." }, "errors" : [ "excel-err:Value if parameter cannot be casted to numeric type.", "excel-err:Value if power is smaller than zero." ] }, { "isDocumented" : true, "arity" : 1, "name" : "product", "qname" : "excel:product", "signature" : "($numbers as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies all the numbers given as arguments and returns the product.\n", "summary" : "

    Multiplies all the numbers given as arguments and returns the product.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The sequence of arguments convertable to numeric types. The sequence can be of any length.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The multiplication result as numeric type." }, "errors" : [ "excel-err:Value if parameters cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 2, "name" : "quotient", "qname" : "excel:quotient", "signature" : "($numerator as xs:anyAtomicType, $denominator as xs:anyAtomicType) as xs:integer", "description" : " Returns the integer portion of a division.\n", "summary" : "

    Returns the integer portion of a division.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numerator", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The divident.
    " }, { "name" : "denominator", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The divisor. It cannot be zero.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The result value as numeric type." }, "errors" : [ "excel-err:Value if parameters cannot be casted to numeric type.", "excel-err:Div0 if denominator casted as numeric type has value zero." ] }, { "isDocumented" : true, "arity" : 1, "name" : "radians", "qname" : "excel:radians", "signature" : "($degree as xs:integer) as xs:decimal", "description" : " Converts degrees to radians.\n", "summary" : "

    Converts degrees to radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "degree", "type" : "xs:integer", "occurrence" : null, "description" : "
    An angle in degrees that you want to convert.
    " } ], "returns" : { "type" : "xs:decimal", "description" : "The value in radians." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "roman", "qname" : "excel:roman", "signature" : "($number as xs:integer) as xs:string", "description" : " Converts an arabic numeral to roman, as text.\n Only the clasic format is supported (out of all formats Excel requires).

    \n M is the largest digit, it represents 1000.\n Numbers bigger than 2000 will be represented by a sequence of \"M\".

    \n D = 500, C = 100, L = 50, X = 10, V = 5, I = 1.\n", "summary" : "

    Converts an arabic numeral to roman, as text.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:integer", "occurrence" : null, "description" : "
    A positive integer.
    " } ], "returns" : { "type" : "xs:string", "description" : "The roman string representation." }, "errors" : [ "excel-err:Num if the input integer is negative" ] }, { "isDocumented" : true, "arity" : 2, "name" : "round", "qname" : "excel:round", "signature" : "($number as xs:anyAtomicType, $precision as xs:integer) as xs:anyAtomicType", "description" : " Rounds a number to a specified number of digits.\n If precision is greater than 0 (zero), then number is rounded\n to the specified number of decimal places.\n If num_digits is 0, then number is rounded to the nearest integer.\n If num_digits is less than 0, then number is rounded to the left of the decimal point.\n The 0.5 is rounded away from zero.\n", "summary" : "

    Rounds a number to a specified number of digits.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The number to round, castable to a numeric type.
    " }, { "name" : "precision", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of decimal places to keep.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The rounded number as numeric type." }, "errors" : [ "excel-err:Value if parameters cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 2, "name" : "rounddown", "qname" : "excel:rounddown", "signature" : "($number as xs:anyAtomicType, $precision as xs:integer) as xs:anyAtomicType", "description" : " Rounds a number down, toward zero.\n If num_digits is greater than 0 (zero), then number is rounded down\n to the specified number of decimal places.\n If num_digits is 0, then number is rounded down to the nearest integer.\n If num_digits is less than 0, then number is rounded down to the left of the decimal point.\n", "summary" : "

    Rounds a number down, toward zero.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The number to round, castable to numeric type.
    " }, { "name" : "precision", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of decimal places to keep.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the truncated number toward zero, as numeric type." }, "errors" : [ "excel-err:Value if parameters cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 2, "name" : "roundup", "qname" : "excel:roundup", "signature" : "($number as xs:anyAtomicType, $precision as xs:integer) as xs:anyAtomicType", "description" : " Rounds a number up, away from 0 (zero).\n If num_digits is greater than 0 (zero), then number is rounded down\n to the specified number of decimal places.\n If num_digits is 0, then number is rounded down to the nearest integer.\n If num_digits is less than 0, then number is rounded down to the left of the decimal point.\n", "summary" : "

    Rounds a number up, away from 0 (zero).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The number to round, castable to numeric type.
    " }, { "name" : "precision", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of decimal places to keep.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The truncated number away from zero, as numeric type." }, "errors" : [ "excel-err:Value if parameters cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 1, "name" : "sign", "qname" : "excel:sign", "signature" : "($number as xs:anyAtomicType) as xs:integer", "description" : " Determines the sign of a number.\n Returns 1 if the number is positive, zero (0) if the number is 0,\n and -1 if the number is negative.\n", "summary" : "

    Determines the sign of a number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The argument castable to numeric type.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The sign as (-1, 0, 1)." }, "errors" : [ "excel-err:Value if parameters cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 1, "name" : "sort-numbers", "qname" : "excel:sort-numbers", "signature" : "($numbers as xs:anyAtomicType*) as xs:anyAtomicType*", "description" : " Helper function.

    \n Sorts a sequence of numbers or arguments castable to numeric.\n It first casts all arguments to numeric and then sorts ascending.\n", "summary" : "

    Helper function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The sequence of arguments castable to numeric.
    " } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "The sorted sequence as numeric types." }, "errors" : [ "excel-err:Value if parameters cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 1, "name" : "sum", "qname" : "excel:sum", "signature" : "($numbers as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Adds all the numbers in the sequence.\n", "summary" : "

    Adds all the numbers in the sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The sequence of arguments castable to numeric types. The sequence can be of any length.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The sum as numeric type." }, "errors" : [ "excel-err:Value if parameters cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 1, "name" : "trunc", "qname" : "excel:trunc", "signature" : "($number as xs:anyAtomicType) as xs:integer", "description" : " Truncates a number to an integer by removing the fractional part of the number.\n", "summary" : "

    Truncates a number to an integer by removing the fractional part of the number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The argument castable to numeric type.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The integer value." }, "errors" : [ "excel-err:Value if parameter cannot be casted to numeric type." ] }, { "isDocumented" : true, "arity" : 2, "name" : "trunc", "qname" : "excel:trunc", "signature" : "($number as xs:anyAtomicType, $precision as xs:integer) as xs:anyAtomicType", "description" : " Truncates a number down to precision.\n This behaves exactly like rounddown.\n", "summary" : "

    Truncates a number down to precision.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The argument castable to numeric type.
    " }, { "name" : "precision", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of decimal places to keep .
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The integer value." }, "errors" : [ "excel-err:Value if parameter cannot be casted to numeric type." ] } ], "variables" : [ ] }, "http://api.28.io/browserview" : { "ns" : "http://api.28.io/browserview", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://api.28.io/browserview", "prefix" : "browserview" }, { "uri" : "http://api.28.io/model", "prefix" : "model" }, { "uri" : "http://zorba.io/modules/reference", "prefix" : "ref" } ], "functions" : [ { "isDocumented" : false, "arity" : 1, "name" : "node-path", "qname" : "browserview:node-path", "signature" : "($node)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "node-reference", "qname" : "browserview:node-reference", "signature" : "($node, $short as xs:boolean)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "short", "type" : "xs:boolean", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "serialize", "qname" : "browserview:serialize", "signature" : "($json)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "json", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "serializeMulti", "qname" : "browserview:serializeMulti", "signature" : "($json)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "json", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "show-namespaces", "qname" : "browserview:show-namespaces", "signature" : "($namespaces)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "show-node", "qname" : "browserview:show-node", "signature" : "($node, $namespaces, $short as xs:boolean)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "node", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "short", "type" : "xs:boolean", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "show-nodes", "qname" : "browserview:show-nodes", "signature" : "($nodes)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/json-csv" : { "ns" : "http://zorba.io/modules/json-csv", "description" : " This module provides an API for parsing and serializing CSV (comma-separated\n values) files.\n See RFC 4180,\n \"Common Format and MIME Type for Comma-Separated Values (CSV) Files.\"\n", "sees" : [ ], "authors" : [ "Paul J. Lucas" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/json-csv", "prefix" : "csv" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "parse", "qname" : "csv:parse", "signature" : "($csv as string) as object()*", "description" : " Parses a CSV (comma-separated values) string using the default options.\n A newline (U+000A), optionally preceeded by a carriage-return (U+000D),\n terminates lines, aka, \"records.\"\n

    \n Quoted values are always considered strings;\n unquoted values are attempted to be cast to other types, e.g., integer\n (unless the cast-unquoted-values option is false).\n Casting is attempted in the following order:\n integer, decimal, double, and boolean.\n If casting fails, the value is considered a string.\n Header field names are always considered strings even if unquoted.\n

    \n In addition to the \"normal\" values of\n true and false for boolean,\n T and Y are also considered \"true\"\n and F and N are also considered \"false.\"\n

    \n The default options are:\n

    \n
    cast-unquoted-values
    \n
    \n Whether to attempt to cast unquoted values to\n integer, decimal, double, or boolean;\n default: true.\n
    \n
    extra-name
    \n
    \n The field name for extra values, if any;\n default: none (error csv:EXTRA_VALUE is raised).\n
    \n
    field-names
    \n
    \n A JSON array of strings denoting field names;\n default: none.\n The first CSV line is assumed to be a header line\n and the field names are taken from this line.\n
    \n
    missing-value
    \n
    \n What should happen when a missing value is detected;\n default: \"null\".\n A \"missing\" value is one of:\n
      \n
    • Two consecutive quote-char characters.
    • \n
    • A quote-char character as either the first\n or last character on a line.
    • \n
    • Fewer values than the number of field names.
    • \n
    \n When a missing value is detected,\n the value is set to null.\n
    \n
    quote-char
    \n
    \n The single ASCII character that may be used to quote values;\n default: \" (U+0022).\n
    \n
    quote-escape
    \n
    \n The single ASCII character used to escape quote-char;\n default: same as quote-char.\n This means that an escaped quote is doubled as \"\".\n
    \n
    separator
    \n
    \n The single ASCII character used to separate values;\n default: , (U+002C).\n
    \n
    \n", "summary" : "

    Parses a CSV (comma-separated values) string using the default options.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "csv", "type" : "string", "occurrence" : null, "description" : "
    The CSV string to parse.
    " } ], "returns" : { "type" : "object()*", "description" : "a sequence of zero or more JSON objects where each key is a field name and each value is a parsed value." }, "errors" : [ "csv:EXTRA_VALUE if an extra value is detected." ] }, { "isDocumented" : true, "arity" : 2, "name" : "parse", "qname" : "csv:parse", "signature" : "($csv as string, $options as object()) as object()* external", "description" : " Parses a CSV (comma-separated values) string using the given options.\n A newline (U+000A), optionally preceeded by a carriage-return (U+000D),\n terminates lines, aka, \"records.\"\n

    \n Quoted values are always considered strings;\n unquoted values are attempted to be cast to other types, e.g., integer\n (unless the cast-unquoted-values option is false).\n Casting is attempted in the following order:\n integer, decimal, double, and boolean.\n If casting fails, the value is considered a string.\n Header field names are always considered strings even if unquoted.\n

    \n In addition to the \"normal\" values of\n true and false for boolean,\n T and Y are also considered \"true\"\n and F and N are also considered \"false.\"\n", "summary" : "

    Parses a CSV (comma-separated values) string using the given options.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "csv", "type" : "string", "occurrence" : null, "description" : "
    The CSV string to parse.
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    The options to use:
    cast-unquoted-values
    Whether to attempt to cast unquoted values to integer, decimal, double, or boolean; default: true.
    extra-name
    The field name for extra values, if any; default: none (error csv:EXTRA_VALUE is raised). If this option is given and a line contains one or more extra values (that is, values that have no corresponding field names), then the extra values are assigned as the values for fields having extra-name as their names.

    If extra-name contains a # (U+0023), then the # is substituted with the field number (where field numbers start at 1). If extra-name does not contains a #, then the field number is appended.

    field-names
    A JSON array of strings denoting field names; default: none. If this option is given, then the first CSV line is assumed not to be a header line; if omitted, then the first CSV line is assumed to be a header line and the field names are taken from this line.
    missing-value
    What should happen when a missing value is detected; default: \"null\". A \"missing\" value is one of:
    • Two consecutive separator characters.
    • A separator character as either the first or last character on a line.
    • Fewer values than the number of field names.
    When a missing value is detected, the value of this option determines what happens:
    \"error\"
    Error csv:MISSING_VALUE is raised.
    \"omit\"
    Both the value and its key are omitted from the result object.
    \"null\"
    The value is set to null.
    quote-char
    The single ASCII character that may be used to quote values; default: \" (U+0022).
    quote-escape
    The single ASCII character used to escape quote-char; default: same as quote-char. If quote-escape equals quote-char, it means that quote-char must be doubled to escape it. If quote-escape does not equal quote-char, it means that quote-escape is used to escape quote-char. For example, a quote-char of \" (U+0022) and a quote-escape of \\ (U+005C) means that quotes will be escaped by \\\".
    separator
    The single ASCII character used to separate values; default: , (U+002C).
    " } ], "returns" : { "type" : "object()*", "description" : "a sequence of zero or more JSON objects where each key is a field name and each value is a parsed value." }, "errors" : [ "csv:INVALID_OPTION if the quote-char, quote-escape, or separator option is given and it's not a single ASCII character.", "csv:MISSING_VALUE if a missing value is detected and the missing-value option is \"error\".", "csv:EXTRA_VALUE if an extra value is detected and the extra-name option is not set." ] }, { "isDocumented" : true, "arity" : 1, "name" : "serialize", "qname" : "csv:serialize", "signature" : "($obj as object()*) as string*", "description" : " Serializes a sequence of JSON objects as CSV (comma-separated values) using\n the default options.\n The default options are:\n
    \n
    field-names
    \n
    \n A JSON array of strings denoting field names;\n default: none.\n The field names are taken from the first JSON object\n and the order of the fields is implementation dependent.\n
    \n
    serialize-boolean-as
    \n
    \n What strings to serialize true and false as;\n default: true and false.\n
    \n
    serialize-header
    \n
    \n Whether a header line is included;\n default: true.\n The first string result is the header line\n comprised of all the objects' keys' names.\n
    \n
    serialize-null-as
    \n
    \n What string to serialize JSON null values as;\n default: null.\n
    \n
    quote-char
    \n
    \n The single ASCII character that may be used to quote values;\n default: \" (U+0022).\n
    \n
    quote-escape
    \n
    \n The single ASCII character used to escape quote-char;\n default: same as quote-char.\n This means that quote-char is doubled to escape it.\n
    \n
    separator
    \n
    \n The single ASCII character used to separate values;\n default: , (U+002C).\n
    \n
    \n", "summary" : "

    Serializes a sequence of JSON objects as CSV (comma-separated values) using\n the default options.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "obj", "type" : "object()", "occurrence" : "*", "description" : "
    The sequence of JSON objects to serialize.
    " } ], "returns" : { "type" : "string*", "description" : "a sequence of strings where each string corresponds to a JSON object, aka, \"record.\"" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "serialize", "qname" : "csv:serialize", "signature" : "($obj as object()*, $options as object()) as string* external", "description" : " Serializes a sequence of JSON objects as CSV (comma-separated values) using\n the given options.\n", "summary" : "

    Serializes a sequence of JSON objects as CSV (comma-separated values) using\n the given options.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "obj", "type" : "object()", "occurrence" : "*", "description" : "
    The sequence of JSON objects to serialize.
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    The options to use:
    field-names
    A JSON array of strings denoting field names; default: none. If this option is not set, the field names are taken from the first JSON object and the order of the fields is implementation dependent. If this option is set, the fields are serielized in the order they are in the array. In either case, every JSON object must have the same keys as the first object.
    serialize-boolean-as
    What strings to serialize true and false as; default: true and false. This must be a sub-object with the two keys \"true\" and \"false\", e.g.: { \"true\" : \"Y\", \"false\" : \"N\" }.
    serialize-header
    Whether a header line is included; default: true. If true, the first string result is the header line comprised of all the objects' keys' names; if false, the heder line is not returned.
    serialize-null-as
    What string to serialize JSON null values as; default: null.
    quote-char
    The single ASCII character that may be used to quote values; default: \" (U+0022).
    quote-escape
    The single ASCII character used to escape quote-char; default: same as quote-char. If quote-escape equals quote-char, it means that quote-char must be doubled to escape it. If quote-escape does not equal quote-char, it means that quote-escape is used to escape quote-char. For example, a quote-char of \" (U+0022) and a quote-escape of \\ (U+005C) means that quotes will be escaped by \\\".
    separator
    The single ASCII character used to separate values; default: , (U+002C).
    " } ], "returns" : { "type" : "string*", "description" : "a sequence of strings where each string corresponds to a JSON object, aka, \"record.\"" }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/email/imap" : { "ns" : "http://www.zorba-xquery.com/modules/email/imap", "description" : " This module provides functions for accessing and manipulating emails on mail\n servers through the IMAP protocol.\n All functions in this module receive as the first argument the IMAP host and user\n information. This is an element with the type hostInfoType as defined\n in the email schema: http://www.zorba-xquery.com/modules/email.\n For example:\n
    \n <email:hostInfo>\n   <email:hostName>imap.example.com</email:hostName>\n   <email:userName>myuser</email:userName>\n   <email:password>mypassword</email:password>\n </email:hostInfo>\n 
    \n The hostInfoType only needs to be in the email schema namespace\n (http://www.zorba-xquery.com/modules/email). It does not need\n to be validated since it's validated by the module.\n", "sees" : [ "c-client library part of UW IMAP toolkit" ], "authors" : [ "Daniel Thomas, Gabriel Petrovay" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.zorba-xquery.com/modules/email", "prefix" : "email" }, { "uri" : "http://www.zorba-xquery.com/modules/email/imap", "prefix" : "imap" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 5, "name" : "copy", "qname" : "imap:copy", "signature" : "($host-info as element(email:hostInfo), $mailbox-from as xs:string, $mailbox-to as xs:string, $messages as xs:long+, $uid as xs:boolean?) as empty-sequence()", "description" : " Copies messages between mailboxes.\n Depending on the value of $uid, the messages are either specified\n through their sequence number or through their unique id. Both mailboxes must exist.\n", "summary" : "

    Copies messages between mailboxes.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox-from", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox in which the messages reside.
    " }, { "name" : "mailbox-to", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox in to which the messages are copied.
    " }, { "name" : "messages", "type" : "xs:long", "occurrence" : "+", "description" : "
    The messages to be copied, specified either by their sequence number or their unique id.
    " }, { "name" : "uid", "type" : "xs:boolean", "occurrence" : "?", "description" : "
    If true, $messages are treated as sequence numbers. Else as unique identifiers.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The function is declared as sequential and has side-effects. It returns the empty sequence." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 2, "name" : "create", "qname" : "imap:create", "signature" : "($host-info as element(email:hostInfo), $mailbox-name as xs:string) as empty-sequence()", "description" : " Creates a new mailbox for the given user.\n", "summary" : "

    Creates a new mailbox for the given user.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox-name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name for the new mailbox.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The function is declared as sequential and has side-effects. It returns the empty sequence." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 2, "name" : "delete", "qname" : "imap:delete", "signature" : "($host-info as element(email:hostInfo), $mailbox-name as xs:string) as empty-sequence()", "description" : " Deletes a mailbox for the given user.\n", "summary" : "

    Deletes a mailbox for the given user.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox-name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the mailbox to delete.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The function is declared as sequential and has side-effects. It returns the empty sequence." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 2, "name" : "expunge", "qname" : "imap:expunge", "signature" : "($host-info as element(email:hostInfo), $mailbox as xs:string) as empty-sequence()", "description" : " Permanently deletes all messages of the given mailbox that have the \"deleted\" flag set.\n", "summary" : "

    Permanently deletes all messages of the given mailbox that have the \"deleted\" flag set.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox for which all messages that have the \\Deleted flag set should be permanently deleted.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The function is declared as sequential and has side-effects. It returns the empty sequence." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 4, "name" : "fetch-envelope", "qname" : "imap:fetch-envelope", "signature" : "($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long, $uid as xs:boolean?) as element(email:envelope)", "description" : " Fetches the envelope of a message.\n", "summary" : "

    Fetches the envelope of a message.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox in which to search for the message.
    " }, { "name" : "message-number", "type" : "xs:long", "occurrence" : null, "description" : "
    The message for which to fetch the envelope (depending on $uid either as message sequence number or unique identifier).
    " }, { "name" : "uid", "type" : "xs:boolean", "occurrence" : "?", "description" : "
    If true, $message-number is treated as sequence number. Else as unique identifier.
    " } ], "returns" : { "type" : "element(email:envelope)", "description" : "The envelope of the requested message. The result is validated against the schema: http://www.zorba-xquery.com/modules/email." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 4, "name" : "fetch-flags", "qname" : "imap:fetch-flags", "signature" : "($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long, $uid as xs:boolean?) as element(email:flags)", "description" : " Fetches the flags of a message.\n", "summary" : "

    Fetches the flags of a message.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox containing the specified message.
    " }, { "name" : "message-number", "type" : "xs:long", "occurrence" : null, "description" : "
    Either the message sequence number or the unique identifier of the message.
    " }, { "name" : "uid", "type" : "xs:boolean", "occurrence" : "?", "description" : "
    If true, $message-number is treated as sequence number. Else as unique identifier.
    " } ], "returns" : { "type" : "element(email:flags)", "description" : "The flags of the specified message. The result is validated against the schema: http://www.zorba-xquery.com/modules/email." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 3, "name" : "fetch-from", "qname" : "imap:fetch-from", "signature" : "($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long) as xs:string", "description" : " Fetches the 'from' string of a message.\n Please note that this function only words with message sequence numbers,\n not with unique identifiers. Only the first 255 characters of a 'from'\n string are fetched.\n", "summary" : "

    Fetches the 'from' string of a message.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox for which we want to get the 'from' string of a message.
    " }, { "name" : "message-number", "type" : "xs:long", "occurrence" : null, "description" : "
    Denotes the message for which we want the 'from' string.
    " } ], "returns" : { "type" : "xs:string", "description" : "The 'from' string of the specified message." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 3, "name" : "fetch-message-sequence-number", "qname" : "imap:fetch-message-sequence-number", "signature" : "($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long) as xs:long", "description" : " Fetches the message sequence number for a given unique identifier.\n", "summary" : "

    Fetches the message sequence number for a given unique identifier.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox for which we want to get the message sequence number of an unique identifier.
    " }, { "name" : "message-number", "type" : "xs:long", "occurrence" : null, "description" : "
    The unique identifier for which we want the message sequence number.
    " } ], "returns" : { "type" : "xs:long", "description" : "The message sequence number of the of the given unique identifier." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 4, "name" : "fetch-message", "qname" : "imap:fetch-message", "signature" : "($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long, $uid as xs:boolean) as element(email:message)", "description" : " Fetches a whole message.\n", "summary" : "

    Fetches a whole message.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox in which to search for the message.
    " }, { "name" : "message-number", "type" : "xs:long", "occurrence" : null, "description" : "
    The message to fetch, denoted either by its sequence number or unique identifier.
    " }, { "name" : "uid", "type" : "xs:boolean", "occurrence" : null, "description" : "
    If true, $message-number is treated as sequence number. Else as unique identifier.
    " } ], "returns" : { "type" : "element(email:message)", "description" : "the message with the given $message-number. The result is validated against the schema: http://www.zorba-xquery.com/modules/email." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 3, "name" : "fetch-subject", "qname" : "imap:fetch-subject", "signature" : "($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long) as xs:string", "description" : " Fetches the subject for a message.\n Please note that this function only works with message sequence numbers,\n not with unique identifiers. Only the first 255 characters of a subject\n are fetched.\n", "summary" : "

    Fetches the subject for a message.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox for which we want to get the subject of a message.
    " }, { "name" : "message-number", "type" : "xs:long", "occurrence" : null, "description" : "
    Denotes the message for which we want the subject.
    " } ], "returns" : { "type" : "xs:string", "description" : "The subject of the specified message." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 3, "name" : "fetch-uid", "qname" : "imap:fetch-uid", "signature" : "($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long) as xs:long", "description" : " Fetches the unique identifier for a given message sequence number.\n", "summary" : "

    Fetches the unique identifier for a given message sequence number.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox for which we want to get the unique identifier of a message sequence number.
    " }, { "name" : "message-number", "type" : "xs:long", "occurrence" : null, "description" : "
    The message sequence number for which we want the unique identifier.
    " } ], "returns" : { "type" : "xs:long", "description" : "The unique identifier of the given message sequence number." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 4, "name" : "list", "qname" : "imap:list", "signature" : "($host-info as element(email:hostInfo), $mailbox-ref as xs:string, $pattern as xs:string, $only-subscribed as xs:boolean) as element(email:mailbox)*", "description" : " Lists IMAP folders for the specified user on the host that match the pattern.\n", "summary" : "

    Lists IMAP folders for the specified user on the host that match the pattern.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox-ref", "type" : "xs:string", "occurrence" : null, "description" : "
    is applied to pattern in an implementation dependent fashion to search for matching mailbox names.
    " }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "
    The pattern for mailboxes to look for (can include wildcards '*' and '%').
    " }, { "name" : "only-subscribed", "type" : "xs:boolean", "occurrence" : null, "description" : "
    If set true, only mailboxes are listed to which the user is subscribed.
    " } ], "returns" : { "type" : "element(email:mailbox)*", "description" : "A sequence of mailbox elements. The result elements are validated against the schema: http://www.zorba-xquery.com/modules/email." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 5, "name" : "move", "qname" : "imap:move", "signature" : "($host-info as element(email:hostInfo), $mailbox-from as xs:string, $mailbox-to as xs:string, $messages as xs:long+, $uid as xs:boolean?) as empty-sequence()", "description" : " Moves messages between mailboxes.\n Depending on the value of $uid, the messages are either specified through\n their sequence number or through their unique id. Both mailboxes must exist.\n", "summary" : "

    Moves messages between mailboxes.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox-from", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox in which the messages reside.
    " }, { "name" : "mailbox-to", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox in to which the messages should be moved.
    " }, { "name" : "messages", "type" : "xs:long", "occurrence" : "+", "description" : "
    The messages to be copied, specified either by their sequence number or their unique id.
    " }, { "name" : "uid", "type" : "xs:boolean", "occurrence" : "?", "description" : "
    If true, $messages are treated as sequence numbers. Else as unique identifiers.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The function is declared as sequential and has side-effects. It returns the empty sequence." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 3, "name" : "rename", "qname" : "imap:rename", "signature" : "($host-info as element(email:hostInfo), $mailbox-old as xs:string, $mailbox-new as xs:string) as empty-sequence()", "description" : " Renames a mailbox.\n", "summary" : "

    Renames a mailbox.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox-old", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the mailbox we want to rename.
    " }, { "name" : "mailbox-new", "type" : "xs:string", "occurrence" : null, "description" : "
    The new name for the mailbox.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The function is declared as sequential and has side-effects. It returns the empty sequence." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 4, "name" : "search", "qname" : "imap:search", "signature" : "($host-info as element(email:hostInfo), $mailbox as xs:string, $criteria as xs:string, $uid as xs:boolean?) as xs:long*", "description" : " Searches a mailbox for messages that match the given criteria.\n The criteria should be a string as defined in the RFC3501 (IMAP4rev1).\n A valid example would be: 'FROM zorba@gmail.com OR NOT SUBJECT Bug'.\n Depending on the value of $uid, the function will either\n return matching sequence numbers or unique identifiers.\n", "summary" : "

    Searches a mailbox for messages that match the given criteria.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox to search.
    " }, { "name" : "criteria", "type" : "xs:string", "occurrence" : null, "description" : "
    The searching criteria.
    " }, { "name" : "uid", "type" : "xs:boolean", "occurrence" : "?", "description" : "
    If true, the function returns the sequence of unique identifiers corresponding to the matching mails, else the corresponding sequence numbers are returned.
    " } ], "returns" : { "type" : "xs:long*", "description" : "Either the sequence of matching sequence numbers or the sequence of matching unique identifiers." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 5, "name" : "set-flags", "qname" : "imap:set-flags", "signature" : "($host-info as element(email:hostInfo), $mailbox as xs:string, $message-number as xs:long, $flags as element(email:flags), $uid as xs:boolean?) as empty-sequence()", "description" : " Sets the flags for a given message.\n The flags are set and unset according to the passed $flags.\n", "summary" : "

    Sets the flags for a given message.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox containing the specified message.
    " }, { "name" : "message-number", "type" : "xs:long", "occurrence" : null, "description" : "
    Either the message sequence number or the unique identifier of the message (depending on the value of $uid).
    " }, { "name" : "flags", "type" : "element(email:flags)", "occurrence" : null, "description" : "
    Defines which flags should be set for this message. The possibilities are \"seen\", \"deleted\", \"flagged\", \"answered\", and \"draft\". Setting all flags at once is done by passing the element: <email:flags> <email:seen/> <email:deleted/> <email:flagged/> <email:answered/> <email:draft/> </email:flags> . Setting \"flagged\" only and unsetting all other at once can be done by passing: <email:flags> <email:flagged/> </email:flags> .
    " }, { "name" : "uid", "type" : "xs:boolean", "occurrence" : "?", "description" : "
    If true, $message-number is treated as sequence number. Else as unique identifier.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The function is declared as sequential and has side-effects. It returns the empty sequence." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "imap:IMAP0003 If no message is found with the provided sequence number/unique identifier.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 2, "name" : "status", "qname" : "imap:status", "signature" : "($host-info as element(email:hostInfo), $mailbox as xs:string) as element(email:status)", "description" : " Returns the status of the given mailbox.\n The status of a mailbox contains:\n
      \n
    • messages: the number of messages in the mailbox
    • \n
    • recent: the number of messages flagged as recent
    • \n
    • unseen: the number of messages flagged as unseen
    • \n
    • uidnext: the next unique identifier that will be assigned to a message
    • \n
    • uidvalidity: a value that, together with the uidnext value\n forms a 64 bit number that must be unique for the server
    • \n
    \n", "summary" : "

    Returns the status of the given mailbox.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox for which we want to have the status.
    " } ], "returns" : { "type" : "element(email:status)", "description" : "The status of the specified $mailbox. The result is validated against the schema: http://www.zorba-xquery.com/modules/email." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 2, "name" : "subscribe", "qname" : "imap:subscribe", "signature" : "($host-info as element(email:hostInfo), $mailbox as xs:string) as empty-sequence()", "description" : " Subscribes the user to the specified mailbox.\n", "summary" : "

    Subscribes the user to the specified mailbox.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox the user wants to subscribe to.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The function is declared as sequential and has side-effects. It returns the empty sequence." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] }, { "isDocumented" : true, "arity" : 2, "name" : "unsubscribe", "qname" : "imap:unsubscribe", "signature" : "($host-info as element(email:hostInfo), $mailbox as xs:string) as empty-sequence()", "description" : " Unsubscribes the user from the specified mailbox.\n", "summary" : "

    Unsubscribes the user from the specified mailbox.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The IMAP host, user name, and password.
    " }, { "name" : "mailbox", "type" : "xs:string", "occurrence" : null, "description" : "
    The mailbox the user wants to unsubscribe from.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The function is declared as sequential and has side-effects. It returns the empty sequence." }, "errors" : [ "imap:IMAP0001 If the IMAP operation failed.", "imap:IMAP0002 If the connection to the IMAP server is refused.", "err:XQDY0027 If the value of $host-info is not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] } ], "variables" : [ ] }, "http://zorba.io/errors" : { "ns" : "http://zorba.io/errors", "description" : " This module contains one variable declaration for each diagnostic of the\n http://zorba.io/errors namespace.\n The variables serves as documentation for the errors but can also\n be used in the code. For example, one useful scenario is to compare\n an error caught in the catch clause of a try-catch expression with one of\n the variables.\n", "sees" : [ ], "authors" : [ "Carlos Lopez" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ ], "variables" : [ { "name" : "zerr:ZDST0032", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0004", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0006", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0007", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0021", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0022", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0023", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0024", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0025", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0026", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0027", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0028", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0029", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0030", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0031", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0003", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0033", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0034", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0035", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0036", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0041", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0044", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0048", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0060", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDTY0001", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDTY0010", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDTY0011", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDTY0012", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZGDB0001", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZOSE0001", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0038", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0024", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0025", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0026", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0027", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0028", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0029", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0030", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0031", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0032", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0033", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0034", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0035", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0036", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0037", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZOSE0002", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0039", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0040", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0041", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0042", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0043", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY1000", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY1001", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY1003", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY1004", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY1005", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY1006", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0001", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDST0002", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJPE0005", "type" : "item()*", "description" : "" }, { "name" : "zerr:XSST0001", "type" : "item()*", "description" : "" }, { "name" : "zerr:XSST0002", "type" : "item()*", "description" : "" }, { "name" : "zerr:XSST0003", "type" : "item()*", "description" : "" }, { "name" : "zerr:XSST0004", "type" : "item()*", "description" : "" }, { "name" : "zerr:XSST0005", "type" : "item()*", "description" : "" }, { "name" : "zerr:XSST0006", "type" : "item()*", "description" : "" }, { "name" : "zerr:XSST0007", "type" : "item()*", "description" : "" }, { "name" : "zerr:XSST0008", "type" : "item()*", "description" : "" }, { "name" : "zerr:XSST0009", "type" : "item()*", "description" : "" }, { "name" : "zerr:XSST0010", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJPE0001", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJPE0002", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJPE0003", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJPE0004", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0066", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJPE0006", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJPE0007", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJPE0008", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJPE0009", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJPE0010", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJSE0001", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJSE0002", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJSE0003", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJSE0004", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJSE0007", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJSE0008", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJSE0009", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZJ2X0001", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0012", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZOSE0003", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZOSE0004", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZOSE0005", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZOSE0006", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZOSE0007", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0001", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0002", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0003", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0004", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0007", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0008", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0009", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0010", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0011", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0023", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0013", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0015", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0016", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0020", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0021", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0030", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0040", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0041", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0045", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0050", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0055", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0060", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZSTR0065", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQD0004", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0036", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0037", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0038", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0039", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0040", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0050", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0060", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0061", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP8401", "type" : "xs:QName", "description" : " The version of the thesaurus is not the expected version.\n" }, { "name" : "zerr:ZXQP8402", "type" : "xs:QName", "description" : " The thesaurus data file's endianness does not match that of the CPU.\n" }, { "name" : "zerr:ZXQP8403", "type" : "xs:QName", "description" : " The thesaurus data contains an unexpected value.\n" }, { "name" : "zerr:ZXQD0001", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQD0002", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQD0003", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0035", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQD0005", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQD0006", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0002", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0003", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0004", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0005", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0006", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0007", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0008", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0009", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0011", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0014", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0015", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0019", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0014", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0000", "type" : "xs:QName", "description" : " An \"error\" constant for \"no error.\"\n" }, { "name" : "zerr:ZXQP0001", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0002", "type" : "xs:QName", "description" : " A Zorba programming assertion failed. If this error occurs, it is a bug\n and should be reported.\n" }, { "name" : "zerr:ZXQP0003", "type" : "xs:QName", "description" : " Something unexpected occurred in Zorba. If this error occurs, it is a\n bug and should be reported.\n" }, { "name" : "zerr:ZXQP0004", "type" : "xs:QName", "description" : " A particular XQuery feature has not been implemented by Zorba.\n" }, { "name" : "zerr:ZXQP0005", "type" : "xs:QName", "description" : " A particular XQuery feature has been implemented by Zorba, but the\n feature has not been enabled in the current build.\n" }, { "name" : "zerr:ZXQP0006", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0007", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0008", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0009", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0010", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0011", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0012", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0013", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0020", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0016", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0017", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0020", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0021", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0024", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0025", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0026", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0028", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0029", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0030", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0031", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0032", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZXQP0033", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0009", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0012", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0013", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0014", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0015", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0016", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0017", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0001", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0002", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0003", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0004", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0005", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0006", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0007", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0008", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0011", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0010", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0011", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0012", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0013", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0014", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0015", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0016", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0017", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0018", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0020", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0019", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0021", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZDDY0022", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0045", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0021", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0023", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0024", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0025", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0026", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0027", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0028", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0029", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0030", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0039", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0040", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0041", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0042", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0043", "type" : "item()*", "description" : "" }, { "name" : "zerr:NS", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0070", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0080", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZAPI0090", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0001", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0002", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0003", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0004", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0005", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0006", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0007", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0008", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0009", "type" : "item()*", "description" : "" }, { "name" : "zerr:ZCSE0010", "type" : "item()*", "description" : "" } ] }, "http://zorba.io/modules/sequence" : { "ns" : "http://zorba.io/modules/sequence", "description" : " This module provides an XQuery API to perform set operations on sequences.\n", "sees" : [ ], "authors" : [ "Paul J. Lucas" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/sequence", "prefix" : "seq" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "value-except", "qname" : "seq:value-except", "signature" : "($seq1 as xs:anyAtomicType*, $seq2 as xs:anyAtomicType*) as xs:anyAtomicType* external", "description" : " Filters the first sequence of atomic items such that they are not in the\n second sequence based on their values.\n", "summary" : "

    Filters the first sequence of atomic items such that they are not in the\n second sequence based on their values.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The first sequence.
    " }, { "name" : "seq2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The second sequence.
    " } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "a sequence only containing items from $seq1 that are not in $seq2." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "value-intersect", "qname" : "seq:value-intersect", "signature" : "($seq1 as xs:anyAtomicType*, $seq2 as xs:anyAtomicType*) as xs:anyAtomicType* external", "description" : " Performs a set intersection of two sequences of atomic items based on their\n values.\n", "summary" : "

    Performs a set intersection of two sequences of atomic items based on their\n values.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The first sequence.
    " }, { "name" : "seq2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The second sequence.
    " } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "a sequence containing only items from $seq1 that are also in $seq2." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "value-union", "qname" : "seq:value-union", "signature" : "($seq1 as xs:anyAtomicType*, $seq2 as xs:anyAtomicType*) as xs:anyAtomicType* external", "description" : " Performs a set union of two sequences of atomic items based on their values.\n", "summary" : "

    Performs a set union of two sequences of atomic items based on their values.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The first sequence.
    " }, { "name" : "seq2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The second sequence.
    " } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "a sequence containing all items from $seq1 and seq2$ but without duplicates." }, "errors" : [ ] } ], "variables" : [ ] }, "http://api.28.io/functions" : { "ns" : "http://api.28.io/functions", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://api.28.io/functions", "prefix" : "functions" }, { "uri" : "http://api.28.io/model", "prefix" : "model" }, { "uri" : "http://www.zorba-xquery.com/schemas/pul", "prefix" : "pul" }, { "uri" : "http://zorba.io/modules/reference", "prefix" : "ref" }, { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "req" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "response" }, { "uri" : "http://api.28.io/sandbox", "prefix" : "sandbox" }, { "uri" : "http://www.zorba-xquery.com/schemas/xdm", "prefix" : "xdm" } ], "functions" : [ { "isDocumented" : false, "arity" : 1, "name" : "apply-pul", "qname" : "functions:apply-pul", "signature" : "($pul)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "pul", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "collections", "qname" : "functions:collections", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "decodeURI", "qname" : "functions:decodeURI", "signature" : "($str as xs:string) as xs:anyURI", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "str", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:anyURI", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "encode-for-js", "qname" : "functions:encode-for-js", "signature" : "($str as xs:string) as xs:string", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "str", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 5, "name" : "entries", "qname" : "functions:entries", "signature" : "($collection as xs:string?, $node as xs:anyURI?, $index as xs:string?, $value as xs:string?, $format as xs:string)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "collection", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "node", "type" : "xs:anyURI", "occurrence" : "?", "description" : "" }, { "name" : "index", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "value", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "format", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "indexes", "qname" : "functions:indexes", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "key", "qname" : "functions:key", "signature" : "($collection as xs:string, $condition as xs:string, $namespaces)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "collection", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "condition", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "namesearch", "qname" : "functions:namesearch", "signature" : "($collection as xs:string, $path as xs:string, $namespaces)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "collection", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "path", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "node-to-js", "qname" : "functions:node-to-js", "signature" : "($node) as xs:string*", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "parse-namespaces", "qname" : "functions:parse-namespaces", "signature" : "($namespaces as xs:string)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "namespaces", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "pksearch", "qname" : "functions:pksearch", "signature" : "($collection as xs:string)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "collection", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "startpage", "qname" : "functions:startpage", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "strip-whitespaces", "qname" : "functions:strip-whitespaces", "signature" : "($xml)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "xml", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "tuple", "qname" : "functions:tuple", "signature" : "($collection as xs:string, $condition as xs:string, $namespaces)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "collection", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "condition", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "valuesearch", "qname" : "functions:valuesearch", "signature" : "($collection as xs:string, $path as xs:string, $namespaces)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "collection", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "path", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "xmltojs", "qname" : "functions:xmltojs", "signature" : "($content)", "description" : " Internal function. Converts the XML contents of a POST BODY to JavaScript calls that rebuild the given XML for the collection browser frontend\n", "summary" : "

    Internal function.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "content", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "JavaScript calls for collection browser frontend" }, "errors" : [ ] } ], "variables" : [ ] }, "http://xbrl.io/modules/bizql/profiles/sec/companies" : { "ns" : "http://xbrl.io/modules/bizql/profiles/sec/companies", "description" : "

    This module provides functionality for querying companies (XBRL entities)\n submitting to the SEC.

    \n

    SEC Companies are nothing else than XBRL entities. For XBRL-generic requests on\n entities, use the generic entities module.

    \n

    With this module, you can retrieve a company with its CIK (without converting\n it to an EID). You can also retrieve companies by sector, by SIC code, by types,\n by tags, by tickers.

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/archives", "prefix" : "archives" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/companies", "prefix" : "companies" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://xbrl.io/modules/bizql/entities", "prefix" : "entities" }, { "uri" : "http://www.28msec.com/modules/mongodb", "prefix" : "mongo" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/core", "prefix" : "sec" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "companies-by-types", "qname" : "companies:companies-by-types", "signature" : "($company-types as string*) as object()*", "description" : "

    Retrieves all companies whose company type matches the passed string(s).

    \n", "summary" : "

    Retrieves all companies whose company type matches the passed string(s).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "company-types", "type" : "string", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "all companies with matching company type." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "companies-for-SIC", "qname" : "companies:companies-for-SIC", "signature" : "($sic-codes as string*) as object()*", "description" : "

    Retrieves all companies whose type of business\n matches the SIC (Standard Industrial Classification) code.

    \n", "summary" : "

    Retrieves all companies whose type of business\n matches the SIC (Standard Industrial Classification) code.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "sic-codes", "type" : "string", "occurrence" : "*", "description" : "
    a sequence of SIC codes.
    " } ], "returns" : { "type" : "object()*", "description" : "all companies with one of these SIC codes." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "companies-for-sector", "qname" : "companies:companies-for-sector", "signature" : "($sectors as string*) as object()*", "description" : "

    Retrieves all companies in the given sectors.

    \n", "summary" : "

    Retrieves all companies in the given sectors.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "sectors", "type" : "string", "occurrence" : "*", "description" : "
    a sequence of sectors as strings.
    " } ], "returns" : { "type" : "object()*", "description" : "all companies in these sectors." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "companies-for-tags", "qname" : "companies:companies-for-tags", "signature" : "($tags as string*) as object()*", "description" : "

    Return all companies with any of the given tags.

    \n", "summary" : "

    Return all companies with any of the given tags.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "tags", "type" : "string", "occurrence" : "*", "description" : "
    the tags to filter.
    " } ], "returns" : { "type" : "object()*", "description" : "all companies with the given tags." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "companies-for-tickers", "qname" : "companies:companies-for-tickers", "signature" : "($tickers as string*) as object()*", "description" : "

    Return all companies with any of the given ticker symbols.

    \n

    Tickers are case insensitive

    \n", "summary" : "

    Return all companies with any of the given ticker symbols.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "tickers", "type" : "string", "occurrence" : "*", "description" : "
    the tickers to filter.
    " } ], "returns" : { "type" : "object()*", "description" : "all companies with the given tickers." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "companies", "qname" : "companies:companies", "signature" : "() as object()*", "description" : "

    Return all companies

    \n", "summary" : "

    Return all companies \n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()*", "description" : "all companies." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "companies", "qname" : "companies:companies", "signature" : "($companies-or-ids as item()*) as object()*", "description" : "

    Return the companies with the given identifiers.

    \n", "summary" : "

    Return the companies with the given identifiers.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "companies-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    the ids of the companies or the companies themselves.
    " } ], "returns" : { "type" : "object()*", "description" : "the companies with the given identifiers the empty sequence if no company was found or if the input is an empty sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "company-type", "qname" : "companies:company-type", "signature" : "($company-name as string) as string", "description" : "

    Return company type for a given company name. Company type can be one of:

    \n

    \n

      \n
    • Corporation
    • \n
    • Partnership
    • \n
    • unknown
    • \n
    \n

    \n", "summary" : "

    Return company type for a given company name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "company-name", "type" : "string", "occurrence" : null, "description" : "
    the name of a company
    " } ], "returns" : { "type" : "string", "description" : "the company type string or \"unknown\" if the type can not be inferred" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "eid", "qname" : "companies:eid", "signature" : "($companies-or-eids-or-ciks as item()*) as string*", "description" : "

    Converts the input to a normalized CIK. The input\n can be either a pure CIK without scheme, or an already\n normalized CIK, or an entity object which contains a CIK\n in its id field.

    \n", "summary" : "

    Converts the input to a normalized CIK.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "companies-or-eids-or-ciks", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "string*", "description" : "the normalized CIK." }, "errors" : [ "sec:INVALID_PARAMETER if the CIK or entity is not valid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "types", "qname" : "companies:types", "signature" : "($companies-or-ciks as item()*) as string*", "description" : "

    Retrieves the type of a company.

    \n", "summary" : "

    Retrieves the type of a company.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "companies-or-ciks", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of companies or their identifiers (CIKs).
    " } ], "returns" : { "type" : "string*", "description" : "all company types." }, "errors" : [ ] } ], "variables" : [ ] }, "http://api.28.io/collections" : { "ns" : "http://api.28.io/collections", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://api.28.io/collections", "prefix" : "cm" }, { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "req" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "resp" }, { "uri" : "http://api.28.io/util", "prefix" : "util" }, { "uri" : "http://api.28.io/validation", "prefix" : "validate" } ], "functions" : [ { "isDocumented" : false, "arity" : 1, "name" : "definition-for-dynamic-collection", "qname" : "cm:definition-for-dynamic-collection", "signature" : "($name as xs:string) as object()", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "object()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "delete-collection-property", "qname" : "cm:delete-collection-property", "signature" : "($name as xs:string, $property as xs:string) as empty-sequence()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "property", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "delete-collection", "qname" : "cm:delete-collection", "signature" : "($name) as empty-sequence()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "dispatch", "qname" : "cm:dispatch", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "get-collection-property", "qname" : "cm:get-collection-property", "signature" : "($name as xs:string, $property as xs:string)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "property", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "get-collection", "qname" : "cm:get-collection", "signature" : "($name as xs:string) as object()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "object()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "get-or-create-collection-dynamic", "qname" : "cm:get-or-create-collection-dynamic", "signature" : "($name as xs:string) as object()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "object()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "list-collections", "qname" : "cm:list-collections", "signature" : "() as array()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "array()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "metadata", "qname" : "cm:metadata", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "put-collection-property", "qname" : "cm:put-collection-property", "signature" : "($name as xs:string, $property as xs:string, $value) as empty-sequence()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "property", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "value", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "put-collection", "qname" : "cm:put-collection", "signature" : "($name as xs:string, $collection as object()) as empty-sequence()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "collection", "type" : "object()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "validate-collection", "qname" : "cm:validate-collection", "signature" : "($collection as object()) as empty-sequence()", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "collection", "type" : "object()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/excel/math-sumproduct" : { "ns" : "http://zorba.io/modules/excel/math-sumproduct", "description" : " Module implementing the sumproduct functions from Excel 2003 math library.\n There are 30 functions defined, implementing the same function\n but with 1 to 30 parameters.\n Each parameter can be a sequence of infinite length.\n", "sees" : [ "Excel 2003 Documentation: Math-sumproduct Functions" ], "authors" : [ "Daniel Turcanu" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/excel/math-sumproduct", "prefix" : "excel" }, { "uri" : "http://zorba.io/modules/excel/errors", "prefix" : "excel-err" }, { "uri" : "http://zorba.io/modules/excel/math", "prefix" : "excel-math" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Sums the values in the sequence.\n The sequence can be of any length.\n", "summary" : "

    Sums the values in the sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 10, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 11, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 12, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 13, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 14, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 15, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 16, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 17, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 18, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*, $array18 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 19, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*, $array18 as xs:anyAtomicType*, $array19 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array19", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 2, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 20, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*, $array18 as xs:anyAtomicType*, $array19 as xs:anyAtomicType*, $array20 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array19", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array20", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 21, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*, $array18 as xs:anyAtomicType*, $array19 as xs:anyAtomicType*, $array20 as xs:anyAtomicType*, $array21 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array19", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array20", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array21", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 22, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*, $array18 as xs:anyAtomicType*, $array19 as xs:anyAtomicType*, $array20 as xs:anyAtomicType*, $array21 as xs:anyAtomicType*, $array22 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array19", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array20", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array21", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array22", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 23, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*, $array18 as xs:anyAtomicType*, $array19 as xs:anyAtomicType*, $array20 as xs:anyAtomicType*, $array21 as xs:anyAtomicType*, $array22 as xs:anyAtomicType*, $array23 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array19", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array20", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array21", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array22", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array23", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 24, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*, $array18 as xs:anyAtomicType*, $array19 as xs:anyAtomicType*, $array20 as xs:anyAtomicType*, $array21 as xs:anyAtomicType*, $array22 as xs:anyAtomicType*, $array23 as xs:anyAtomicType*, $array24 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array19", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array20", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array21", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array22", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array23", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array24", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 25, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*, $array18 as xs:anyAtomicType*, $array19 as xs:anyAtomicType*, $array20 as xs:anyAtomicType*, $array21 as xs:anyAtomicType*, $array22 as xs:anyAtomicType*, $array23 as xs:anyAtomicType*, $array24 as xs:anyAtomicType*, $array25 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array19", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array20", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array21", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array22", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array23", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array24", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array25", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 26, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*, $array18 as xs:anyAtomicType*, $array19 as xs:anyAtomicType*, $array20 as xs:anyAtomicType*, $array21 as xs:anyAtomicType*, $array22 as xs:anyAtomicType*, $array23 as xs:anyAtomicType*, $array24 as xs:anyAtomicType*, $array25 as xs:anyAtomicType*, $array26 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array19", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array20", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array21", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array22", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array23", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array24", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array25", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array26", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 27, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*, $array18 as xs:anyAtomicType*, $array19 as xs:anyAtomicType*, $array20 as xs:anyAtomicType*, $array21 as xs:anyAtomicType*, $array22 as xs:anyAtomicType*, $array23 as xs:anyAtomicType*, $array24 as xs:anyAtomicType*, $array25 as xs:anyAtomicType*, $array26 as xs:anyAtomicType*, $array27 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array19", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array20", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array21", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array22", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array23", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array24", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array25", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array26", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array27", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 28, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*, $array18 as xs:anyAtomicType*, $array19 as xs:anyAtomicType*, $array20 as xs:anyAtomicType*, $array21 as xs:anyAtomicType*, $array22 as xs:anyAtomicType*, $array23 as xs:anyAtomicType*, $array24 as xs:anyAtomicType*, $array25 as xs:anyAtomicType*, $array26 as xs:anyAtomicType*, $array27 as xs:anyAtomicType*, $array28 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array19", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array20", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array21", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array22", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array23", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array24", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array25", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array26", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array27", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array28", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 29, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*, $array18 as xs:anyAtomicType*, $array19 as xs:anyAtomicType*, $array20 as xs:anyAtomicType*, $array21 as xs:anyAtomicType*, $array22 as xs:anyAtomicType*, $array23 as xs:anyAtomicType*, $array24 as xs:anyAtomicType*, $array25 as xs:anyAtomicType*, $array26 as xs:anyAtomicType*, $array27 as xs:anyAtomicType*, $array28 as xs:anyAtomicType*, $array29 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array19", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array20", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array21", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array22", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array23", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array24", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array25", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array26", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array27", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array28", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array29", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 3, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 30, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*, $array10 as xs:anyAtomicType*, $array11 as xs:anyAtomicType*, $array12 as xs:anyAtomicType*, $array13 as xs:anyAtomicType*, $array14 as xs:anyAtomicType*, $array15 as xs:anyAtomicType*, $array16 as xs:anyAtomicType*, $array17 as xs:anyAtomicType*, $array18 as xs:anyAtomicType*, $array19 as xs:anyAtomicType*, $array20 as xs:anyAtomicType*, $array21 as xs:anyAtomicType*, $array22 as xs:anyAtomicType*, $array23 as xs:anyAtomicType*, $array24 as xs:anyAtomicType*, $array25 as xs:anyAtomicType*, $array26 as xs:anyAtomicType*, $array27 as xs:anyAtomicType*, $array28 as xs:anyAtomicType*, $array29 as xs:anyAtomicType*, $array30 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array10", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array11", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array12", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array13", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array14", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array15", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array16", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array17", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array18", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array19", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array20", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array21", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array22", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array23", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array24", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array25", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array26", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array27", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array28", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array29", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array30", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 4, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 5, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 6, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 7, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 8, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 9, "name" : "sumproduct", "qname" : "excel:sumproduct", "signature" : "($array1 as xs:anyAtomicType*, $array2 as xs:anyAtomicType*, $array3 as xs:anyAtomicType*, $array4 as xs:anyAtomicType*, $array5 as xs:anyAtomicType*, $array6 as xs:anyAtomicType*, $array7 as xs:anyAtomicType*, $array8 as xs:anyAtomicType*, $array9 as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Multiplies the elements on the same position in each sequence\n and sums up the results.\n", "summary" : "

    Multiplies the elements on the same position in each sequence\n and sums up the results.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "array1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array3", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array4", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array5", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array6", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array7", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array8", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " }, { "name" : "array9", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequences of numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of products" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "sumsq", "qname" : "excel:sumsq", "signature" : "($numbers as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " Returns the sum of the squares of the arguments.\n It used the sumproduct function.\n", "summary" : "

    Returns the sum of the squares of the arguments.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of one or more numbers or arguments castable to numeric
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the sum of squared values, as numeric type" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] } ], "variables" : [ ] }, "http://zorba.io/modules/item" : { "ns" : "http://zorba.io/modules/item", "description" : " This module provides utility functions on items. For example,\n it provides a function that allows estimating the size in bytes\n that a given item allocates in memory.\n", "sees" : [ ], "authors" : [ "Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/item", "prefix" : "item" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "size", "qname" : "item:size", "signature" : "($item as item()) as xs:integer external", "description" : " Computes the size in bytes of the given item in main memory.

    \n", "summary" : "

    Computes the size in bytes of the given item in main memory.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "item", "type" : "item()", "occurrence" : null, "description" : "
    the item whose size to compute.
    " } ], "returns" : { "type" : "xs:integer", "description" : "the size allocated by the item in bytes." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/xqdoc/menu" : { "ns" : "http://www.zorba-xquery.com/modules/xqdoc/menu", "description" : " Generate navigation for XQDoc batches.\n", "sees" : [ ], "authors" : [ "William Candillon" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.zorba-xquery.com/modules/xqdoc/menu", "prefix" : "menu" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : false, "arity" : 2, "name" : "categories-as-js", "qname" : "menu:categories-as-js", "signature" : "($url-prefix as xs:string, $cats as element(*)) as xs:string", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "url-prefix", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cats", "type" : "element(*)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "categories", "qname" : "menu:categories", "signature" : "($top as element(*)) as xs:string*", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "top", "type" : "element(*)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "closed-tabs", "qname" : "menu:closed-tabs", "signature" : "($item as element(section), $url-prefix as xs:string) as element(li)*", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "item", "type" : "element(section)", "occurrence" : null, "description" : "" }, { "name" : "url-prefix", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "element(li)*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "closed-tabs", "qname" : "menu:closed-tabs", "signature" : "($item as element(*)?, $result as element(*)*, $url-prefix as xs:string) as element(li)*", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "item", "type" : "element(*)", "occurrence" : "?", "description" : "" }, { "name" : "result", "type" : "element(*)", "occurrence" : "*", "description" : "" }, { "name" : "url-prefix", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "element(li)*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "item-uri", "qname" : "menu:item-uri", "signature" : "($item as element(*)) as xs:string", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "item", "type" : "element(*)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "item-uri", "qname" : "menu:item-uri", "signature" : "($item as element(*)?, $result as xs:string*) as xs:string+", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "item", "type" : "element(*)", "occurrence" : "?", "description" : "" }, { "name" : "result", "type" : "xs:string", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:string+", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "item", "qname" : "menu:item", "signature" : "($ctx as element(*)?, $path as xs:string*) as element(*)?", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "ctx", "type" : "element(*)", "occurrence" : "?", "description" : "" }, { "name" : "path", "type" : "xs:string", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "element(*)?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "menu", "qname" : "menu:menu", "signature" : "($item as element(*), $url-prefix as xs:string)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "item", "type" : "element(*)", "occurrence" : null, "description" : "" }, { "name" : "url-prefix", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] } ], "variables" : [ { "name" : "menu:not-found", "type" : "item()*", "description" : "" } ] }, "http://zorba.io/modules/dbgp-message-handler" : { "ns" : "http://zorba.io/modules/dbgp-message-handler", "description" : " Zorba debugger module.\n", "sees" : [ ], "authors" : [ "Gabriel Petrovay" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/base64", "prefix" : "base64" }, { "uri" : "http://zorba.io/modules/dbgp-message-handler", "prefix" : "dmh" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "process", "qname" : "dmh:process", "signature" : "($message as element(*)) as xs:anyAtomicType*", "description" : " Process one message received from the Zorba debugger server.\n", "summary" : "

    Process one message received from the Zorba debugger server.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "message", "type" : "element(*)", "occurrence" : null, "description" : "
    the message.
    " } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "()." }, "errors" : [ ] } ], "variables" : [ { "name" : "dmh:debug", "type" : "xs:boolean", "description" : " Set this variale to true if you want to have mode debug information when\n an error occurs.\n" } ] }, "http://www.28msec.com/modules/ws/mailchimp" : { "ns" : "http://www.28msec.com/modules/ws/mailchimp", "description" : " Mailchimp Client Module.\n", "sees" : [ "http://apidocs.mailchimp.com" ], "authors" : [ "William Candillon {william.candillon@28msec.com}" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://expath.org/ns/http-client", "prefix" : "http-client" }, { "uri" : "http://www.28msec.com/modules/ws/mailchimp", "prefix" : "mailchimp" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://www.28msec.com/modules/xmlrpc", "prefix" : "xmlrpc" } ], "functions" : [ { "isDocumented" : true, "arity" : 3, "name" : "apikey-add", "qname" : "mailchimp:apikey-add", "signature" : "($username as xs:string, $password as xs:string, $apikey as xs:string) as item()*", "description" : " Convenience function for apikey-add#4.\n", "summary" : "

    Convenience function for apikey-add#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "username", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "password", "type" : "xs:string", "occurrence" : null, "description" : "
    Your MailChimp password
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    Any valid API Key
    " } ], "returns" : { "type" : "item()*", "description" : "A new API Key that can be immediately used." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "apikey-add", "qname" : "mailchimp:apikey-add", "signature" : "($endpoint-url as xs:string, $username as xs:string, $password as xs:string, $apikey as xs:string) as item()*", "description" : " Add an API Key to your account. We will generate a new key for you and return it.\n", "summary" : "

    Add an API Key to your account.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "username", "type" : "xs:string", "occurrence" : null, "description" : "
    Your MailChimp user name
    " }, { "name" : "password", "type" : "xs:string", "occurrence" : null, "description" : "
    Your MailChimp password
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    Any valid API Key
    " } ], "returns" : { "type" : "item()*", "description" : "A new API Key that can be immediately used." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "apikey-expire", "qname" : "mailchimp:apikey-expire", "signature" : "($username as xs:string, $password as xs:string, $apikey as xs:string) as item()*", "description" : " Convenience function for apikey-expire#4.\n", "summary" : "

    Convenience function for apikey-expire#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "username", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "password", "type" : "xs:string", "occurrence" : null, "description" : "
    Your MailChimp password
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    Any valid API Key that you wish to expire
    " } ], "returns" : { "type" : "item()*", "description" : "True if it worked, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "apikey-expire", "qname" : "mailchimp:apikey-expire", "signature" : "($endpoint-url as xs:string, $username as xs:string, $password as xs:string, $apikey as xs:string) as item()*", "description" : " Expire a Specific API Key. Note that if you expire all of your keys, just visit your API dashboard to create a new one. If you are trying to shut off access to your account for an old developer, change your MailChimp password, then expire all of the keys they had access to. Note that this takes effect immediately, so make sure you replace the keys in any working application before expiring them! Consider yourself warned...\n", "summary" : "

    Expire a Specific API Key.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "username", "type" : "xs:string", "occurrence" : null, "description" : "
    Your MailChimp user name
    " }, { "name" : "password", "type" : "xs:string", "occurrence" : null, "description" : "
    Your MailChimp password
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    Any valid API Key that you wish to expire
    " } ], "returns" : { "type" : "item()*", "description" : "True if it worked, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "apikeys", "qname" : "mailchimp:apikeys", "signature" : "($username as xs:string, $password as xs:string, $apikey as xs:string, $expired as xs:boolean) as item()*", "description" : " Convenience function for apikeys#5.\n", "summary" : "

    Convenience function for apikeys#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "username", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "password", "type" : "xs:string", "occurrence" : null, "description" : "
    Your MailChimp password
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    Any valid API Key for your account
    " }, { "name" : "expired", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional - whether or not to include expired keys, defaults to false
    " } ], "returns" : { "type" : "item()*", "description" : "An array of API keys." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "apikeys", "qname" : "mailchimp:apikeys", "signature" : "($endpoint-url as xs:string, $username as xs:string, $password as xs:string, $apikey as xs:string, $expired as xs:boolean) as item()*", "description" : " Retrieve a list of all MailChimp API Keys for this User.\n", "summary" : "

    Retrieve a list of all MailChimp API Keys for this User.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "username", "type" : "xs:string", "occurrence" : null, "description" : "
    Your MailChimp user name
    " }, { "name" : "password", "type" : "xs:string", "occurrence" : null, "description" : "
    Your MailChimp password
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    Any valid API Key for your account
    " }, { "name" : "expired", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional - whether or not to include expired keys, defaults to false
    " } ], "returns" : { "type" : "item()*", "description" : "An array of API keys." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-abuse-reports", "qname" : "mailchimp:campaign-abuse-reports", "signature" : "($apikey as xs:string, $cid as xs:string, $since as xs:integer, $start as xs:integer, $limit as xs:string) as item()*", "description" : " Convenience function for campaign-abuse-reports#6.\n", "summary" : "

    Convenience function for campaign-abuse-reports#6 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull abuse reports for (can be gathered using campaigns())
    " }, { "name" : "since", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 500, upper limit set at 1000
    " }, { "name" : "limit", "type" : "xs:string", "occurrence" : null, "description" : "
    optional pull only messages since this time - use YYYY-MM-DD HH:II:SS format in GMT
    " } ], "returns" : { "type" : "item()*", "description" : "Reports the abuse reports for this campaign" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "campaign-abuse-reports", "qname" : "mailchimp:campaign-abuse-reports", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $since as xs:integer, $start as xs:integer, $limit as xs:string) as item()*", "description" : " Get all email addresses that complained about a given campaign.\n", "summary" : "

    Get all email addresses that complained about a given campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull abuse reports for (can be gathered using campaigns())
    " }, { "name" : "since", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 500, upper limit set at 1000
    " }, { "name" : "limit", "type" : "xs:string", "occurrence" : null, "description" : "
    optional pull only messages since this time - use YYYY-MM-DD HH:II:SS format in GMT
    " } ], "returns" : { "type" : "item()*", "description" : "Reports the abuse reports for this campaign" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-advice", "qname" : "mailchimp:campaign-advice", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-advice#3.\n", "summary" : "

    Convenience function for campaign-advice#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull advice text for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "Advice on the campaign's performance" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-advice", "qname" : "mailchimp:campaign-advice", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Retrieve the text presented in our app for how a campaign performed and any advice we may have for you - best suited for display in customized reports pages.\n Note: some messages will contain HTML - clean tags as necessary.\n", "summary" : "

    Retrieve the text presented in our app for how a campaign performed and any advice we may have for you - best suited for display in customized reports pages.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull advice text for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "Advice on the campaign's performance" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-analytics", "qname" : "mailchimp:campaign-analytics", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-analytics#3.\n", "summary" : "

    Convenience function for campaign-analytics#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "Analytics we've collected for the passed campaign." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-analytics", "qname" : "mailchimp:campaign-analytics", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Retrieve the Google Analytics data we've collected for this campaign. Note, requires Google Analytics Add-on to be installed and configured.\n", "summary" : "

    Retrieve the Google Analytics data we've collected for this campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "Analytics we've collected for the passed campaign." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-bounce-message", "qname" : "mailchimp:campaign-bounce-message", "signature" : "($apikey as xs:string, $cid as xs:string, $email as xs:string) as item()*", "description" : " Convenience function for campaign-bounce-message#4.\n", "summary" : "

    Convenience function for campaign-bounce-message#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "email", "type" : "xs:string", "occurrence" : null, "description" : "
    the email address or unique id of the member to pull a bounce message for.
    " } ], "returns" : { "type" : "item()*", "description" : "The full bounce message for this email+campaign along with some extra data." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-bounce-message", "qname" : "mailchimp:campaign-bounce-message", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $email as xs:string) as item()*", "description" : " Retrieve the most recent full bounce message for a specific email address on the given campaign. Messages over 30 days old are subject to being removed.\n", "summary" : "

    Retrieve the most recent full bounce message for a specific email address on the given campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "email", "type" : "xs:string", "occurrence" : null, "description" : "
    the email address or unique id of the member to pull a bounce message for.
    " } ], "returns" : { "type" : "item()*", "description" : "The full bounce message for this email+campaign along with some extra data." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-bounce-messages", "qname" : "mailchimp:campaign-bounce-messages", "signature" : "($apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer, $since as xs:string) as item()*", "description" : " Convenience function for campaign-bounce-messages#6.\n", "summary" : "

    Convenience function for campaign-bounce-messages#6 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 25, upper limit set at 50
    " }, { "name" : "since", "type" : "xs:string", "occurrence" : null, "description" : "
    optional pull only messages since this time - use YYYY-MM-DD format in GMT (we only store the date, not the time)
    " } ], "returns" : { "type" : "item()*", "description" : "Bounces the full bounce messages for this campaign" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "campaign-bounce-messages", "qname" : "mailchimp:campaign-bounce-messages", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer, $since as xs:string) as item()*", "description" : " Retrieve the full bounce messages for the given campaign. Note that this can return very large amounts of data depending on how large the campaign was and how much cruft the bounce provider returned.\n", "summary" : "

    Retrieve the full bounce messages for the given campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 25, upper limit set at 50
    " }, { "name" : "since", "type" : "xs:string", "occurrence" : null, "description" : "
    optional pull only messages since this time - use YYYY-MM-DD format in GMT (we only store the date, not the time)
    " } ], "returns" : { "type" : "item()*", "description" : "Bounces the full bounce messages for this campaign" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-click-detail-AIM", "qname" : "mailchimp:campaign-click-detail-AIM", "signature" : "($apikey as xs:string, $cid as xs:string, $url as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Convenience function for campaign-click-detail-AIM#6.\n", "summary" : "

    Convenience function for campaign-click-detail-AIM#6 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get click stats for (can be gathered using campaigns())
    " }, { "name" : "url", "type" : "xs:string", "occurrence" : null, "description" : "
    the URL of the link that was clicked on
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "Array containing the total records matched and the specific records for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "campaign-click-detail-AIM", "qname" : "mailchimp:campaign-click-detail-AIM", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $url as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Return the list of email addresses that clicked on a given url, and how many times they clicked.\n", "summary" : "

    Return the list of email addresses that clicked on a given url, and how many times they clicked.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get click stats for (can be gathered using campaigns())
    " }, { "name" : "url", "type" : "xs:string", "occurrence" : null, "description" : "
    the URL of the link that was clicked on
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "Array containing the total records matched and the specific records for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-click-stats", "qname" : "mailchimp:campaign-click-stats", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-click-stats#3.\n", "summary" : "

    Convenience function for campaign-click-stats#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull stats for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "URLs will be keys and contain their associated statistics: clicks (number of times a specific link was clicked) and unique (number of unique people who clicked on the specific link)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-click-stats", "qname" : "mailchimp:campaign-click-stats", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Get an array of the urls being tracked, and their click counts for a given campaign.\n", "summary" : "

    Get an array of the urls being tracked, and their click counts for a given campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull stats for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "URLs will be keys and contain their associated statistics: clicks (number of times a specific link was clicked) and unique (number of unique people who clicked on the specific link)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-content", "qname" : "mailchimp:campaign-content", "signature" : "($apikey as xs:string, $cid as xs:string, $for_archive as xs:boolean) as item()*", "description" : " Convenience function for campaign-content#4.\n", "summary" : "

    Convenience function for campaign-content#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get content for (can be gathered using campaigns())
    " }, { "name" : "for_archive", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional controls whether we return the Archive version (true) or the Raw version (false), defaults to true
    " } ], "returns" : { "type" : "item()*", "description" : "Struct containing all content for the campaign" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-content", "qname" : "mailchimp:campaign-content", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $for_archive as xs:boolean) as item()*", "description" : " Get the content (both html and text) for a campaign either as it would appear in the campaign archive or as the raw, original content.\n", "summary" : "

    Get the content (both html and text) for a campaign either as it would appear in the campaign archive or as the raw, original content.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get content for (can be gathered using campaigns())
    " }, { "name" : "for_archive", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional controls whether we return the Archive version (true) or the Raw version (false), defaults to true
    " } ], "returns" : { "type" : "item()*", "description" : "Struct containing all content for the campaign" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "campaign-create", "qname" : "mailchimp:campaign-create", "signature" : "($apikey as xs:string, $type as xs:string, $options as element(array), $content as element(array), $segment_opts as element(array), $type_opts as element(array)) as item()*", "description" : " Convenience function for campaign-create#7.\n", "summary" : "

    Convenience function for campaign-create#7 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the Campaign Type to create - one of \"regular\", \"plaintext\", \"absplit\", \"rss\", \"trans\", \"auto\"
    " }, { "name" : "options", "type" : "element(array)", "occurrence" : null, "description" : "
    a hash of the standard options for this campaign. See Mailchimp API documentation for more information about the parameter structure.
    " }, { "name" : "content", "type" : "element(array)", "occurrence" : null, "description" : "
    the content for this campaign - use a struct with the following keys. See Mailchimp API documentation for more information about the parameter structure.
    " }, { "name" : "segment_opts", "type" : "element(array)", "occurrence" : null, "description" : "
    optional - if you wish to do Segmentation with this campaign this array should contain: see campaign-segment-test(). It's suggested that you test your options against campaign-segment-test(). Also, \"trans\" campaigns do not support segmentation.
    " }, { "name" : "type_opts", "type" : "element(array)", "occurrence" : null, "description" : "
    optional -
    " } ], "returns" : { "type" : "item()*", "description" : "The ID for the created campaign" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 7, "name" : "campaign-create", "qname" : "mailchimp:campaign-create", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $type as xs:string, $options as element(array), $content as element(array), $segment_opts as element(array), $type_opts as element(array)) as item()*", "description" : " Create a new draft campaign to send. You can not have more than 32,000 campaigns in your account.\n", "summary" : "

    Create a new draft campaign to send.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the Campaign Type to create - one of \"regular\", \"plaintext\", \"absplit\", \"rss\", \"trans\", \"auto\"
    " }, { "name" : "options", "type" : "element(array)", "occurrence" : null, "description" : "
    a hash of the standard options for this campaign. See Mailchimp API documentation for more information about the parameter structure.
    " }, { "name" : "content", "type" : "element(array)", "occurrence" : null, "description" : "
    the content for this campaign - use a struct with the following keys. See Mailchimp API documentation for more information about the parameter structure.
    " }, { "name" : "segment_opts", "type" : "element(array)", "occurrence" : null, "description" : "
    optional - if you wish to do Segmentation with this campaign this array should contain: see campaign-segment-test(). It's suggested that you test your options against campaign-segment-test(). Also, \"trans\" campaigns do not support segmentation.
    " }, { "name" : "type_opts", "type" : "element(array)", "occurrence" : null, "description" : "
    optional
    " } ], "returns" : { "type" : "item()*", "description" : "The ID for the created campaign" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-delete", "qname" : "mailchimp:campaign-delete", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-delete#3.\n", "summary" : "

    Convenience function for campaign-delete#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the Campaign Id to delete
    " } ], "returns" : { "type" : "item()*", "description" : "True if the delete succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-delete", "qname" : "mailchimp:campaign-delete", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Delete a campaign. Seriously, \"poof, gone!\" - be careful!.\n", "summary" : "

    Delete a campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the Campaign Id to delete
    " } ], "returns" : { "type" : "item()*", "description" : "True if the delete succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-ecomm-order-add", "qname" : "mailchimp:campaign-ecomm-order-add", "signature" : "($apikey as xs:string, $order as element(array)) as item()*", "description" : " Convenience function for campaign-ecomm-order-add#3.\n", "summary" : "

    Convenience function for campaign-ecomm-order-add#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "order", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of information pertaining to the order that has completed. Use the following keys. See Mailchimp API documentation for more information about the parameter structure.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the data is saved, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-ecomm-order-add", "qname" : "mailchimp:campaign-ecomm-order-add", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $order as element(array)) as item()*", "description" : " Attach Ecommerce Order Information to a Campaign.\n", "summary" : "

    Attach Ecommerce Order Information to a Campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "order", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of information pertaining to the order that has completed. Use the following keys. See Mailchimp API documentation for more information about the parameter structure.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the data is saved, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-ecomm-orders", "qname" : "mailchimp:campaign-ecomm-orders", "signature" : "($apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer, $since as xs:string) as item()*", "description" : " Convenience function for campaign-ecomm-orders#6.\n", "summary" : "

    Convenience function for campaign-ecomm-orders#6 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 100, upper limit set at 500
    " }, { "name" : "since", "type" : "xs:string", "occurrence" : null, "description" : "
    optional pull only messages since this time - use YYYY-MM-DD HH:II:SS format in GMT
    " } ], "returns" : { "type" : "item()*", "description" : "The total matching orders and the specific orders for the requested page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "campaign-ecomm-orders", "qname" : "mailchimp:campaign-ecomm-orders", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer, $since as xs:string) as item()*", "description" : " Retrieve the Ecommerce Orders tracked by campaign-ecomm-order-add().\n", "summary" : "

    Retrieve the Ecommerce Orders tracked by campaign-ecomm-order-add() .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 100, upper limit set at 500
    " }, { "name" : "since", "type" : "xs:string", "occurrence" : null, "description" : "
    optional pull only messages since this time - use YYYY-MM-DD HH:II:SS format in GMT
    " } ], "returns" : { "type" : "item()*", "description" : "The total matching orders and the specific orders for the requested page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-eep-url-stats", "qname" : "mailchimp:campaign-eep-url-stats", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-eep-url-stats#3.\n", "summary" : "

    Convenience function for campaign-eep-url-stats#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "Stats an array containing tweets, retweets, clicks, and referrer related to using the campaign's eepurl" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-eep-url-stats", "qname" : "mailchimp:campaign-eep-url-stats", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Retrieve the tracked eepurl mentions on Twitter.\n", "summary" : "

    Retrieve the tracked eepurl mentions on Twitter.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "Stats an array containing tweets, retweets, clicks, and referrer related to using the campaign's eepurl" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-email-domain-performance", "qname" : "mailchimp:campaign-email-domain-performance", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-email-domain-performance#3.\n", "summary" : "

    Convenience function for campaign-email-domain-performance#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull email domain performance for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "Domains email domains and their associated stats" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-email-domain-performance", "qname" : "mailchimp:campaign-email-domain-performance", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Get the top 5 performing email domains for this campaign. Users want more than 5 should use campaign campaign-email-stats-AIM() or campaign-email-stats-AIM-all() and generate any additional stats they require.\n", "summary" : "

    Get the top 5 performing email domains for this campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull email domain performance for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "Domains email domains and their associated stats" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-email-stats-AIM-all", "qname" : "mailchimp:campaign-email-stats-AIM-all", "signature" : "($apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Convenience function for campaign-email-stats-AIM-all#5.\n", "summary" : "

    Convenience function for campaign-email-stats-AIM-all#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get stats for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 100, upper limit set at 1000
    " } ], "returns" : { "type" : "item()*", "description" : "Array containing a total record count and data including the actions (opens and clicks) for each email, with timestamps" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-email-stats-AIM-all", "qname" : "mailchimp:campaign-email-stats-AIM-all", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Given a campaign and correct paging limits, return the entire click and open history with timestamps, ordered by time, for every user a campaign was delivered to.\n", "summary" : "

    Given a campaign and correct paging limits, return the entire click and open history with timestamps, ordered by time, for every user a campaign was delivered to.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get stats for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 100, upper limit set at 1000
    " } ], "returns" : { "type" : "item()*", "description" : "Array containing a total record count and data including the actions (opens and clicks) for each email, with timestamps" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-email-stats-AIM", "qname" : "mailchimp:campaign-email-stats-AIM", "signature" : "($apikey as xs:string, $cid as xs:string, $email_address as element(array)) as item()*", "description" : " Convenience function for campaign-email-stats-AIM#4.\n", "summary" : "

    Convenience function for campaign-email-stats-AIM#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get stats for (can be gathered using campaigns())
    " }, { "name" : "email_address", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of up to 50 email addresses to check OR the email \"id\" returned from listMemberInfo, Webhooks, and Campaigns. For backwards compatibility, if a string is passed, it will be treated as an array with a single element (will not work with XML-RPC).
    " } ], "returns" : { "type" : "item()*", "description" : "Array an array with the keys listed in Returned Fields below" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-email-stats-AIM", "qname" : "mailchimp:campaign-email-stats-AIM", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $email_address as element(array)) as item()*", "description" : " Given a campaign and email address, return the entire click and open history with timestamps, ordered by time.\n", "summary" : "

    Given a campaign and email address, return the entire click and open history with timestamps, ordered by time.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get stats for (can be gathered using campaigns())
    " }, { "name" : "email_address", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of up to 50 email addresses to check OR the email \"id\" returned from listMemberInfo, Webhooks, and Campaigns. For backwards compatibility, if a string is passed, it will be treated as an array with a single element (will not work with XML-RPC).
    " } ], "returns" : { "type" : "item()*", "description" : "Array an array with the keys listed in Returned Fields below" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-geo-opens-for-country", "qname" : "mailchimp:campaign-geo-opens-for-country", "signature" : "($apikey as xs:string, $cid as xs:string, $code as xs:string) as item()*", "description" : " Convenience function for campaign-geo-opens-for-country#4.\n", "summary" : "

    Convenience function for campaign-geo-opens-for-country#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "code", "type" : "xs:string", "occurrence" : null, "description" : "
    An ISO3166 2 digit country code
    " } ], "returns" : { "type" : "item()*", "description" : "Regions an array of regions within the provided country where opens occurred." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-geo-opens-for-country", "qname" : "mailchimp:campaign-geo-opens-for-country", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $code as xs:string) as item()*", "description" : " Retrieve the regions and number of opens tracked for a certain country. Email address are not returned.\n", "summary" : "

    Retrieve the regions and number of opens tracked for a certain country.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "code", "type" : "xs:string", "occurrence" : null, "description" : "
    An ISO3166 2 digit country code
    " } ], "returns" : { "type" : "item()*", "description" : "Regions an array of regions within the provided country where opens occurred." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-geo-opens", "qname" : "mailchimp:campaign-geo-opens", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-geo-opens#3.\n", "summary" : "

    Convenience function for campaign-geo-opens#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "Countries an array of countries where opens occurred" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-geo-opens", "qname" : "mailchimp:campaign-geo-opens", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Retrieve the countries and number of opens tracked for each. Email address are not returned.\n", "summary" : "

    Retrieve the countries and number of opens tracked for each.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "Countries an array of countries where opens occurred" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-hard-bounces", "qname" : "mailchimp:campaign-hard-bounces", "signature" : "($apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Convenience function for campaign-hard-bounces#5.\n", "summary" : "

    Convenience function for campaign-hard-bounces#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "array a total of all hard bounced emails and the specific emails for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-hard-bounces", "qname" : "mailchimp:campaign-hard-bounces", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " DEPRECATED Get all email addresses with Hard Bounces for a given campaign the email address that bounced.\n", "summary" : "

    DEPRECATED Get all email addresses with Hard Bounces for a given campaign the email address that bounced.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "array a total of all hard bounced emails and the specific emails for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-members", "qname" : "mailchimp:campaign-members", "signature" : "($apikey as xs:string, $cid as xs:string, $status as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Convenience function for campaign-members#6.\n", "summary" : "

    Convenience function for campaign-members#6 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull members for (can be gathered using campaigns())
    " }, { "name" : "status", "type" : "xs:string", "occurrence" : null, "description" : "
    optional the status to pull - one of 'sent', 'hard' (bounce), or 'soft' (bounce). By default, all records are returned
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "A total of all matching emails and the specific emails for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "campaign-members", "qname" : "mailchimp:campaign-members", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $status as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Get all email addresses the campaign was successfully sent to (ie, no bounces).\n", "summary" : "

    Get all email addresses the campaign was successfully sent to (ie, no bounces).

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull members for (can be gathered using campaigns())
    " }, { "name" : "status", "type" : "xs:string", "occurrence" : null, "description" : "
    optional the status to pull - one of 'sent', 'hard' (bounce), or 'soft' (bounce). By default, all records are returned
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "A total of all matching emails and the specific emails for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-not-opened-AIM", "qname" : "mailchimp:campaign-not-opened-AIM", "signature" : "($apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Convenience function for campaign-not-opened-AIM#5.\n", "summary" : "

    Convenience function for campaign-not-opened-AIM#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get no opens for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "Array containing the total records matched and the specific records for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-not-opened-AIM", "qname" : "mailchimp:campaign-not-opened-AIM", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Retrieve the list of email addresses that did not open a given campaign string email Email address that opened the campaign.\n", "summary" : "

    Retrieve the list of email addresses that did not open a given campaign string email Email address that opened the campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get no opens for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "array array containing the total records matched and the specific records for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-opened-AIM", "qname" : "mailchimp:campaign-opened-AIM", "signature" : "($apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Convenience function for campaign-openedAIM#5.\n", "summary" : "

    Convenience function for campaign-openedAIM#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get opens for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "Array containing the total records matched and the specific records for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-opened-AIM", "qname" : "mailchimp:campaign-opened-AIM", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Retrieve the list of email addresses that opened a given campaign with how many times they opened.\n", "summary" : "

    Retrieve the list of email addresses that opened a given campaign with how many times they opened.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get opens for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "Array containing the total records matched and the specific records for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-pause", "qname" : "mailchimp:campaign-pause", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-pause#3.\n", "summary" : "

    Convenience function for campaign-pause#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the campaign to pause
    " } ], "returns" : { "type" : "item()*", "description" : "True on success" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-pause", "qname" : "mailchimp:campaign-pause", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Pause an AutoResponder or RSS campaign from sending.\n", "summary" : "

    Pause an AutoResponder or RSS campaign from sending.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the campaign to pause
    " } ], "returns" : { "type" : "item()*", "description" : "True on success" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-replicate", "qname" : "mailchimp:campaign-replicate", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-replicate#3.\n", "summary" : "

    Convenience function for campaign-replicate#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the Campaign Id to replicate
    " } ], "returns" : { "type" : "item()*", "description" : "The id of the replicated Campaign created, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-replicate", "qname" : "mailchimp:campaign-replicate", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Replicate a campaign.\n", "summary" : "

    Replicate a campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the Campaign Id to replicate
    " } ], "returns" : { "type" : "item()*", "description" : "The id of the replicated Campaign created, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-resume", "qname" : "mailchimp:campaign-resume", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-resume#3.\n", "summary" : "

    Convenience function for campaign-resume#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the campaign to pause
    " } ], "returns" : { "type" : "item()*", "description" : "True on success" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-resume", "qname" : "mailchimp:campaign-resume", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Resume sending an AutoResponder or RSS campaign.\n", "summary" : "

    Resume sending an AutoResponder or RSS campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the campaign to pause
    " } ], "returns" : { "type" : "item()*", "description" : "True on success" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-schedule", "qname" : "mailchimp:campaign-schedule", "signature" : "($apikey as xs:string, $cid as xs:string, $schedule_time as xs:string, $schedule_time_b as xs:string) as item()*", "description" : " Convenience function for campaign-schedule#5.\n", "summary" : "

    Convenience function for campaign-schedule#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the campaign to schedule
    " }, { "name" : "schedule_time", "type" : "xs:string", "occurrence" : null, "description" : "
    the time to schedule the campaign. For A/B Split \"schedule\" campaigns, the time for Group A - in YYYY-MM-DD HH:II:SS format in GMT
    " }, { "name" : "schedule_time_b", "type" : "xs:string", "occurrence" : null, "description" : "
    optional -the time to schedule Group B of an A/B Split \"schedule\" campaign - in YYYY-MM-DD HH:II:SS format in GMT
    " } ], "returns" : { "type" : "item()*", "description" : "boolean True on success" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-schedule", "qname" : "mailchimp:campaign-schedule", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $schedule_time as xs:string, $schedule_time_b as xs:string) as item()*", "description" : " Schedule a campaign to be sent in the future.\n", "summary" : "

    Schedule a campaign to be sent in the future.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the campaign to schedule
    " }, { "name" : "schedule_time", "type" : "xs:string", "occurrence" : null, "description" : "
    the time to schedule the campaign. For A/B Split \"schedule\" campaigns, the time for Group A - in YYYY-MM-DD HH:II:SS format in GMT
    " }, { "name" : "schedule_time_b", "type" : "xs:string", "occurrence" : null, "description" : "
    optional -the time to schedule Group B of an A/B Split \"schedule\" campaign - in YYYY-MM-DD HH:II:SS format in GMT
    " } ], "returns" : { "type" : "item()*", "description" : "boolean True on success" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-segment-test", "qname" : "mailchimp:campaign-segment-test", "signature" : "($apikey as xs:string, $list_id as xs:string, $options as element(array)) as item()*", "description" : " Convenience function for campaign-segment-test#4.\n", "summary" : "

    Convenience function for campaign-segment-test#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "list_id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list to test segmentation on - get lists using lists()
    " }, { "name" : "options", "type" : "element(array)", "occurrence" : null, "description" : "
    with 2 keys. See Mailchimp API documentation for more information about the parameter structure.
    " } ], "returns" : { "type" : "item()*", "description" : "The total number of subscribers matching your segmentation options" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-segment-test", "qname" : "mailchimp:campaign-segment-test", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $list_id as xs:string, $options as element(array)) as item()*", "description" : " Allows one to test their segmentation rules before creating a campaign using them.\n", "summary" : "

    Allows one to test their segmentation rules before creating a campaign using them.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "list_id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list to test segmentation on - get lists using lists()
    " }, { "name" : "options", "type" : "element(array)", "occurrence" : null, "description" : "
    with 2 keys. See Mailchimp API documentation for more information about the parameter structure.
    " } ], "returns" : { "type" : "item()*", "description" : "The total number of subscribers matching your segmentation options" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-send-now", "qname" : "mailchimp:campaign-send-now", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-send-now#3.\n", "summary" : "

    Convenience function for campaign-send-now#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the campaign to send
    " } ], "returns" : { "type" : "item()*", "description" : "True on success" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-send-now", "qname" : "mailchimp:campaign-send-now", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Send a given campaign immediately. For RSS campaigns, this will \"start\" them.\n", "summary" : "

    Send a given campaign immediately.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the campaign to send
    " } ], "returns" : { "type" : "item()*", "description" : "True on success" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-send-test", "qname" : "mailchimp:campaign-send-test", "signature" : "($apikey as xs:string, $cid as xs:string, $test_emails as element(array), $send_type as xs:string) as item()*", "description" : " Convenience function for campaign-send-test#5.\n", "summary" : "

    Convenience function for campaign-send-test#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the campaign to test
    " }, { "name" : "test_emails", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of email address to receive the test message
    " }, { "name" : "send_type", "type" : "xs:string", "occurrence" : null, "description" : "
    optional by default (null) both formats are sent - \"html\" or \"text\" send just that format
    " } ], "returns" : { "type" : "item()*", "description" : "True on success" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-send-test", "qname" : "mailchimp:campaign-send-test", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $test_emails as element(array), $send_type as xs:string) as item()*", "description" : " Send a test of this campaign to the provided email address.\n", "summary" : "

    Send a test of this campaign to the provided email address.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the campaign to test
    " }, { "name" : "test_emails", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of email address to receive the test message
    " }, { "name" : "send_type", "type" : "xs:string", "occurrence" : null, "description" : "
    optional by default (null) both formats are sent - \"html\" or \"text\" send just that format
    " } ], "returns" : { "type" : "item()*", "description" : "True on success" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-share-report", "qname" : "mailchimp:campaign-share-report", "signature" : "($apikey as xs:string, $cid as xs:string, $opts as element(array)) as item()*", "description" : " Convenience function for campaign-share-report#4.\n", "summary" : "

    Convenience function for campaign-share-report#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to share a report for (can be gathered using campaigns())
    " }, { "name" : "opts", "type" : "element(array)", "occurrence" : null, "description" : "
    s optional various parameters which can be used to configure the shared report
    " } ], "returns" : { "type" : "item()*", "description" : "Struct containing details for the shared report" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-share-report", "qname" : "mailchimp:campaign-share-report", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $opts as element(array)) as item()*", "description" : " Get the URL to a customized VIP Report for the specified campaign and optionally send an email to someone with links to it. Note subsequent calls will overwrite anything already set for the same campign (eg, the password).\n", "summary" : "

    Get the URL to a customized VIP Report for the specified campaign and optionally send an email to someone with links to it.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to share a report for (can be gathered using campaigns())
    " }, { "name" : "opts", "type" : "element(array)", "occurrence" : null, "description" : "
    s optional various parameters which can be used to configure the shared report
    " } ], "returns" : { "type" : "item()*", "description" : "Struct containing details for the shared report" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-soft-bounces", "qname" : "mailchimp:campaign-soft-bounces", "signature" : "($apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Convenience function for campaign-soft-bounces#5.\n", "summary" : "

    Convenience function for campaign-soft-bounces#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "A total of all soft bounced emails and the specific emails for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-soft-bounces", "qname" : "mailchimp:campaign-soft-bounces", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " DEPRECATED Get all email addresses with Soft Bounces for a given campaign the email address that bounced.\n", "summary" : "

    DEPRECATED Get all email addresses with Soft Bounces for a given campaign the email address that bounced.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "A total of all soft bounced emails and the specific emails for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-stats", "qname" : "mailchimp:campaign-stats", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-stats#3.\n", "summary" : "

    Convenience function for campaign-stats#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull stats for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "array struct of the statistics for this campaign" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-stats", "qname" : "mailchimp:campaign-stats", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Given a list and a campaign, get all the relevant campaign statistics (opens, bounces, clicks, etc.)\n", "summary" : "

    Given a list and a campaign, get all the relevant campaign statistics (opens, bounces, clicks, etc.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull stats for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "array struct of the statistics for this campaign" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-template-content", "qname" : "mailchimp:campaign-template-content", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-template-content#3.\n", "summary" : "

    Convenience function for campaign-template-content#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get content for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "Array containing all content section for the campaign -" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-template-content", "qname" : "mailchimp:campaign-template-content", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Get the HTML template content sections for a campaign. Note that this will return very jagged, non-standard results based on the template a campaign is using. You only want to use this if you want to allow editing template sections in your applicaton.\n", "summary" : "

    Get the HTML template content sections for a campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to get content for (can be gathered using campaigns())
    " } ], "returns" : { "type" : "item()*", "description" : "Array containing all content section for the campaign -" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaign-unschedule", "qname" : "mailchimp:campaign-unschedule", "signature" : "($apikey as xs:string, $cid as xs:string) as item()*", "description" : " Convenience function for campaign-unschedule#3.\n", "summary" : "

    Convenience function for campaign-unschedule#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the campaign to unschedule
    " } ], "returns" : { "type" : "item()*", "description" : "True on success" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaign-unschedule", "qname" : "mailchimp:campaign-unschedule", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string) as item()*", "description" : " Unschedule a campaign that is scheduled to be sent in the future.\n", "summary" : "

    Unschedule a campaign that is scheduled to be sent in the future.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the campaign to unschedule
    " } ], "returns" : { "type" : "item()*", "description" : "True on success" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-unsubscribes", "qname" : "mailchimp:campaign-unsubscribes", "signature" : "($apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Convenience function for campaign-unsubscribes#5.\n", "summary" : "

    Convenience function for campaign-unsubscribes#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "array email addresses that unsubscribed from this campaign along with reasons, if given array a total of all unsubscribed emails and the specific emails for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-unsubscribes", "qname" : "mailchimp:campaign-unsubscribes", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Get all unsubscribed email addresses for a given campaign.\n", "summary" : "

    Get all unsubscribed email addresses for a given campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the campaign id to pull bounces for (can be gathered using campaigns())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    art optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    mit optional for large data sets, the number of results to return - defaults to 1000, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "array email addresses that unsubscribed from this campaign along with reasons, if given array a total of all unsubscribed emails and the specific emails for this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaign-update", "qname" : "mailchimp:campaign-update", "signature" : "($apikey as xs:string, $cid as xs:string, $name as xs:string, $value as item()) as item()*", "description" : " Convenience function for campaign-update#5.\n", "summary" : "

    Convenience function for campaign-update#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the Campaign Id to update
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the parameter name (see campaigncreate()). For items in the options array, this will be that parameter's name (subject, from_email, etc.). Additional parameters will be that option name (content, segment_opts). \"type_opts\" will be the name of the type - rss, auto, trans, etc.
    " }, { "name" : "value", "type" : "item()", "occurrence" : null, "description" : "
    e an appropriate value for the parameter ( see campaigncreate()). For items in the options array, this will be that parameter's value. For additional parameters, this is the same value passed to them.
    " } ], "returns" : { "type" : "item()*", "description" : "boolean true if the update succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaign-update", "qname" : "mailchimp:campaign-update", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $cid as xs:string, $name as xs:string, $value as item()) as item()*", "description" : " Update just about any setting for a campaign that has not been sent. See campaigncreate() for details.\n Caveats:
    \n
      \n
    • If you set list_id, all segmentation options will be deleted and must be re-added.
    • \n
    • If you set template_id, you need to follow that up by setting it's 'content'
    • \n
    • If you set segment_opts, you should have tested your options against campaign-segment-test() as campaign-update() will not allow you to set a segment that includes no members.
    • \n
    .\n", "summary" : "

    Update just about any setting for a campaign that has not been sent.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "cid", "type" : "xs:string", "occurrence" : null, "description" : "
    the Campaign Id to update
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the parameter name ( see campaigncreate()). For items in the options array, this will be that parameter's name (subject, from_email, etc.). Additional parameters will be that option name (content, segment_opts). \"type_opts\" will be the name of the type - rss, auto, trans, etc.
    " }, { "name" : "value", "type" : "item()", "occurrence" : null, "description" : "
    An appropriate value for the parameter ( see campaigncreate()). For items in the options array, this will be that parameter's value. For additional parameters, this is the same value passed to them.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the update succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "campaigns-for-email", "qname" : "mailchimp:campaigns-for-email", "signature" : "($apikey as xs:string, $email_address as xs:string) as item()*", "description" : " Convenience function for campaigns-for-email#3.\n", "summary" : "

    Convenience function for campaigns-for-email#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "email_address", "type" : "xs:string", "occurrence" : null, "description" : "
    the email address to unsubscribe OR the email \"id\" returned from listMemberInfo, Webhooks, and Campaigns
    " } ], "returns" : { "type" : "item()*", "description" : "An array of campaign_ids the member received" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "campaigns-for-email", "qname" : "mailchimp:campaigns-for-email", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $email_address as xs:string) as item()*", "description" : " Retrieve all Campaigns Ids a member was sent.\n", "summary" : "

    Retrieve all Campaigns Ids a member was sent.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "email_address", "type" : "xs:string", "occurrence" : null, "description" : "
    the email address to unsubscribe OR the email \"id\" returned from listMemberInfo, Webhooks, and Campaigns
    " } ], "returns" : { "type" : "item()*", "description" : "An array of campaign_ids the member received" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "campaigns", "qname" : "mailchimp:campaigns", "signature" : "($apikey as xs:string, $filters as element(array), $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Convenience function for campaigns#5.\n", "summary" : "

    Convenience function for campaigns#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "filters", "type" : "element(array)", "occurrence" : null, "description" : "
    a hash of filters to apply to this query - all are optional. See Mailchimp API documentation for more information about the parameter structure.
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional - control paging of campaigns, start results at this campaign #, defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional - control paging of campaigns, number of campaigns to return with each call, defaults to 25 (max=1000)
    " } ], "returns" : { "type" : "item()*", "description" : "An array containing a count of all matching campaigns and the specific ones for the current page (see Mailchimp API documentation for more information about the return type)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "campaigns", "qname" : "mailchimp:campaigns", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $filters as element(array), $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Get the list of campaigns and their details matching the specified filters.\n", "summary" : "

    Get the list of campaigns and their details matching the specified filters.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "filters", "type" : "element(array)", "occurrence" : null, "description" : "
    a hash of filters to apply to this query - all are optional. See Mailchimp API documentation for more information about the parameter structure.
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional - control paging of campaigns, start results at this campaign #, defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional - control paging of campaigns, number of campaigns to return with each call, defaults to 25 (max=1000)
    " } ], "returns" : { "type" : "item()*", "description" : "An array containing a count of all matching campaigns and the specific ones for the current page (see Mailchimp API documentation for more information about the return type)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "chimp-chatter", "qname" : "mailchimp:chimp-chatter", "signature" : "($apikey as xs:string) as item()*", "description" : " Convenience function for chimp-chatter#2.\n", "summary" : "

    Convenience function for chimp-chatter#2 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "An array of chatter messages and properties" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "chimp-chatter", "qname" : "mailchimp:chimp-chatter", "signature" : "($endpoint-url as xs:string, $apikey as xs:string) as item()*", "description" : " Return the current Chimp Chatter messages for an account.\n", "summary" : "

    Return the current Chimp Chatter messages for an account.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " } ], "returns" : { "type" : "item()*", "description" : "An array of chatter messages and properties" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "ecomm-order-add", "qname" : "mailchimp:ecomm-order-add", "signature" : "($apikey as xs:string, $order as element(array)) as item()*", "description" : " Convenience function for ecomm-order-add#3.\n", "summary" : "

    Convenience function for ecomm-order-add#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "order", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of information pertaining to the order that has completed. Use the following keys. See Mailchimp API documentation for more information about the parameter structure.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the data is saved, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "ecomm-order-add", "qname" : "mailchimp:ecomm-order-add", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $order as element(array)) as item()*", "description" : " Import Ecommerce Order Information to be used for Segmentation.\n", "summary" : "

    Import Ecommerce Order Information to be used for Segmentation.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "order", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of information pertaining to the order that has completed. Use the following keys. See Mailchimp API documentation for more information about the parameter structure.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the data is saved, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "ecomm-order-del", "qname" : "mailchimp:ecomm-order-del", "signature" : "($apikey as xs:string, $store_id as xs:string, $order_id as xs:string) as item()*", "description" : " Convenience function for ecomm-order-del#4.\n", "summary" : "

    Convenience function for ecomm-order-del#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "store_id", "type" : "xs:string", "occurrence" : null, "description" : "
    the store id the order belongs to
    " }, { "name" : "order_id", "type" : "xs:string", "occurrence" : null, "description" : "
    the order id (generated by the store) to delete
    " } ], "returns" : { "type" : "item()*", "description" : "True if an order is deleted, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "ecomm-order-del", "qname" : "mailchimp:ecomm-order-del", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $store_id as xs:string, $order_id as xs:string) as item()*", "description" : " Delete Ecommerce Order Information used for segmentation. This will generally be used by ecommerce package plugins that we provide or by 3rd part system developers.\n", "summary" : "

    Delete Ecommerce Order Information used for segmentation.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "store_id", "type" : "xs:string", "occurrence" : null, "description" : "
    the store id the order belongs to
    " }, { "name" : "order_id", "type" : "xs:string", "occurrence" : null, "description" : "
    the order id (generated by the store) to delete
    " } ], "returns" : { "type" : "item()*", "description" : "True if an order is deleted, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "ecomm-orders", "qname" : "mailchimp:ecomm-orders", "signature" : "($apikey as xs:string, $start as xs:integer, $limit as xs:integer, $since as xs:string) as item()*", "description" : " Convenience function for ecomm-orders#5.\n", "summary" : "

    Convenience function for ecomm-orders#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 100, upper limit set at 500
    " }, { "name" : "since", "type" : "xs:string", "occurrence" : null, "description" : "
    optional pull only messages since this time - use YYYY-MM-DD HH:II:SS format in GMT
    " } ], "returns" : { "type" : "item()*", "description" : "Array the total matching orders and the specific orders for the requested page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "ecomm-orders", "qname" : "mailchimp:ecomm-orders", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $start as xs:integer, $limit as xs:integer, $since as xs:string) as item()*", "description" : " Retrieve the Ecommerce Orders for an account.\n", "summary" : "

    Retrieve the Ecommerce Orders for an account.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 100, upper limit set at 500
    " }, { "name" : "since", "type" : "xs:string", "occurrence" : null, "description" : "
    optional pull only messages since this time - use YYYY-MM-DD HH:II:SS format in GMT
    " } ], "returns" : { "type" : "item()*", "description" : "Array the total matching orders and the specific orders for the requested page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "folder-add", "qname" : "mailchimp:folder-add", "signature" : "($apikey as xs:string, $name as xs:string, $type as xs:string) as item()*", "description" : " Convenience function for folder-add#4.\n", "summary" : "

    Convenience function for folder-add#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    a unique name for a folder (max 100 bytes)
    " }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    optional the type of folder to create - either \"campaign\" or \"autoresponder\". Defaults to \"campaign\"
    " } ], "returns" : { "type" : "item()*", "description" : "The folder_id of the newly created folder." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "folder-add", "qname" : "mailchimp:folder-add", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $name as xs:string, $type as xs:string) as item()*", "description" : " Add a new folder to file campaigns or autoresponders in.\n", "summary" : "

    Add a new folder to file campaigns or autoresponders in.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    a unique name for a folder (max 100 bytes)
    " }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    optional the type of folder to create - either \"campaign\" or \"autoresponder\". Defaults to \"campaign\"
    " } ], "returns" : { "type" : "item()*", "description" : "The folder_id of the newly created folder." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "folder-del", "qname" : "mailchimp:folder-del", "signature" : "($apikey as xs:string, $fid as xs:integer, $type as xs:string) as item()*", "description" : " Convenience function for folder-del#4.\n", "summary" : "

    Convenience function for folder-del#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "fid", "type" : "xs:integer", "occurrence" : null, "description" : "
    the folder id to update - retrieve from folders()
    " }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    optional the type of folder to create - either \"campaign\" or \"autoresponder\". Defaults to \"campaign\"
    " } ], "returns" : { "type" : "item()*", "description" : "True if the delete worked, otherwise an exception is thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "folder-del", "qname" : "mailchimp:folder-del", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $fid as xs:integer, $type as xs:string) as item()*", "description" : " Delete a campaign or autoresponder folder. Note that this will simply make campaigns in the folder appear unfiled, they are not removed.\n", "summary" : "

    Delete a campaign or autoresponder folder.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "fid", "type" : "xs:integer", "occurrence" : null, "description" : "
    the folder id to update - retrieve from folders()
    " }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    optional the type of folder to create - either \"campaign\" or \"autoresponder\". Defaults to \"campaign\"
    " } ], "returns" : { "type" : "item()*", "description" : "True if the delete worked, otherwise an exception is thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "folder-update", "qname" : "mailchimp:folder-update", "signature" : "($apikey as xs:string, $fid as xs:integer, $name as xs:string, $type as xs:string) as item()*", "description" : " Convenience function for folder-update#5.\n", "summary" : "

    Convenience function for folder-update#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "fid", "type" : "xs:integer", "occurrence" : null, "description" : "
    the folder id to update - retrieve from folders()
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    a new, unique name for the folder (max 100 bytes)
    " }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    optional the type of folder to create - either \"campaign\" or \"autoresponder\". Defaults to \"campaign\"
    " } ], "returns" : { "type" : "item()*", "description" : "True if the update worked, otherwise an exception is thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "folder-update", "qname" : "mailchimp:folder-update", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $fid as xs:integer, $name as xs:string, $type as xs:string) as item()*", "description" : " Update the name of a folder for campaigns or autoresponders.\n", "summary" : "

    Update the name of a folder for campaigns or autoresponders.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "fid", "type" : "xs:integer", "occurrence" : null, "description" : "
    the folder id to update - retrieve from folders()
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    a new, unique name for the folder (max 100 bytes)
    " }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    optional the type of folder to create - either \"campaign\" or \"autoresponder\". Defaults to \"campaign\"
    " } ], "returns" : { "type" : "item()*", "description" : "True if the update worked, otherwise an exception is thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "folders", "qname" : "mailchimp:folders", "signature" : "($apikey as xs:string, $type as xs:string) as item()*", "description" : " Convenience function for folders#3.\n", "summary" : "

    Convenience function for folders#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    optional the type of folders to return - either \"campaign\" or \"autoresponder\". Defaults to \"campaign\"
    " } ], "returns" : { "type" : "item()*", "description" : "Array of folder structs (see Returned Fields for details)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "folders", "qname" : "mailchimp:folders", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $type as xs:string) as item()*", "description" : " List all the folders for a user account.\n", "summary" : "

    List all the folders for a user account.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    optional the type of folders to return - either \"campaign\" or \"autoresponder\". Defaults to \"campaign\"
    " } ], "returns" : { "type" : "item()*", "description" : "Array of folder structs (see Returned Fields for details)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "generate-text", "qname" : "mailchimp:generate-text", "signature" : "($apikey as xs:string, $type as xs:string, $content as item()) as item()*", "description" : " Convenience function for generate-text#4.\n", "summary" : "

    Convenience function for generate-text#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    The type of content to parse. Must be one of: \"html\", \"template\", \"url\", \"cid\" (Campaign Id), or \"tid\" (Template Id)
    " }, { "name" : "content", "type" : "item()", "occurrence" : null, "description" : "
    The content to use. For \"html\" expects a single string value, \"template\" expects an array like you send to campaignCreate, \"url\" expects a valid & public URL to pull from, \"cid\" expects a valid Campaign Id, and \"tid\" expects a valid Template Id on your account.
    " } ], "returns" : { "type" : "item()*", "description" : "The content pass in converted to text." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "generate-text", "qname" : "mailchimp:generate-text", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $type as xs:string, $content as item()) as item()*", "description" : " Have HTML content auto-converted to a text-only format. You can send: plain HTML, an array of Template content, an existing Campaign Id, or an existing Template Id. Note that this will not save anything to or update any of your lists, campaigns, or templates.\n", "summary" : "

    Have HTML content auto-converted to a text-only format.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    The type of content to parse. Must be one of: \"html\", \"template\", \"url\", \"cid\" (Campaign Id), or \"tid\" (Template Id)
    " }, { "name" : "content", "type" : "item()", "occurrence" : null, "description" : "
    The content to use. For \"html\" expects a single string value, \"template\" expects an array like you send to campaignCreate, \"url\" expects a valid & public URL to pull from, \"cid\" expects a valid Campaign Id, and \"tid\" expects a valid Template Id on your account.
    " } ], "returns" : { "type" : "item()*", "description" : "The content pass in converted to text." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "get-account-details", "qname" : "mailchimp:get-account-details", "signature" : "($apikey as xs:string) as item()*", "description" : " Convenience function for get-account-details#2.\n", "summary" : "

    Convenience function for get-account-details#2 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "array containing the details for the account tied to this API Key" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "get-account-details", "qname" : "mailchimp:get-account-details", "signature" : "($endpoint-url as xs:string, $apikey as xs:string) as item()*", "description" : " Retrieve lots of account information including payments made, plan info, some account stats, installed modules, contact info, and more.\n", "summary" : "

    Retrieve lots of account information including payments made, plan info, some account stats, installed modules, contact info, and more.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " } ], "returns" : { "type" : "item()*", "description" : "Array containing the details for the account tied to this API Key" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "inline-css", "qname" : "mailchimp:inline-css", "signature" : "($apikey as xs:string, $html as xs:string, $strip_css as xs:boolean) as item()*", "description" : " Convenience function for inline-css#4.\n", "summary" : "

    Convenience function for inline-css#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "html", "type" : "xs:string", "occurrence" : null, "description" : "
    Your HTML content
    " }, { "name" : "strip_css", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional Whether you want the CSS &lt;style&gt; tags stripped from the returned document. Defaults to false.
    " } ], "returns" : { "type" : "item()*", "description" : "Your HTML content with all CSS inlined, just like if we sent it." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "inline-css", "qname" : "mailchimp:inline-css", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $html as xs:string, $strip_css as xs:boolean) as item()*", "description" : " Send your HTML content to have the CSS inlined and optionally remove the original styles.\n", "summary" : "

    Send your HTML content to have the CSS inlined and optionally remove the original styles.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "html", "type" : "xs:string", "occurrence" : null, "description" : "
    Your HTML content
    " }, { "name" : "strip_css", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional Whether you want the CSS &lt;style&gt; tags stripped from the returned document. Defaults to false.
    " } ], "returns" : { "type" : "item()*", "description" : "Your HTML content with all CSS inlined, just like if we sent it." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "list-abuse-reports", "qname" : "mailchimp:list-abuse-reports", "signature" : "($apikey as xs:string, $id as xs:string, $start as xs:integer, $limit as xs:integer, $since as xs:string) as item()*", "description" : " Convenience function for list-abuse-reports#6.\n", "summary" : "

    Convenience function for list-abuse-reports#6 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to pull abuse reports for (can be gathered using lists())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 500, upper limit set at 1000
    " }, { "name" : "since", "type" : "xs:string", "occurrence" : null, "description" : "
    optional pull only messages since this time - use YYYY-MM-DD HH:II:SS format in GMT
    " } ], "returns" : { "type" : "item()*", "description" : "The total of all reports and the specific reports reports this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "list-abuse-reports", "qname" : "mailchimp:list-abuse-reports", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $start as xs:integer, $limit as xs:integer, $since as xs:string) as item()*", "description" : " Get all email addresses that complained about a given campaign.\n", "summary" : "

    Get all email addresses that complained about a given campaign.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to pull abuse reports for (can be gathered using lists())
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 500, upper limit set at 1000
    " }, { "name" : "since", "type" : "xs:string", "occurrence" : null, "description" : "
    optional pull only messages since this time - use YYYY-MM-DD HH:II:SS format in GMT
    " } ], "returns" : { "type" : "item()*", "description" : "The total of all reports and the specific reports reports this page" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-activity", "qname" : "mailchimp:list-activity", "signature" : "($apikey as xs:string, $id as xs:string) as item()*", "description" : " Convenience function for list-activity#3.\n", "summary" : "

    Convenience function for list-activity#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "Array of array of daily values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-activity", "qname" : "mailchimp:list-activity", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string) as item()*", "description" : " Access up to the previous 180 days of daily detailed aggregated activity stats for a given list.\n", "summary" : "

    Access up to the previous 180 days of daily detailed aggregated activity stats for a given list.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "array array of array of daily values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "list-batch-subscribe", "qname" : "mailchimp:list-batch-subscribe", "signature" : "($apikey as xs:string, $id as xs:string, $batch as element(array), $double_optin as xs:boolean, $update_existing as xs:boolean, $replace_interests as xs:boolean) as item()*", "description" : " Convenience function for list-batch-subscribe#7.\n", "summary" : "

    Convenience function for list-batch-subscribe#7 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "batch", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of structs for each address to import with two special keys: \"EMAIL\" for the email address, and \"EMAIL_TYPE\" for the email type option (html, text, or mobile)
    " }, { "name" : "double_optin", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to control whether to send an opt-in confirmation email - defaults to true
    " }, { "name" : "update_existing", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to control whether to update members that are already subscribed to the list or to return an error, defaults to false (return error)
    " }, { "name" : "replace_interests", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to determine whether we replace the interest groups with the updated groups provided, or we add the provided groups to the member's interest groups (optional, defaults to true)
    " } ], "returns" : { "type" : "item()*", "description" : "Array of result counts and any errors that occurred" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 7, "name" : "list-batch-subscribe", "qname" : "mailchimp:list-batch-subscribe", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $batch as element(array), $double_optin as xs:boolean, $update_existing as xs:boolean, $replace_interests as xs:boolean) as item()*", "description" : " Subscribe a batch of email addresses to a list at once. If you are using a serialized version of the API, we strongly suggest that you only run this method as a POST request, and not a GET request. Maximum batch sizes vary based on the amount of data in each record, though you should cap them at 5k - 10k records, depending on your experience. These calls are also long, so be sure you increase your timeout values.\n", "summary" : "

    Subscribe a batch of email addresses to a list at once.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "batch", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of structs for each address to import with two special keys: \"EMAIL\" for the email address, and \"EMAIL_TYPE\" for the email type option (html, text, or mobile)
    " }, { "name" : "double_optin", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to control whether to send an opt-in confirmation email - defaults to true
    " }, { "name" : "update_existing", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to control whether to update members that are already subscribed to the list or to return an error, defaults to false (return error)
    " }, { "name" : "replace_interests", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to determine whether we replace the interest groups with the updated groups provided, or we add the provided groups to the member's interest groups (optional, defaults to true)
    " } ], "returns" : { "type" : "item()*", "description" : "Array of result counts and any errors that occurred" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "list-batch-unsubscribe", "qname" : "mailchimp:list-batch-unsubscribe", "signature" : "($apikey as xs:string, $id as xs:string, $emails as element(array), $delete_member as xs:boolean, $send_goodbye as xs:boolean, $send_notify as xs:boolean) as item()*", "description" : " Convenience function for list-batch-unsubscribe#7.\n", "summary" : "

    Convenience function for list-batch-unsubscribe#7 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "emails", "type" : "element(array)", "occurrence" : null, "description" : "
    array of email addresses to unsubscribe
    " }, { "name" : "delete_member", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to completely delete the member from your list instead of just unsubscribing, default to false
    " }, { "name" : "send_goodbye", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to send the goodbye email to the email addresses, defaults to true
    " }, { "name" : "send_notify", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to send the unsubscribe notification email to the address defined in the list email notification settings, defaults to false
    " } ], "returns" : { "type" : "item()*", "description" : "Array of result counts and any errors that occurred" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 7, "name" : "list-batch-unsubscribe", "qname" : "mailchimp:list-batch-unsubscribe", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $emails as element(array), $delete_member as xs:boolean, $send_goodbye as xs:boolean, $send_notify as xs:boolean) as item()*", "description" : " Unsubscribe a batch of email addresses to a list.\n", "summary" : "

    Unsubscribe a batch of email addresses to a list.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "emails", "type" : "element(array)", "occurrence" : null, "description" : "
    array of email addresses to unsubscribe
    " }, { "name" : "delete_member", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to completely delete the member from your list instead of just unsubscribing, default to false
    " }, { "name" : "send_goodbye", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to send the goodbye email to the email addresses, defaults to true
    " }, { "name" : "send_notify", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to send the unsubscribe notification email to the address defined in the list email notification settings, defaults to false
    " } ], "returns" : { "type" : "item()*", "description" : "Array of result counts and any errors that occurred" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-clients", "qname" : "mailchimp:list-clients", "signature" : "($apikey as xs:string, $id as xs:string) as item()*", "description" : " Convenience function for list-clients#3.\n", "summary" : "

    Convenience function for list-clients#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "array the desktop and mobile user agents in use on the list" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-clients", "qname" : "mailchimp:list-clients", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string) as item()*", "description" : " Retrieve the clients that the list's subscribers have been tagged as being used based on user agents seen. Made possible by user-agent-string.info double penetration the percent of desktop clients in use array clients a record containing the 'client', an 'icon' image url, the 'percent' using the client, and the total 'members' represented double penetration the percent of mobile clients in use array clients a record containing the 'client', an 'icon' image url, the 'percent' using the client, and the total 'members' represented.\n", "summary" : "

    Retrieve the clients that the list's subscribers have been tagged as being used based on user agents seen.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "Array the desktop and mobile user agents in use on the list" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-growth-history", "qname" : "mailchimp:list-growth-history", "signature" : "($apikey as xs:string, $id as xs:string) as item()*", "description" : " Convenience function for list-growth-history#3.\n", "summary" : "

    Convenience function for list-growth-history#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "Array of months and growth" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-growth-history", "qname" : "mailchimp:list-growth-history", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string) as item()*", "description" : " Access the Growth History by Month for a given list.\n", "summary" : "

    Access the Growth History by Month for a given list.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "Array of months and growth" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "list-interest-group-add", "qname" : "mailchimp:list-interest-group-add", "signature" : "($apikey as xs:string, $id as xs:string, $group_name as xs:string, $grouping_id as xs:integer) as item()*", "description" : " Convenience function for list-interest-group-add#5.\n", "summary" : "

    Convenience function for list-interest-group-add#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "group_name", "type" : "xs:string", "occurrence" : null, "description" : "
    the interest group to add - group names must be unique within a grouping
    " }, { "name" : "grouping_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    ouping_id The grouping to add the new group to - get using list-interest-groupings(). If not supplied, the first grouping on the list is used.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "list-interest-group-add", "qname" : "mailchimp:list-interest-group-add", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $group_name as xs:string, $grouping_id as xs:integer) as item()*", "description" : " Add a single Interest Group - if interest groups for the List are not yet enabled, adding the first group will automatically turn them on.\n", "summary" : "

    Add a single Interest Group - if interest groups for the List are not yet enabled, adding the first group will automatically turn them on.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "group_name", "type" : "xs:string", "occurrence" : null, "description" : "
    the interest group to add - group names must be unique within a grouping
    " }, { "name" : "grouping_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    ouping_id The grouping to add the new group to - get using list-interest-groupings() . If not supplied, the first grouping on the list is used.
    " } ], "returns" : { "type" : "item()*", "description" : "bool true if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "list-interest-group-del", "qname" : "mailchimp:list-interest-group-del", "signature" : "($apikey as xs:string, $id as xs:string, $group_name as xs:string, $grouping_id as xs:integer) as item()*", "description" : " Convenience function for list-interest-group-del#5.\n", "summary" : "

    Convenience function for list-interest-group-del#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "group_name", "type" : "xs:string", "occurrence" : null, "description" : "
    the interest group to delete
    " }, { "name" : "grouping_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    The grouping to delete the group from - get using list-interest-groupings() . If not supplied, the first grouping on the list is used.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "list-interest-group-del", "qname" : "mailchimp:list-interest-group-del", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $group_name as xs:string, $grouping_id as xs:integer) as item()*", "description" : " Delete a single Interest Group - if the last group for a list is deleted, this will also turn groups for the list off.\n", "summary" : "

    Delete a single Interest Group - if the last group for a list is deleted, this will also turn groups for the list off.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "group_name", "type" : "xs:string", "occurrence" : null, "description" : "
    the interest group to delete
    " }, { "name" : "grouping_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    The grouping to delete the group from - get using list-interest-groupings() . If not supplied, the first grouping on the list is used.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "list-interest-group-update", "qname" : "mailchimp:list-interest-group-update", "signature" : "($apikey as xs:string, $id as xs:string, $old_name as xs:string, $new_name as xs:string, $grouping_id as xs:integer) as item()*", "description" : " Convenience function for list-interest-group-update#6.\n", "summary" : "

    Convenience function for list-interest-group-update#6 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "old_name", "type" : "xs:string", "occurrence" : null, "description" : "
    the interest group name to be changed
    " }, { "name" : "new_name", "type" : "xs:string", "occurrence" : null, "description" : "
    the new interest group name to be set
    " }, { "name" : "grouping_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    ouping_id The grouping to delete the group from - get using list-interest-groupings() . If not supplied, the first grouping on the list is used.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "list-interest-group-update", "qname" : "mailchimp:list-interest-group-update", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $old_name as xs:string, $new_name as xs:string, $grouping_id as xs:integer) as item()*", "description" : " Change the name of an Interest Group.\n", "summary" : "

    Change the name of an Interest Group.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "old_name", "type" : "xs:string", "occurrence" : null, "description" : "
    the interest group name to be changed
    " }, { "name" : "new_name", "type" : "xs:string", "occurrence" : null, "description" : "
    the new interest group name to be set
    " }, { "name" : "grouping_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    ouping_id The grouping to delete the group from - get using list-interest-groupings() . If not supplied, the first grouping on the list is used.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "list-interest-grouping-add", "qname" : "mailchimp:list-interest-grouping-add", "signature" : "($apikey as xs:string, $id as xs:string, $name as xs:string, $type as xs:string, $groups as element(array)) as item()*", "description" : " Convenience function for list-interest-grouping-add#6.\n", "summary" : "

    Convenience function for list-interest-grouping-add#6 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the interest grouping to add - grouping names must be unique
    " }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    The type of the grouping to add - one of \"checkboxes\", \"hidden\", \"dropdown\", \"radio\"
    " }, { "name" : "groups", "type" : "element(array)", "occurrence" : null, "description" : "
    The lists of initial group names to be added - at least 1 is required and the names must be unique within a grouping. If the number takes you over the 60 group limit, an error will be thrown.
    " } ], "returns" : { "type" : "item()*", "description" : "The new grouping id if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "list-interest-grouping-add", "qname" : "mailchimp:list-interest-grouping-add", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $name as xs:string, $type as xs:string, $groups as element(array)) as item()*", "description" : " Add a new Interest Grouping - if interest groups for the List are not yet enabled, adding the first grouping will automatically turn them on.\n", "summary" : "

    Add a new Interest Grouping - if interest groups for the List are not yet enabled, adding the first grouping will automatically turn them on.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the interest grouping to add - grouping names must be unique
    " }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    The type of the grouping to add - one of \"checkboxes\", \"hidden\", \"dropdown\", \"radio\"
    " }, { "name" : "groups", "type" : "element(array)", "occurrence" : null, "description" : "
    The lists of initial group names to be added - at least 1 is required and the names must be unique within a grouping. If the number takes you over the 60 group limit, an error will be thrown.
    " } ], "returns" : { "type" : "item()*", "description" : "The new grouping id if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-interest-grouping-del", "qname" : "mailchimp:list-interest-grouping-del", "signature" : "($apikey as xs:string, $grouping_id as xs:integer) as item()*", "description" : " Convenience function for list-interest-grouping-del#3.\n", "summary" : "

    Convenience function for list-interest-grouping-del#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "grouping_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the interest grouping id - get from list-interest-groupings()
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-interest-grouping-del", "qname" : "mailchimp:list-interest-grouping-del", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $grouping_id as xs:integer) as item()*", "description" : " Delete an existing Interest Grouping - this will permanently delete all contained interest groups and will remove those selections from all list members.\n", "summary" : "

    Delete an existing Interest Grouping - this will permanently delete all contained interest groups and will remove those selections from all list members.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "grouping_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the interest grouping id - get from list-interest-groupings()
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "list-interest-grouping-update", "qname" : "mailchimp:list-interest-grouping-update", "signature" : "($apikey as xs:string, $grouping_id as xs:integer, $name as xs:string, $value as xs:string) as item()*", "description" : " Convenience function for list-interest-grouping-update#5.\n", "summary" : "

    Convenience function for list-interest-grouping-update#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "grouping_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the interest grouping id - get from list-interest-groupings()
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the field to update - either \"name\" or \"type\". Groups with in the grouping should be manipulated using the standard listInterestGroup* methods
    " }, { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    The new value of the field. Grouping names must be unique - only \"hidden\" and \"checkboxes\" grouping types can be converted between each other.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "list-interest-grouping-update", "qname" : "mailchimp:list-interest-grouping-update", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $grouping_id as xs:integer, $name as xs:string, $value as xs:string) as item()*", "description" : " Update an existing Interest Grouping.\n", "summary" : "

    Update an existing Interest Grouping.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "grouping_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the interest grouping id - get from list-interest-groupings()
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the field to update - either \"name\" or \"type\". Groups with in the grouping should be manipulated using the standard listInterestGroup* methods
    " }, { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    The new value of the field. Grouping names must be unique - only \"hidden\" and \"checkboxes\" grouping types can be converted between each other.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-interest-groupings", "qname" : "mailchimp:list-interest-groupings", "signature" : "($apikey as xs:string, $id as xs:string) as item()*", "description" : " Convenience function for list-interest-groupings#3.\n", "summary" : "

    Convenience function for list-interest-groupings#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "List of interest groups for the list" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-interest-groupings", "qname" : "mailchimp:list-interest-groupings", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string) as item()*", "description" : " Get the list of interest groupings for a given list, including the label, form information, and included groups for each.\n", "summary" : "

    Get the list of interest groupings for a given list, including the label, form information, and included groups for each.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "List of interest groups for the list" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-locations", "qname" : "mailchimp:list-locations", "signature" : "($apikey as xs:string, $id as xs:string) as item()*", "description" : " Convenience function for list-locations#3.\n", "summary" : "

    Convenience function for list-locations#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "Array of locations" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-locations", "qname" : "mailchimp:list-locations", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string) as item()*", "description" : " Retrieve the locations (countries) that the list's subscribers have been tagged to based on geocoding their IP address.\n", "summary" : "

    Retrieve the locations (countries) that the list's subscribers have been tagged to based on geocoding their IP address.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "Array of locations" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-member-activity", "qname" : "mailchimp:list-member-activity", "signature" : "($apikey as xs:string, $id as xs:string, $email_address as element(array)) as item()*", "description" : " Convenience function for list-member-activity#4.\n", "summary" : "

    Convenience function for list-member-activity#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "email_address", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of up to 50 email addresses to get information for OR the \"id\"(s) for the member returned from listMembers, Webhooks, and Campaigns.
    " } ], "returns" : { "type" : "item()*", "description" : "Array of data and success/error counts" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "list-member-activity", "qname" : "mailchimp:list-member-activity", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $email_address as element(array)) as item()*", "description" : " Get the most recent 100 activities for particular list members (open, click, bounce, unsub, abuse, sent to).\n", "summary" : "

    Get the most recent 100 activities for particular list members (open, click, bounce, unsub, abuse, sent to).

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "email_address", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of up to 50 email addresses to get information for OR the \"id\"(s) for the member returned from listMembers, Webhooks, and Campaigns.
    " } ], "returns" : { "type" : "item()*", "description" : "Array of data and success/error counts" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-member-info", "qname" : "mailchimp:list-member-info", "signature" : "($apikey as xs:string, $id as xs:string, $email_address as element(array)) as item()*", "description" : " Convenience function for list-member-info#4.\n", "summary" : "

    Convenience function for list-member-info#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "email_address", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of up to 50 email addresses to get information for OR the \"id\"(s) for the member returned from listMembers, Webhooks, and Campaigns. For backwards compatibility, if a string is passed, it will be treated as an array with a single element (will not work with XML-RPC).
    " } ], "returns" : { "type" : "item()*", "description" : "Array of list members with their info in an array (see Returned Fields for details)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "list-member-info", "qname" : "mailchimp:list-member-info", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $email_address as element(array)) as item()*", "description" : " Get all the information for particular members of a list.\n", "summary" : "

    Get all the information for particular members of a list.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "email_address", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of up to 50 email addresses to get information for OR the \"id\"(s) for the member returned from listMembers, Webhooks, and Campaigns. For backwards compatibility, if a string is passed, it will be treated as an array with a single element (will not work with XML-RPC).
    " } ], "returns" : { "type" : "item()*", "description" : "Array of list members with their info in an array (see Returned Fields for details)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "list-members", "qname" : "mailchimp:list-members", "signature" : "($apikey as xs:string, $id as xs:string, $status as xs:string, $since as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Convenience function for list-members#7.\n", "summary" : "

    Convenience function for list-members#7 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "status", "type" : "xs:string", "occurrence" : null, "description" : "
    the status to get members for - one of(subscribed, unsubscribed, cleaned, updated), defaults to subscribed
    " }, { "name" : "since", "type" : "xs:string", "occurrence" : null, "description" : "
    optional pull all members whose status (subscribed/unsubscribed/cleaned) has changed or whose profile (updated) has changed since this date/time (in GMT) - format is YYYY-MM-DD HH:mm:ss (24hr)
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 100, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "Array of a the total records match and matching list member data for this page (see Returned Fields for details)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 7, "name" : "list-members", "qname" : "mailchimp:list-members", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $status as xs:string, $since as xs:string, $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Get all of the list members for a list that are of a particular status.\n", "summary" : "

    Get all of the list members for a list that are of a particular status.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "status", "type" : "xs:string", "occurrence" : null, "description" : "
    the status to get members for - one of(subscribed, unsubscribed, cleaned, updated), defaults to subscribed
    " }, { "name" : "since", "type" : "xs:string", "occurrence" : null, "description" : "
    optional pull all members whose status (subscribed/unsubscribed/cleaned) has changed or whose profile (updated) has changed since this date/time (in GMT) - format is YYYY-MM-DD HH:mm:ss (24hr)
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the page number to start at - defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional for large data sets, the number of results to return - defaults to 100, upper limit set at 15000
    " } ], "returns" : { "type" : "item()*", "description" : "Array of a the total records match and matching list member data for this page (see Returned Fields for details)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "list-merge-var-add", "qname" : "mailchimp:list-merge-var-add", "signature" : "($apikey as xs:string, $id as xs:string, $tag as xs:string, $name as xs:string, $options as element(array)) as item()*", "description" : " Convenience function for list-merge-var-add#6.\n", "summary" : "

    Convenience function for list-merge-var-add#6 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "tag", "type" : "xs:string", "occurrence" : null, "description" : "
    The merge tag to add, e.g. FNAME
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The long description of the tag being added, used for user displays
    " }, { "name" : "options", "type" : "element(array)", "occurrence" : null, "description" : "
    optional Various options for this merge var. note: for historical purposes this can also take a \"boolean\"
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "list-merge-var-add", "qname" : "mailchimp:list-merge-var-add", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $tag as xs:string, $name as xs:string, $options as element(array)) as item()*", "description" : " Add a new merge tag to a given list.\n", "summary" : "

    Add a new merge tag to a given list.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "tag", "type" : "xs:string", "occurrence" : null, "description" : "
    The merge tag to add, e.g. FNAME
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The long description of the tag being added, used for user displays
    " }, { "name" : "options", "type" : "element(array)", "occurrence" : null, "description" : "
    optional Various options for this merge var. note: for historical purposes this can also take a \"boolean\"
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-merge-var-del", "qname" : "mailchimp:list-merge-var-del", "signature" : "($apikey as xs:string, $id as xs:string, $tag as xs:string) as item()*", "description" : " Convenience function for list-merge-var-del#4.\n", "summary" : "

    Convenience function for list-merge-var-del#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "tag", "type" : "xs:string", "occurrence" : null, "description" : "
    The merge tag to delete
    " } ], "returns" : { "type" : "item()*", "description" : "bool true if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "list-merge-var-del", "qname" : "mailchimp:list-merge-var-del", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $tag as xs:string) as item()*", "description" : " Delete a merge tag from a given list and all its members. Seriously - the data is removed from all members as well! Note that on large lists this method may seem a bit slower than calls you typically make.\n", "summary" : "

    Delete a merge tag from a given list and all its members.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "tag", "type" : "xs:string", "occurrence" : null, "description" : "
    The merge tag to delete
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "list-merge-var-update", "qname" : "mailchimp:list-merge-var-update", "signature" : "($apikey as xs:string, $id as xs:string, $tag as xs:string, $options as element(array)) as item()*", "description" : " Convenience function for list-merge-var-update#5.\n", "summary" : "

    Convenience function for list-merge-var-update#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "tag", "type" : "xs:string", "occurrence" : null, "description" : "
    The merge tag to update
    " }, { "name" : "options", "type" : "element(array)", "occurrence" : null, "description" : "
    The options to change for a merge var. See list-merge-var-add() for valid options
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "list-merge-var-update", "qname" : "mailchimp:list-merge-var-update", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $tag as xs:string, $options as element(array)) as item()*", "description" : " Update most parameters for a merge tag on a given list. You cannot currently change the merge type.\n", "summary" : "

    Update most parameters for a merge tag on a given list.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "tag", "type" : "xs:string", "occurrence" : null, "description" : "
    The merge tag to update
    " }, { "name" : "options", "type" : "element(array)", "occurrence" : null, "description" : "
    The options to change for a merge var. See list-merge-var-add() for valid options
    " } ], "returns" : { "type" : "item()*", "description" : "True if the request succeeds, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-merge-vars", "qname" : "mailchimp:list-merge-vars", "signature" : "($apikey as xs:string, $id as xs:string) as item()*", "description" : " Convenience function for list-merge-vars#3.\n", "summary" : "

    Convenience function for list-merge-vars#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "List of merge tags for the list" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-merge-vars", "qname" : "mailchimp:list-merge-vars", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string) as item()*", "description" : " Get the list of merge tags for a given list, including their name, tag, and required setting.\n", "summary" : "

    Get the list of merge tags for a given list, including their name, tag, and required setting.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "List of merge tags for the list" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-static-segment-add", "qname" : "mailchimp:list-static-segment-add", "signature" : "($apikey as xs:string, $id as xs:string, $name as xs:string) as item()*", "description" : " Convenience function for list-static-segment-add#4.\n", "summary" : "

    Convenience function for list-static-segment-add#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    a unique name per list for the segment - 50 byte maximum length, anything longer will throw an error
    " } ], "returns" : { "type" : "item()*", "description" : "The id of the new segment, otherwise an error will be thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "list-static-segment-add", "qname" : "mailchimp:list-static-segment-add", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $name as xs:string) as item()*", "description" : " Save a segment against a list for later use. There is no limit to the number of segments which can be saved. Static Segments are not tied to any merge data, interest groups, etc. They essentially allow you to configure an unlimited number of custom segments which will have standard performance. When using proper segments, Static Segments are one of the available options for segmentation just as if you used a merge var (and they can be used with other segmentation options), though performance may degrade at that point.\n", "summary" : "

    Save a segment against a list for later use.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    a unique name per list for the segment - 50 byte maximum length, anything longer will throw an error
    " } ], "returns" : { "type" : "item()*", "description" : "The id of the new segment, otherwise an error will be thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-static-segment-del", "qname" : "mailchimp:list-static-segment-del", "signature" : "($apikey as xs:string, $id as xs:string, $seg_id as xs:integer) as item()*", "description" : " Convenience function for list-static-segment-del#4.\n", "summary" : "

    Convenience function for list-static-segment-del#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "seg_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the static segment to delete - get from list-static-segments()
    " } ], "returns" : { "type" : "item()*", "description" : "True if it worked, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "list-static-segment-del", "qname" : "mailchimp:list-static-segment-del", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $seg_id as xs:integer) as item()*", "description" : " Delete a static segment. Note that this will, of course, remove any member affiliations with the segment.\n", "summary" : "

    Delete a static segment.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "seg_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the static segment to delete - get from list-static-segments()
    " } ], "returns" : { "type" : "item()*", "description" : "True if it worked, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "list-static-segment-members-add", "qname" : "mailchimp:list-static-segment-members-add", "signature" : "($apikey as xs:string, $id as xs:string, $seg_id as xs:integer, $batch as element(array)) as item()*", "description" : " Convenience function for list-static-segment-members-add#5.\n", "summary" : "

    Convenience function for list-static-segment-members-add#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "seg_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the static segment to modify - get from list-static-segments()
    " }, { "name" : "batch", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of email addresses and/or unique_ids to add to the segment
    " } ], "returns" : { "type" : "item()*", "description" : "An array with the results of the operation" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "list-static-segment-members-add", "qname" : "mailchimp:list-static-segment-members-add", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $seg_id as xs:integer, $batch as element(array)) as item()*", "description" : " Add list members to a static segment. It is suggested that you limit batch size to no more than 10,000 addresses per call. Email addresses must exist on the list in order to be included - this will not subscribe them to the list!.\n", "summary" : "

    Add list members to a static segment.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "seg_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the static segment to modify - get from list-static-segments()
    " }, { "name" : "batch", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of email addresses and/or unique_ids to add to the segment
    " } ], "returns" : { "type" : "item()*", "description" : "array an array with the results of the operation" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "list-static-segment-members-del", "qname" : "mailchimp:list-static-segment-members-del", "signature" : "($apikey as xs:string, $id as xs:string, $seg_id as xs:integer, $batch as element(array)) as item()*", "description" : " Convenience function for list-static-segment-members-del#5.\n", "summary" : "

    Convenience function for list-static-segment-members-del#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "seg_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the static segment to delete - get from list-static-segments()
    " }, { "name" : "batch", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of email addresses and/or unique_ids to remove from the segment
    " } ], "returns" : { "type" : "item()*", "description" : "An array with the results of the operation" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "list-static-segment-members-del", "qname" : "mailchimp:list-static-segment-members-del", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $seg_id as xs:integer, $batch as element(array)) as item()*", "description" : " Remove list members from a static segment. It is suggested that you limit batch size to no more than 10,000 addresses per call. Email addresses must exist on the list in order to be removed - this will not unsubscribe them from the list!.\n", "summary" : "

    Remove list members from a static segment.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "seg_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the static segment to delete - get from list-static-segments()
    " }, { "name" : "batch", "type" : "element(array)", "occurrence" : null, "description" : "
    an array of email addresses and/or unique_ids to remove from the segment
    " } ], "returns" : { "type" : "item()*", "description" : "An array with the results of the operation" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-static-segment-reset", "qname" : "mailchimp:list-static-segment-reset", "signature" : "($apikey as xs:string, $id as xs:string, $seg_id as xs:integer) as item()*", "description" : " Convenience function for list-static-segment-reset#4.\n", "summary" : "

    Convenience function for list-static-segment-reset#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "seg_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the static segment to reset - get from list-static-segments()
    " } ], "returns" : { "type" : "item()*", "description" : "True if it worked, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "list-static-segment-reset", "qname" : "mailchimp:list-static-segment-reset", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $seg_id as xs:integer) as item()*", "description" : " Resets a static segment - removes all members from the static segment. Note: does not actually affect list member data.\n", "summary" : "

    Resets a static segment - removes all members from the static segment.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "seg_id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the static segment to reset - get from list-static-segments()
    " } ], "returns" : { "type" : "item()*", "description" : "True if it worked, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-static-segments", "qname" : "mailchimp:list-static-segments", "signature" : "($apikey as xs:string, $id as xs:string) as item()*", "description" : " Convenience function for list-static-segments#3.\n", "summary" : "

    Convenience function for list-static-segments#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "An array of parameters for each static segment" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-static-segments", "qname" : "mailchimp:list-static-segments", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string) as item()*", "description" : " Retrieve all of the Static Segments for a list.\n", "summary" : "

    Retrieve all of the Static Segments for a list.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "An array of parameters for each static segment" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 10, "name" : "list-subscribe", "qname" : "mailchimp:list-subscribe", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $email_address as xs:string, $merge_vars as element(array), $email_type as xs:string, $double_optin as xs:boolean, $update_existing as xs:boolean, $replace_interests as xs:boolean, $send_welcome as xs:boolean) as item()*", "description" : " Subscribe the provided email to a list.\n", "summary" : "

    Subscribe the provided email to a list.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "email_address", "type" : "xs:string", "occurrence" : null, "description" : "
    the email address to subscribe
    " }, { "name" : "merge_vars", "type" : "element(array)", "occurrence" : null, "description" : "
    optional merges for the email (FNAME, LNAME, etc.) (see examples below for handling \"blank\" arrays). Note that a merge field can only hold up to 255 bytes. Also, there are a few \"special\" keys. See Mailchimp API documentation for more information about the parameter structure.
    " }, { "name" : "email_type", "type" : "xs:string", "occurrence" : null, "description" : "
    optional email type preference for the email (html, text, or mobile defaults to html)
    " }, { "name" : "double_optin", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional flag to control whether a double opt-in confirmation message is sent, defaults to true. Abusing this may cause your account to be suspended.
    " }, { "name" : "update_existing", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional flag to control whether a existing subscribers should be updated instead of throwing and error, defaults to false
    " }, { "name" : "replace_interests", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional flag to determine whether we replace the interest groups with the groups provided, or we add the provided groups to the member's interest groups (optional, defaults to true)
    " }, { "name" : "send_welcome", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional if your double_optin is false and this is true, we will send your lists Welcome Email if this subscribe succeeds - this will *not* fire if we end up updating an existing subscriber. If double_optin is true, this has no effect. defaults to false.
    " } ], "returns" : { "type" : "item()*", "description" : "True on success, false on failure." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 9, "name" : "list-subscribe", "qname" : "mailchimp:list-subscribe", "signature" : "($apikey as xs:string, $id as xs:string, $email_address as xs:string, $merge_vars as element(array), $email_type as xs:string, $double_optin as xs:boolean, $update_existing as xs:boolean, $replace_interests as xs:boolean, $send_welcome as xs:boolean) as item()*", "description" : " Convenience function for list-subscribe#10.\n", "summary" : "

    Convenience function for list-subscribe#10 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "email_address", "type" : "xs:string", "occurrence" : null, "description" : "
    the email address to subscribe
    " }, { "name" : "merge_vars", "type" : "element(array)", "occurrence" : null, "description" : "
    optional merges for the email (FNAME, LNAME, etc.) (see examples below for handling \"blank\" arrays). Note that a merge field can only hold up to 255 bytes. Also, there are a few \"special\" keys. See Mailchimp API documentation for more information about the parameter structure.
    " }, { "name" : "email_type", "type" : "xs:string", "occurrence" : null, "description" : "
    optional email type preference for the email (html, text, or mobile defaults to html)
    " }, { "name" : "double_optin", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional flag to control whether a double opt-in confirmation message is sent, defaults to true. Abusing this may cause your account to be suspended.
    " }, { "name" : "update_existing", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional flag to control whether a existing subscribers should be updated instead of throwing and error, defaults to false
    " }, { "name" : "replace_interests", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional flag to determine whether we replace the interest groups with the groups provided, or we add the provided groups to the member's interest groups (optional, defaults to true)
    " }, { "name" : "send_welcome", "type" : "xs:boolean", "occurrence" : null, "description" : "
    optional if your double_optin is false and this is true, we will send your lists Welcome Email if this subscribe succeeds - this will *not* fire if we end up updating an existing subscriber. If double_optin is true, this has no effect. defaults to false.
    " } ], "returns" : { "type" : "item()*", "description" : "True on success, false on failure." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "list-unsubscribe", "qname" : "mailchimp:list-unsubscribe", "signature" : "($apikey as xs:string, $id as xs:string, $email_address as xs:string, $delete_member as xs:boolean, $send_goodbye as xs:boolean, $send_notify as xs:boolean) as item()*", "description" : " Convenience function for list-unsubscribe#7.\n", "summary" : "

    Convenience function for list-unsubscribe#7 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "email_address", "type" : "xs:string", "occurrence" : null, "description" : "
    the email address to unsubscribe OR the email \"id\" returned from listMemberInfo, Webhooks, and Campaigns
    " }, { "name" : "delete_member", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to completely delete the member from your list instead of just unsubscribing, default to false
    " }, { "name" : "send_goodbye", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to send the goodbye email to the email address, defaults to true
    " }, { "name" : "send_notify", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to send the unsubscribe notification email to the address defined in the list email notification settings, defaults to true
    " } ], "returns" : { "type" : "item()*", "description" : "True on success, false on failure." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 7, "name" : "list-unsubscribe", "qname" : "mailchimp:list-unsubscribe", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $email_address as xs:string, $delete_member as xs:boolean, $send_goodbye as xs:boolean, $send_notify as xs:boolean) as item()*", "description" : " Unsubscribe the given email address from the list.\n", "summary" : "

    Unsubscribe the given email address from the list.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "email_address", "type" : "xs:string", "occurrence" : null, "description" : "
    the email address to unsubscribe OR the email \"id\" returned from listMemberInfo, Webhooks, and Campaigns
    " }, { "name" : "delete_member", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to completely delete the member from your list instead of just unsubscribing, default to false
    " }, { "name" : "send_goodbye", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to send the goodbye email to the email address, defaults to true
    " }, { "name" : "send_notify", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to send the unsubscribe notification email to the address defined in the list email notification settings, defaults to true
    " } ], "returns" : { "type" : "item()*", "description" : "True on success, false on failure." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "list-update-member", "qname" : "mailchimp:list-update-member", "signature" : "($apikey as xs:string, $id as xs:string, $email_address as xs:string, $merge_vars as element(array), $email_type as xs:string, $replace_interests as xs:boolean) as item()*", "description" : " Convenience function for list-update-member#7.\n", "summary" : "

    Convenience function for list-update-member#7 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "email_address", "type" : "xs:string", "occurrence" : null, "description" : "
    the current email address of the member to update OR the \"id\" for the member returned from listMemberInfo, Webhooks, and Campaigns
    " }, { "name" : "merge_vars", "type" : "element(array)", "occurrence" : null, "description" : "
    array of new field values to update the member with. See merge_vars in list-subscribe() for details.
    " }, { "name" : "email_type", "type" : "xs:string", "occurrence" : null, "description" : "
    change the email type preference for the member (\"html\", \"text\", or \"mobile\"). Leave blank to keep the existing preference (optional)
    " }, { "name" : "replace_interests", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to determine whether we replace the interest groups with the updated groups provided, or we add the provided groups to the member's interest groups (optional, defaults to true)
    " } ], "returns" : { "type" : "item()*", "description" : "True on success, false on failure." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 7, "name" : "list-update-member", "qname" : "mailchimp:list-update-member", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $email_address as xs:string, $merge_vars as element(array), $email_type as xs:string, $replace_interests as xs:boolean) as item()*", "description" : " Edit the email address, merge fields, and interest groups for a list member. If you are doing a batch update on lots of users, consider using #list-batch-subscribe() with the update_existing and possible replace_interests parameter.\n", "summary" : "

    Edit the email address, merge fields, and interest groups for a list member.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "email_address", "type" : "xs:string", "occurrence" : null, "description" : "
    the current email address of the member to update OR the \"id\" for the member returned from listMemberInfo, Webhooks, and Campaigns
    " }, { "name" : "merge_vars", "type" : "element(array)", "occurrence" : null, "description" : "
    array of new field values to update the member with. See merge_vars in list-subscribe() for details.
    " }, { "name" : "email_type", "type" : "xs:string", "occurrence" : null, "description" : "
    change the email type preference for the member (\"html\", \"text\", or \"mobile\"). Leave blank to keep the existing preference (optional)
    " }, { "name" : "replace_interests", "type" : "xs:boolean", "occurrence" : null, "description" : "
    flag to determine whether we replace the interest groups with the updated groups provided, or we add the provided groups to the member's interest groups (optional, defaults to true)
    " } ], "returns" : { "type" : "item()*", "description" : "True on success, false on failure." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "list-webhook-add", "qname" : "mailchimp:list-webhook-add", "signature" : "($apikey as xs:string, $id as xs:string, $url as xs:string, $actions as element(array), $sources as element(array)) as item()*", "description" : " Convenience function for list-webhook-add#6.\n", "summary" : "

    Convenience function for list-webhook-add#6 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "url", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid URL for the Webhook - it will be validated. note that a url may only exist on a list once.
    " }, { "name" : "actions", "type" : "element(array)", "occurrence" : null, "description" : "
    optional a hash of actions to fire this Webhook for
    " }, { "name" : "sources", "type" : "element(array)", "occurrence" : null, "description" : "
    optional a hash of sources to fire this Webhook for
    " } ], "returns" : { "type" : "item()*", "description" : "True if the call succeeds, otherwise an exception will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "list-webhook-add", "qname" : "mailchimp:list-webhook-add", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $url as xs:string, $actions as element(array), $sources as element(array)) as item()*", "description" : " Add a new Webhook URL for the given list.\n", "summary" : "

    Add a new Webhook URL for the given list.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "url", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid URL for the Webhook - it will be validated. note that a url may only exist on a list once.
    " }, { "name" : "actions", "type" : "element(array)", "occurrence" : null, "description" : "
    optional a hash of actions to fire this Webhook for
    " }, { "name" : "sources", "type" : "element(array)", "occurrence" : null, "description" : "
    optional a hash of sources to fire this Webhook for
    " } ], "returns" : { "type" : "item()*", "description" : "True if the call succeeds, otherwise an exception will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-webhook-del", "qname" : "mailchimp:list-webhook-del", "signature" : "($apikey as xs:string, $id as xs:string, $url as xs:string) as item()*", "description" : " Convenience function for list-webhook-del#4.\n", "summary" : "

    Convenience function for list-webhook-del#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "url", "type" : "xs:string", "occurrence" : null, "description" : "
    the URL of a Webhook on this list
    " } ], "returns" : { "type" : "item()*", "description" : "True if the call succeeds, otherwise an exception will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "list-webhook-del", "qname" : "mailchimp:list-webhook-del", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string, $url as xs:string) as item()*", "description" : " Delete an existing Webhook URL from a given list.\n", "summary" : "

    Delete an existing Webhook URL from a given list.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " }, { "name" : "url", "type" : "xs:string", "occurrence" : null, "description" : "
    the URL of a Webhook on this list
    " } ], "returns" : { "type" : "item()*", "description" : "True if the call succeeds, otherwise an exception will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-webhooks", "qname" : "mailchimp:list-webhooks", "signature" : "($apikey as xs:string, $id as xs:string) as item()*", "description" : " Convenience function for list-webhooks#3.\n", "summary" : "

    Convenience function for list-webhooks#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "List of webhooks" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "list-webhooks", "qname" : "mailchimp:list-webhooks", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:string) as item()*", "description" : " Return the Webhooks configured for the given list.\n", "summary" : "

    Return the Webhooks configured for the given list.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the list id to connect to. Get by calling lists()
    " } ], "returns" : { "type" : "item()*", "description" : "List of webhooks" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "lists-for-email", "qname" : "mailchimp:lists-for-email", "signature" : "($apikey as xs:string, $email_address as xs:string) as item()*", "description" : " Convenience function for lists-for-email#3.\n", "summary" : "

    Convenience function for lists-for-email#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "email_address", "type" : "xs:string", "occurrence" : null, "description" : "
    the email address to check OR the email \"id\" returned from listMemberInfo, Webhooks, and Campaigns
    " } ], "returns" : { "type" : "item()*", "description" : "An array of list_ids the member is subscribed to." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "lists-for-email", "qname" : "mailchimp:lists-for-email", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $email_address as xs:string) as item()*", "description" : " Retrieve all List Ids a member is subscribed to.\n", "summary" : "

    Retrieve all List Ids a member is subscribed to.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "email_address", "type" : "xs:string", "occurrence" : null, "description" : "
    the email address to check OR the email \"id\" returned from listMemberInfo, Webhooks, and Campaigns
    " } ], "returns" : { "type" : "item()*", "description" : "An array of list_ids the member is subscribed to." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "lists", "qname" : "mailchimp:lists", "signature" : "($apikey as xs:string, $filters as element(array), $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Convenience function for lists#5.\n", "summary" : "

    Convenience function for lists#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "filters", "type" : "element(array)", "occurrence" : null, "description" : "
    a hash of filters to apply to this query - all are optional. See Mailchimp API documentation for more information about the parameter structure.
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional - control paging of lists, start results at this list #, defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional - control paging of lists, number of lists to return with each call, defaults to 25 (max=100)
    " } ], "returns" : { "type" : "item()*", "description" : "Array with keys listed in Returned Fields below" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "lists", "qname" : "mailchimp:lists", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $filters as element(array), $start as xs:integer, $limit as xs:integer) as item()*", "description" : " Retrieve all of the lists defined for your user account.\n", "summary" : "

    Retrieve all of the lists defined for your user account.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "filters", "type" : "element(array)", "occurrence" : null, "description" : "
    a hash of filters to apply to this query - all are optional. See Mailchimp API documentation for more information about the parameter structure.
    " }, { "name" : "start", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional - control paging of lists, start results at this list #, defaults to 1st page of data (page 0)
    " }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "
    optional - control paging of lists, number of lists to return with each call, defaults to 25 (max=100)
    " } ], "returns" : { "type" : "item()*", "description" : "Array with keys listed in Returned Fields below" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "ping", "qname" : "mailchimp:ping", "signature" : "($apikey as xs:string) as item()*", "description" : " Convenience function for ping#2.\n", "summary" : "

    Convenience function for ping#2 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "Returns \"Everything's Chimpy!\" if everything is chimpy, otherwise returns an error message" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "ping", "qname" : "mailchimp:ping", "signature" : "($endpoint-url as xs:string, $apikey as xs:string) as item()*", "description" : " \"Ping\" the MailChimp API - a simple method you can call that will return a constant value as long as everything is good. Note than unlike most all of our methods, we don't throw an Exception if we are having issues. You will simply receive a different string back that will explain our view on what is going on.\n", "summary" : "

    \"Ping\" the MailChimp API - a simple method you can call that will return a constant value as long as everything is good.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " } ], "returns" : { "type" : "item()*", "description" : "Returns \"Everything's Chimpy!\" if everything is chimpy, otherwise returns an error message" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "template-add", "qname" : "mailchimp:template-add", "signature" : "($apikey as xs:string, $name as xs:string, $html as xs:string) as item()*", "description" : " Convenience function for template-add#4.\n", "summary" : "

    Convenience function for template-add#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name for the template - names must be unique and a max of 50 bytes
    " }, { "name" : "html", "type" : "xs:string", "occurrence" : null, "description" : "
    a string specifying the entire template to be created. This is NOT campaign content. They are intended to utilize our template language.
    " } ], "returns" : { "type" : "item()*", "description" : "The new template id, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "template-add", "qname" : "mailchimp:template-add", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $name as xs:string, $html as xs:string) as item()*", "description" : " Create a new user template, NOT campaign content. These templates can then be applied while creating campaigns.\n", "summary" : "

    Create a new user template, NOT campaign content.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name for the template - names must be unique and a max of 50 bytes
    " }, { "name" : "html", "type" : "xs:string", "occurrence" : null, "description" : "
    a string specifying the entire template to be created. This is NOT campaign content. They are intended to utilize our template language.
    " } ], "returns" : { "type" : "item()*", "description" : "The new template id, otherwise an error is thrown." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "template-del", "qname" : "mailchimp:template-del", "signature" : "($apikey as xs:string, $id as xs:integer) as item()*", "description" : " Convenience function for template-del#3.\n", "summary" : "

    Convenience function for template-del#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the user template to delete
    " } ], "returns" : { "type" : "item()*", "description" : "True if the template was deleted, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "template-del", "qname" : "mailchimp:template-del", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:integer) as item()*", "description" : " Delete (deactivate) a user template.\n", "summary" : "

    Delete (deactivate) a user template.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the user template to delete
    " } ], "returns" : { "type" : "item()*", "description" : "True if the template was deleted, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "template-info", "qname" : "mailchimp:template-info", "signature" : "($apikey as xs:string, $tid as xs:integer, $type as xs:string) as item()*", "description" : " Convenience function for template-info#4.\n", "summary" : "

    Convenience function for template-info#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "tid", "type" : "xs:integer", "occurrence" : null, "description" : "
    the template id - get from templates()
    " }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the template type to load - one of 'user', 'gallery', 'base'
    " } ], "returns" : { "type" : "item()*", "description" : "An array of info to be used when editing" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "template-info", "qname" : "mailchimp:template-info", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $tid as xs:integer, $type as xs:string) as item()*", "description" : " Pull details for a specific template to help support editing.\n", "summary" : "

    Pull details for a specific template to help support editing.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "tid", "type" : "xs:integer", "occurrence" : null, "description" : "
    the template id - get from templates()
    " }, { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the template type to load - one of 'user', 'gallery', 'base'
    " } ], "returns" : { "type" : "item()*", "description" : "An array of info to be used when editing" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "template-undel", "qname" : "mailchimp:template-undel", "signature" : "($apikey as xs:string, $id as xs:integer) as item()*", "description" : " Convenience function for template-undel#3.\n", "summary" : "

    Convenience function for template-undel#3 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the user template to reactivate
    " } ], "returns" : { "type" : "item()*", "description" : "boolean true if the template was deleted, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "template-undel", "qname" : "mailchimp:template-undel", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:integer) as item()*", "description" : " Undelete (reactivate) a user template.\n", "summary" : "

    Undelete (reactivate) a user template.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the user template to reactivate
    " } ], "returns" : { "type" : "item()*", "description" : "boolean true if the template was deleted, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "template-update", "qname" : "mailchimp:template-update", "signature" : "($apikey as xs:string, $id as xs:integer, $values as element(array)) as item()*", "description" : " Convenience function for template-update#4.\n", "summary" : "

    Convenience function for template-update#4 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the user template to update
    " }, { "name" : "values", "type" : "element(array)", "occurrence" : null, "description" : "
    s the values to updates - while both are optional, at least one should be provided. Both can be updated at the same time.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the template was updated, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "template-update", "qname" : "mailchimp:template-update", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $id as xs:integer, $values as element(array)) as item()*", "description" : " Replace the content of a user template, NOT campaign content.\n", "summary" : "

    Replace the content of a user template, NOT campaign content.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "id", "type" : "xs:integer", "occurrence" : null, "description" : "
    the id of the user template to update
    " }, { "name" : "values", "type" : "element(array)", "occurrence" : null, "description" : "
    s the values to updates - while both are optional, at least one should be provided. Both can be updated at the same time.
    " } ], "returns" : { "type" : "item()*", "description" : "True if the template was updated, otherwise an error will be thrown" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "templates", "qname" : "mailchimp:templates", "signature" : "($apikey as xs:string, $types as element(array), $category as xs:string, $inactives as element(array)) as item()*", "description" : " Convenience function for templates#5.\n", "summary" : "

    Convenience function for templates#5 .

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "types", "type" : "element(array)", "occurrence" : null, "description" : "
    optional the types of templates to return
    " }, { "name" : "category", "type" : "xs:string", "occurrence" : null, "description" : "
    optional for Gallery templates only, limit to a specific template category
    " }, { "name" : "inactives", "type" : "element(array)", "occurrence" : null, "description" : "
    optional options to control how inactive templates are returned, if at all
    " } ], "returns" : { "type" : "item()*", "description" : "An array of structs, one for each template (see Returned Fields for details)" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "templates", "qname" : "mailchimp:templates", "signature" : "($endpoint-url as xs:string, $apikey as xs:string, $types as element(array), $category as xs:string, $inactives as element(array)) as item()*", "description" : " Retrieve various templates available in the system, allowing some thing similar to our template gallery to be created. boolean user Customer template for this user account. Defaults to true. boolean gallery Templates from our Gallery. Note that some templates that require extra configuration are withheld. (eg, the Etsy template). Defaults to false. boolean base Our \"start from scratch\" extremely basic templates boolean include user templates are not deleted, only set inactive. defaults to false. boolean only only include inactive templates. defaults to false.\n", "summary" : "

    Retrieve various templates available in the system, allowing some thing similar to our template gallery to be created.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint-url", "type" : "xs:string", "occurrence" : null, "description" : "
    Mailchimp endpoint URL, e.g. http://us1.api.mailchimp.com/1.3/
    " }, { "name" : "apikey", "type" : "xs:string", "occurrence" : null, "description" : "
    a valid API Key for your user account. Get by visiting your API dashboard
    " }, { "name" : "types", "type" : "element(array)", "occurrence" : null, "description" : "
    optional the types of templates to return
    " }, { "name" : "category", "type" : "xs:string", "occurrence" : null, "description" : "
    optional for Gallery templates only, limit to a specific template category
    " }, { "name" : "inactives", "type" : "element(array)", "occurrence" : null, "description" : "
    optional options to control how inactive templates are returned, if at all
    " } ], "returns" : { "type" : "item()*", "description" : "An array of structs, one for each template (see Returned Fields for details)" }, "errors" : [ ] } ], "variables" : [ { "name" : "mailchimp:gateway", "type" : "item()*", "description" : " Mailchimp gateway where the client data is stored.\n" }, { "name" : "mailchimp:version", "type" : "item()*", "description" : " Mailchimp API version.\n" }, { "name" : "mailchimp:endpoint", "type" : "item()*", "description" : " Endpoint URL for the XML-RPC requests.\n" } ] }, "http://www.zorba-xquery.com/modules/couchbase" : { "ns" : "http://www.zorba-xquery.com/modules/couchbase", "description" : " This module provides minimal functionality to interact with the\n Couchbase NoSQL database.\n The module is built using the libcouchbase C client library and\n exposes most of its functionality in XQuery with JSONiq extensions.\n Beyond just allowing for basic key-value store operations (e.g.\n put-/get-text or put-/get-binary, this module also allows to work\n with Couchbase views in order to allow for complex JSON query\n operations.\n", "sees" : [ ], "authors" : [ "Juan Zacarias" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.zorba-xquery.com/modules/couchbase", "prefix" : "cb" }, { "uri" : "http://jsoniq.org/functions", "prefix" : "jn" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "connect", "qname" : "cb:connect", "signature" : "($options as object()) as xs:anyURI external", "description" : " Connect to the Couchbase server and return an opaque identifier\n representing the established connection.\n", "summary" : "

    Connect to the Couchbase server and return an opaque identifier\n representing the established connection.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    a JSONiq object that contains the host, bucket, and user information.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for the established connection. Example: { \"host\": \"localhost:8091\", \"username\" : null, \"password\" : null, \"bucket\" : \"default\" } " }, "errors" : [ "cb:LCB0001 if the connection to the given host/bucket could not be established.", "cb:CB0001 if mandatory connection information is missing.", "cb:CB0007 if a given option is not supported." ] }, { "isDocumented" : true, "arity" : 4, "name" : "connect", "qname" : "cb:connect", "signature" : "($host as xs:string, $username as xs:string?, $password as xs:string?, $bucket as xs:string) as xs:anyURI", "description" : " Connect to the Couchbase server and return an opaque identifier\n representing the established connection.\n", "summary" : "

    Connect to the Couchbase server and return an opaque identifier\n representing the established connection.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host", "type" : "xs:string", "occurrence" : null, "description" : "
    address of the couchbase server (e.g. \"localhost:8091\")
    " }, { "name" : "username", "type" : "xs:string", "occurrence" : "?", "description" : "
    username used for the connection
    " }, { "name" : "password", "type" : "xs:string", "occurrence" : "?", "description" : "
    password used for the connection
    " }, { "name" : "bucket", "type" : "xs:string", "occurrence" : null, "description" : "
    name of the bucket to use (e.g. \"default\")
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for the established connection." }, "errors" : [ "cb:LCB0001 if the connection to the given host/bucket could not be established." ] }, { "isDocumented" : true, "arity" : 3, "name" : "create-view", "qname" : "cb:create-view", "signature" : "($db as xs:anyURI, $doc-name as xs:string, $view-names as xs:string*) as xs:string* external", "description" : " Create a document/view.\n If the document already exists, it is replaced. A document can hold several\n views that must be specified in the same call of cb:create-view.\n", "summary" : "

    Create a document/view.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "doc-name", "type" : "xs:string", "occurrence" : null, "description" : "
    name of the document to create.
    " }, { "name" : "view-names", "type" : "xs:string", "occurrence" : "*", "description" : "
    names of the views to create in the document.
    " } ], "returns" : { "type" : "xs:string*", "description" : "the names of the paths for the views that have been created." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 4, "name" : "create-view", "qname" : "cb:create-view", "signature" : "($db as xs:anyURI, $doc-name as xs:string, $view-names as xs:string*, $options as object()*) as xs:string* external", "description" : " Create a document/view.\n If the document already exists, it is replaced. A document can hold several\n views that must be specified in the same call of cb:create-view.\n", "summary" : "

    Create a document/view.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "doc-name", "type" : "xs:string", "occurrence" : null, "description" : "
    name of the document to create.
    " }, { "name" : "view-names", "type" : "xs:string", "occurrence" : "*", "description" : "
    names of the views to create in the document.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "*", "description" : "
    options describing how to create the view.
    " } ], "returns" : { "type" : "xs:string*", "description" : "the names of the paths for the views that have been created." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server.", "cb:CB0005 if the number of options doesn't match the number of view-names.", "cb:CB0007 if any of the options is not supported.", "cb:CB0010 if any of the given options has an invalid type." ] }, { "isDocumented" : true, "arity" : 2, "name" : "delete-view", "qname" : "cb:delete-view", "signature" : "($db as xs:anyURI, $doc as xs:string*) as xs:string* external", "description" : " Delete a document/view.\n If the document doesn't exists, function does nothing. All the views hold in the\n Document are deleted, this function can't delete single views.\n", "summary" : "

    Delete a document/view.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "doc", "type" : "xs:string", "occurrence" : "*", "description" : "
    -name name of the document to create.
    " } ], "returns" : { "type" : "xs:string*", "description" : "empty sequence." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 1, "name" : "flush", "qname" : "cb:flush", "signature" : "($db as xs:anyURI) as empty-sequence() external", "description" : " Remove all key/value pairs from the cluster\n", "summary" : "

    Remove all key/value pairs from the cluster\n

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 2, "name" : "get-binary", "qname" : "cb:get-binary", "signature" : "($db as xs:anyURI, $key as xs:string*) as xs:base64Binary* external", "description" : " Return the values of the given keys (type xs:string) as base64Binary.\n", "summary" : "

    Return the values of the given keys (type xs:string) as base64Binary.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "key", "type" : "xs:string", "occurrence" : "*", "description" : "
    the requested keys
    " } ], "returns" : { "type" : "xs:base64Binary*", "description" : "a sequence of xs:base64Binary items for the given keys." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 3, "name" : "get-binary", "qname" : "cb:get-binary", "signature" : "($db as xs:anyURI, $key as xs:string*, $options as object()) as xs:base64Binary* external", "description" : " Return the values of the given keys (type xs:string) as base64Binary.\n", "summary" : "

    Return the values of the given keys (type xs:string) as base64Binary.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "key", "type" : "xs:string", "occurrence" : "*", "description" : "
    the requested keys
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    JSONiq object with additional options
    " } ], "returns" : { "type" : "xs:base64Binary*", "description" : "a sequence of xs:base64Binary items for the given keys." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server.", "cb:CB0007 if any of the options is not supported.", "cb:CB0009 if the given expiration time is not an xs:integer." ] }, { "isDocumented" : true, "arity" : 2, "name" : "get-text", "qname" : "cb:get-text", "signature" : "($db as xs:anyURI, $key as xs:string*) as xs:string* external", "description" : " Return the values of the given keys (type xs:string) as string.\n", "summary" : "

    Return the values of the given keys (type xs:string) as string.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "key", "type" : "xs:string", "occurrence" : "*", "description" : "
    the requested keys
    " } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of string Items corresponding to the key" }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 3, "name" : "get-text", "qname" : "cb:get-text", "signature" : "($db as xs:anyURI, $key as xs:string*, $options as object()) as xs:string* external", "description" : " Return the values of the given keys (type xs:string) as string.\n", "summary" : "

    Return the values of the given keys (type xs:string) as string.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "key", "type" : "xs:string", "occurrence" : "*", "description" : "
    the requested keys
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    JSONiq object with additional options
    " } ], "returns" : { "type" : "xs:string*", "description" : "a sequence of strings for the given keys." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server.", "cb:CB0006 if the given encoding is not supported.", "cb:CB0007 if any of the options is not supported.", "cb:CB0009 if the given expiration time is not an xs:integer." ] }, { "isDocumented" : true, "arity" : 3, "name" : "put-binary", "qname" : "cb:put-binary", "signature" : "($db as xs:anyURI, $key as xs:string*, $value as xs:base64Binary*) as empty-sequence()", "description" : " Store the given key-value bindings.\n", "summary" : "

    Store the given key-value bindings.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "key", "type" : "xs:string", "occurrence" : "*", "description" : "
    the keys to store
    " }, { "name" : "value", "type" : "xs:base64Binary", "occurrence" : "*", "description" : "
    the values (as xs:base64binary) to be stored.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server.", "cb:CB0005 if the number of keys doesn't match the number of values." ] }, { "isDocumented" : true, "arity" : 4, "name" : "put-binary", "qname" : "cb:put-binary", "signature" : "($db as xs:anyURI, $key as xs:string*, $value as xs:base64Binary*, $options as object()) as empty-sequence() external", "description" : " Store the given key-value bindings.\n", "summary" : "

    Store the given key-value bindings.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "key", "type" : "xs:string", "occurrence" : "*", "description" : "
    the keys to store
    " }, { "name" : "value", "type" : "xs:base64Binary", "occurrence" : "*", "description" : "
    the values (as xs:base64binary) to be stored.
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    JSONiq object with additional options
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server.", "cb:CB0005 if the number of keys doesn't match the number of values.", "cb:CB0007 if any of the options is not supported.", "cb:CB0009 if the given expiration time is not an xs:integer.", "cb:CB0011 if the stored Variable was not stored" ] }, { "isDocumented" : true, "arity" : 3, "name" : "put-text", "qname" : "cb:put-text", "signature" : "($db as xs:anyURI, $key as xs:string*, $value as xs:string*) as empty-sequence()", "description" : " Store the given key-value bindings.\n The values are stored with the UTF-8 encoding and a default\n expiration time of 60 seconds.\n", "summary" : "

    Store the given key-value bindings.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "key", "type" : "xs:string", "occurrence" : "*", "description" : "
    the keys to store
    " }, { "name" : "value", "type" : "xs:string", "occurrence" : "*", "description" : "
    the values (as xs:string) to be stored.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server.", "cb:CB0005 if the number of keys doesn't match the number of values." ] }, { "isDocumented" : true, "arity" : 4, "name" : "put-text", "qname" : "cb:put-text", "signature" : "($db as xs:anyURI, $key as xs:string*, $value as xs:string*, $options as object()) as empty-sequence() external", "description" : " Store the given key-value bindings.\n", "summary" : "

    Store the given key-value bindings.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "key", "type" : "xs:string", "occurrence" : "*", "description" : "
    the keys to store
    " }, { "name" : "value", "type" : "xs:string", "occurrence" : "*", "description" : "
    the values (as xs:string) to be stored.
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    JSONiq object with additional options
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server.", "cb:CB0005 if the number of keys doesn't match the number of values.", "cb:CB0006 if the given encoding is not supported.", "cb:CB0007 if any of the options is not supported.", "cb:CB0009 if the given expiration time is not an xs:integer.", "cb:CB0011 if the stored Variable was not stored" ] }, { "isDocumented" : true, "arity" : 2, "name" : "remove", "qname" : "cb:remove", "signature" : "($db as xs:anyURI, $key as xs:string*) as empty-sequence() external", "description" : " Remove the values matching the given keys (xs:string) from the server.\n", "summary" : "

    Remove the values matching the given keys (xs:string) from the server.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "key", "type" : "xs:string", "occurrence" : "*", "description" : "
    the keys of the values that should be removed.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 3, "name" : "touch", "qname" : "cb:touch", "signature" : "($db as xs:anyURI, $key as xs:string*, $exp-time as xs:integer) as empty-sequence() external", "description" : " Refresh the expiration time of the given keys.\n", "summary" : "

    Refresh the expiration time of the given keys.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "key", "type" : "xs:string", "occurrence" : "*", "description" : "
    the keys to touch
    " }, { "name" : "exp-time", "type" : "xs:integer", "occurrence" : null, "description" : "
    new expieration time in seconds
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "a empty sequence." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 2, "name" : "view", "qname" : "cb:view", "signature" : "($db as xs:anyURI, $path as xs:string*) as object()*", "description" : " Retrieve the content of existing views.\n", "summary" : "

    Retrieve the content of existing views.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "path", "type" : "xs:string", "occurrence" : "*", "description" : "
    contains the string of a view path (e.g. \"_design/test/_view/vies\").
    " } ], "returns" : { "type" : "object()*", "description" : "a sequence of strings (as JSON) containing information of the views." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server." ] }, { "isDocumented" : true, "arity" : 3, "name" : "view", "qname" : "cb:view", "signature" : "($db as xs:anyURI, $path as xs:string*, $options as object()) as object()*", "description" : " Retrieve the content of existing views.\n", "summary" : "

    Retrieve the content of existing views.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "db", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    connection reference
    " }, { "name" : "path", "type" : "xs:string", "occurrence" : "*", "description" : "
    contains the string of a view path (e.g. \"_design/test/_view/vies\").
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    JSONiq object with additional options
    " } ], "returns" : { "type" : "object()*", "description" : "a sequence of strings (as JSON) containing information of the views." }, "errors" : [ "cb:LCB0002 if any error occurs in the communication with the server.", "cb:CB0007 if any of the options is not supported." ] } ], "variables" : [ ] }, "http://zorba.io/modules/excel/text" : { "ns" : "http://zorba.io/modules/excel/text", "description" : " This is a library module offering the same set of functions\n defined by Microsoft Excel, under Text and Data Functions.\n", "sees" : [ "Excel Documentation: Text Functions" ], "authors" : [ "Sorin Nasoi" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/excel/errors", "prefix" : "excel-err" }, { "uri" : "http://zorba.io/modules/excel/math", "prefix" : "excel-math" }, { "uri" : "http://zorba.io/modules/excel/text", "prefix" : "excel-text" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "asc", "qname" : "excel-text:asc", "signature" : "($text as xs:string) as xs:string", "description" : " Returns the given $text unchanged.\n", "summary" : "

    Returns the given $text unchanged.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "text", "type" : "xs:string", "occurrence" : null, "description" : "
    the time
    " } ], "returns" : { "type" : "xs:string", "description" : "The given $text unchanged." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "char", "qname" : "excel-text:char", "signature" : "($number as xs:integer) as xs:string", "description" : " Returns the character specified by a certain codepoint.\n", "summary" : "

    Returns the character specified by a certain codepoint.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:integer", "occurrence" : null, "description" : "
    the codepoint.
    " } ], "returns" : { "type" : "xs:string", "description" : "the character specified by a certain codepoint." }, "errors" : [ "excel-err:Value provided $number must be in range [1,255]." ] }, { "isDocumented" : true, "arity" : 1, "name" : "clean", "qname" : "excel-text:clean", "signature" : "($arg as xs:string?) as xs:string?", "description" : " Removes all nonprintable characters from text.\n", "summary" : "

    Removes all nonprintable characters from text.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string.
    " } ], "returns" : { "type" : "xs:string?", "description" : "Removes all nonprintable characters from text. The CLEAN function was designed. to remove the first 32 nonprinting characters in the 7-bit ASCII code (values 0 through 31) from text.

    In the Unicode character set, there are additional nonprinting characters (values 127, 129, 141, 143, 144, and 157).

    By itself, the CLEAN function does not remove these additional nonprinting characters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "code", "qname" : "excel-text:code", "signature" : "($arg as xs:string) as xs:integer", "description" : " Returns a codepoint for the first character in a text string.\n", "summary" : "

    Returns a codepoint for the first character in a text string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : null, "description" : "
    the string.
    " } ], "returns" : { "type" : "xs:integer", "description" : "A codepoint for the first character in a text string." }, "errors" : [ "excel-err:Value Provided $arg was empty." ] }, { "isDocumented" : true, "arity" : 1, "name" : "concatenate", "qname" : "excel-text:concatenate", "signature" : "($args as xs:anyAtomicType*) as xs:string", "description" : " Joins several text strings into one text string.\n", "summary" : "

    Joins several text strings into one text string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "args", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    a sequence of strings.
    " } ], "returns" : { "type" : "xs:string", "description" : "Joins several text strings into one text string." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "concatenate", "qname" : "excel-text:concatenate", "signature" : "($arg1 as xs:anyAtomicType?, $arg2 as xs:anyAtomicType?) as xs:string", "description" : " Joins two text strings into one text string.\n", "summary" : "

    Joins two text strings into one text string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the first string.
    " }, { "name" : "arg2", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the second string.
    " } ], "returns" : { "type" : "xs:string", "description" : "Joins two text strings into one text string." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "dollar", "qname" : "excel-text:dollar", "signature" : "($number as xs:decimal) as xs:string", "description" : " Converts a number to text format and applies a currency symbol. The number of\ndigits to the right of the decimal point is 2.\n", "summary" : "

    Converts a number to text format and applies a currency symbol.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:decimal", "occurrence" : null, "description" : "
    is the number.
    " } ], "returns" : { "type" : "xs:string", "description" : "Converts a number to text format and applies a currency symbol. The number of digits to the right of the decimal point is 2." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "dollar", "qname" : "excel-text:dollar", "signature" : "($number as xs:decimal, $decimals as xs:decimal) as xs:string", "description" : " Converts a number to text format and applies a currency symbol.\n", "summary" : "

    Converts a number to text format and applies a currency symbol.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:decimal", "occurrence" : null, "description" : "
    is the number.
    " }, { "name" : "decimals", "type" : "xs:decimal", "occurrence" : null, "description" : "
    is the number of digits to the right of the decimal point.

    If decimals is negative, number is rounded to the left of the decimal point.

    " } ], "returns" : { "type" : "xs:string", "description" : "Converts a number to text format and applies a currency symbol." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "exact", "qname" : "excel-text:exact", "signature" : "($arg1 as xs:string, $arg2 as xs:string) as xs:boolean", "description" : " Compares two text strings and returns TRUE if they are exactly the same,\nFALSE otherwise. EXACT is case-sensitive but ignores formatting differences.\n", "summary" : "

    Compares two text strings and returns TRUE if they are exactly the same,\nFALSE otherwise.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:string", "occurrence" : null, "description" : "
    the first string.
    " }, { "name" : "arg2", "type" : "xs:string", "occurrence" : null, "description" : "
    the second string.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "Compares two text strings and returns TRUE if they are exactly the same, FALSE otherwise. EXACT is case-sensitive but ignores formatting differences." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "find", "qname" : "excel-text:find", "signature" : "($find_text as xs:string, $within_text as xs:string) as xs:integer?", "description" : " Locate one text string within a second text string, and return the number of the\n starting position of the first text string from the first character of the second text string.

    \n The search is case sensitive.\n", "summary" : "

    Locate one text string within a second text string, and return the number of the\n starting position of the first text string from the first character of the second text string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "find_text", "type" : "xs:string", "occurrence" : null, "description" : "
    text you want to find.
    " }, { "name" : "within_text", "type" : "xs:string", "occurrence" : null, "description" : "
    text in which you want to search for $find_text.
    " } ], "returns" : { "type" : "xs:integer?", "description" : "Locate one text string within a second text string, and return the number of the starting position of the first text string from the first character of the second text string.

    The search is case sensitive." }, "errors" : [ "excel-err:Value the value is not greater than zero or is greater than the length of within_text.", "excel-err:Value value was not found." ] }, { "isDocumented" : true, "arity" : 3, "name" : "find", "qname" : "excel-text:find", "signature" : "($find_text as xs:string, $within_text as xs:string, $start_num as xs:integer) as xs:integer?", "description" : " Locate one text string within a second text string, and return the number of the\n starting position of the first text string from the first character of the second text string.

    \n The search is case sensitive.\n", "summary" : "

    Locate one text string within a second text string, and return the number of the\n starting position of the first text string from the first character of the second text string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "find_text", "type" : "xs:string", "occurrence" : null, "description" : "
    text you want to find.
    " }, { "name" : "within_text", "type" : "xs:string", "occurrence" : null, "description" : "
    text in which you want to search for $find_text.
    " }, { "name" : "start_num", "type" : "xs:integer", "occurrence" : null, "description" : "
    specifies the character at which to start the search.
    " } ], "returns" : { "type" : "xs:integer?", "description" : "Locate one text string within a second text string, and return the number of the starting position of the first text string from the first character of the second text string.

    The search is case sensitive." }, "errors" : [ "excel-err:Value the value is not greater than zero or is greater than the length of within_text.", "excel-err:Value value was not found." ] }, { "isDocumented" : true, "arity" : 2, "name" : "fixed", "qname" : "excel-text:fixed", "signature" : "($number as xs:decimal, $decimals as xs:decimal) as xs:string", "description" : " Rounds a number to the specified number of decimals, formats the number in\n decimal format using a period and commas, and returns the result as text.\n", "summary" : "

    Rounds a number to the specified number of decimals, formats the number in\n decimal format using a period and commas, and returns the result as text.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:decimal", "occurrence" : null, "description" : "
    is the number you want to round and convert to text.
    " }, { "name" : "decimals", "type" : "xs:decimal", "occurrence" : null, "description" : "
    is the number of digits to the right of the decimal point.
    " } ], "returns" : { "type" : "xs:string", "description" : "Rounds a number to the specified number of decimals, formats the number in decimal format using a period and commas, and returns the result as text." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "fixed", "qname" : "excel-text:fixed", "signature" : "($number as xs:decimal, $decimals as xs:decimal, $no_commas as xs:boolean) as xs:string", "description" : " Rounds a number to the specified number of decimals, formats the number in\ndecimal format using a period and commas, and returns the result as text.\n", "summary" : "

    Rounds a number to the specified number of decimals, formats the number in\ndecimal format using a period and commas, and returns the result as text.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "number", "type" : "xs:decimal", "occurrence" : null, "description" : "
    is the number you want to round and convert to text.
    " }, { "name" : "decimals", "type" : "xs:decimal", "occurrence" : null, "description" : "
    is the number of digits to the right of the decimal point.
    " }, { "name" : "no_commas", "type" : "xs:boolean", "occurrence" : null, "description" : "
    is a logical value that, if TRUE, prevents FIXED from including commas in the returned text.
    " } ], "returns" : { "type" : "xs:string", "description" : "Rounds a number to the specified number of decimals, formats the number in decimal format using a period and commas, and returns the result as text." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "left", "qname" : "excel-text:left", "signature" : "($arg as xs:string) as xs:string", "description" : " Returns the first character in a text string.\n", "summary" : "

    Returns the first character in a text string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : null, "description" : "
    is the text string that contains the characters you want to extract.
    " } ], "returns" : { "type" : "xs:string", "description" : "The first character in a text string." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "left", "qname" : "excel-text:left", "signature" : "($text as xs:string, $num_chars as xs:integer) as xs:string", "description" : " Returns the first character or characters in $text, based on the number of $num_chars you specify.\n", "summary" : "

    Returns the first character or characters in $text, based on the number of $num_chars you specify.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "text", "type" : "xs:string", "occurrence" : null, "description" : "
    is the text string that contains the characters you want to extract.
    " }, { "name" : "num_chars", "type" : "xs:integer", "occurrence" : null, "description" : "
    specifies the number of characters you want to extract.
    " } ], "returns" : { "type" : "xs:string", "description" : "The first character or characters in $text, based on the number of $num_chars you specify." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "len", "qname" : "excel-text:len", "signature" : "($arg as xs:string?) as xs:integer", "description" : " Returns the number of characters in a text string.\n", "summary" : "

    Returns the number of characters in a text string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The number of characters in a text string." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "lower", "qname" : "excel-text:lower", "signature" : "($arg as xs:string?) as xs:string?", "description" : " Converts all uppercase letters in a text string to lowercase.\n", "summary" : "

    Converts all uppercase letters in a text string to lowercase.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string.
    " } ], "returns" : { "type" : "xs:string?", "description" : "Converts all uppercase letters in a text string to lowercase." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "mid", "qname" : "excel-text:mid", "signature" : "($text as xs:string?, $start_num as xs:integer, $num_chars as xs:integer) as xs:string?", "description" : " Returns a specific number of characters from a text string, starting at\nthe position you specify, based on the number of characters you specify.\n", "summary" : "

    Returns a specific number of characters from a text string, starting at\nthe position you specify, based on the number of characters you specify.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "text", "type" : "xs:string", "occurrence" : "?", "description" : "
    the text string containing the characters you want to extract.
    " }, { "name" : "start_num", "type" : "xs:integer", "occurrence" : null, "description" : "
    the position of the first character you want to extract in text. The first character in text has start_num 1, and so on.
    " }, { "name" : "num_chars", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of characters you want to return from text.
    " } ], "returns" : { "type" : "xs:string?", "description" : "A specific number of characters from a text string, starting at the position you specify, based on the number of characters you specify." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "pad-integer-to-length", "qname" : "excel-text:pad-integer-to-length", "signature" : "($toPad as xs:anyAtomicType?, $padChar as xs:string, $length as xs:integer) as xs:string", "description" : " Returns $toPad appended with enough repetitions of $padChar to make its length $length, the characters are added before the string.\n", "summary" : "

    Returns $toPad appended with enough repetitions of $padChar to make its length $length, the characters are added before the string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "toPad", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the value to be padded.
    " }, { "name" : "padChar", "type" : "xs:string", "occurrence" : null, "description" : "
    the character used for padding.
    " }, { "name" : "length", "type" : "xs:integer", "occurrence" : null, "description" : "
    the desired length.
    " } ], "returns" : { "type" : "xs:string", "description" : "$toPad appended with enough repetitions of $padChar to make its length $length, the characters are added before the string." }, "errors" : [ "excel-err:Value if the length of the $toPad is greater than the desired length." ] }, { "isDocumented" : true, "arity" : 4, "name" : "replace", "qname" : "excel-text:replace", "signature" : "($old_text as xs:string?, $start_num as xs:integer, $num_chars as xs:integer, $new_text as xs:string) as xs:string", "description" : " Replaces part of a text string, based on the number of characters you specify, with a different text string.\n", "summary" : "

    Replaces part of a text string, based on the number of characters you specify, with a different text string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "old_text", "type" : "xs:string", "occurrence" : "?", "description" : "
    is text in which you want to replace some characters.
    " }, { "name" : "start_num", "type" : "xs:integer", "occurrence" : null, "description" : "
    the position of the character in old_text that you want to replace with new_text.
    " }, { "name" : "num_chars", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of characters in old_text that you want REPLACE to replace with new_text.
    " }, { "name" : "new_text", "type" : "xs:string", "occurrence" : null, "description" : "
    the text that will replace characters in old_text.
    " } ], "returns" : { "type" : "xs:string", "description" : "Replaces part of a text string, based on the number of characters you specify, with a different text string." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "right", "qname" : "excel-text:right", "signature" : "($arg as xs:string) as xs:string", "description" : " Returns the last character in a text string.\n", "summary" : "

    Returns the last character in a text string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : null, "description" : "
    the text string containing the characters you want to extract.
    " } ], "returns" : { "type" : "xs:string", "description" : "The last character in a text string." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "right", "qname" : "excel-text:right", "signature" : "($text as xs:string, $num_chars as xs:integer) as xs:string", "description" : " Returns the last character or characters in a text string, based on the number of characters you specify.\n", "summary" : "

    Returns the last character or characters in a text string, based on the number of characters you specify.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "text", "type" : "xs:string", "occurrence" : null, "description" : "
    the text string containing the characters you want to extract.
    " }, { "name" : "num_chars", "type" : "xs:integer", "occurrence" : null, "description" : "
    specifies the number of characters you want RIGHT to extract.
    " } ], "returns" : { "type" : "xs:string", "description" : "The last character or characters in a text string, based on the number of characters you specify." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "search", "qname" : "excel-text:search", "signature" : "($find_text as xs:string, $within_text as xs:string) as xs:integer?", "description" : " Locate one text string within a second text string, and return the number of\n the starting position of the first text string from the first character of the\n second text string.

    The search starts at position 1, and it is not case sensitive.\n", "summary" : "

    Locate one text string within a second text string, and return the number of\n the starting position of the first text string from the first character of the\n second text string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "find_text", "type" : "xs:string", "occurrence" : null, "description" : "
    text you want to find.
    " }, { "name" : "within_text", "type" : "xs:string", "occurrence" : null, "description" : "
    text in which you want to search for $find_text.
    " } ], "returns" : { "type" : "xs:integer?", "description" : "Locate one text string within a second text string, and return the number of the starting position of the first text string from the first character of the second text string.

    The search starts at position 1, and it is not case sensitive." }, "errors" : [ "excel-err:Value the value is not greater than zero or is greater than the length of within_text.", "excel-err:Value value was not found." ] }, { "isDocumented" : true, "arity" : 3, "name" : "search", "qname" : "excel-text:search", "signature" : "($find_text as xs:string, $within_text as xs:string, $start_num as xs:integer) as xs:integer?", "description" : " Locate one text string within a second text string, and return the number of\n the starting position of the first text string from the first character of the\n second text string.

    The search starts at $start_num, and it is not case sensitive.\n", "summary" : "

    Locate one text string within a second text string, and return the number of\n the starting position of the first text string from the first character of the\n second text string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "find_text", "type" : "xs:string", "occurrence" : null, "description" : "
    text you want to find.
    " }, { "name" : "within_text", "type" : "xs:string", "occurrence" : null, "description" : "
    text in which you want to search for $find_text.
    " }, { "name" : "start_num", "type" : "xs:integer", "occurrence" : null, "description" : "
    the character number in within_text at which you want to start searching.
    " } ], "returns" : { "type" : "xs:integer?", "description" : "Locate one text string within a second text string, and return the number of the starting position of the first text string from the first character of the second text string.

    The search starts at $start_num, and it is not case sensitive." }, "errors" : [ "excel-err:Value the value is not greater than zero or is greater than the length of within_text.", "excel-err:Value value was not found." ] }, { "isDocumented" : true, "arity" : 3, "name" : "substitute", "qname" : "excel-text:substitute", "signature" : "($text as xs:string, $old_text as xs:string, $new_text as xs:string) as xs:string?", "description" : " Substitutes new_text for old_text in a text string. Every occurrence of old_text in text is changed to new_text.\n", "summary" : "

    Substitutes new_text for old_text in a text string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "text", "type" : "xs:string", "occurrence" : null, "description" : "
    the text or the reference to a cell containing text for which you want to substitute characters.
    " }, { "name" : "old_text", "type" : "xs:string", "occurrence" : null, "description" : "
    text you want to replace.
    " }, { "name" : "new_text", "type" : "xs:string", "occurrence" : null, "description" : "
    text you want to replace old_text with.
    " } ], "returns" : { "type" : "xs:string?", "description" : "Substitutes new_text for old_text in a text string. Every occurrence of old_text in text is changed to new_text." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "substitute", "qname" : "excel-text:substitute", "signature" : "($text as xs:string, $old_text as xs:string, $new_text as xs:string, $instance_num as xs:integer?) as xs:string", "description" : " Substitutes new_text for old_text in a text string.\n", "summary" : "

    Substitutes new_text for old_text in a text string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "text", "type" : "xs:string", "occurrence" : null, "description" : "
    the text or the reference to a cell containing text for which you want to substitute characters.
    " }, { "name" : "old_text", "type" : "xs:string", "occurrence" : null, "description" : "
    text you want to replace.
    " }, { "name" : "new_text", "type" : "xs:string", "occurrence" : null, "description" : "
    text you want to replace old_text with.
    " }, { "name" : "instance_num", "type" : "xs:integer", "occurrence" : "?", "description" : "
    specifies which occurrence of old_text you want to replace with new_text.

    Only that instance of old_text is replaced.

    " } ], "returns" : { "type" : "xs:string", "description" : "Substitutes new_text for old_text in a text string.

    Use SUBSTITUTE when you want to replace specific text in a text string; use REPLACE when you want to replace any text that occurs in a specific location in a text string." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "t", "qname" : "excel-text:t", "signature" : "($value as xs:anyAtomicType?) as xs:string", "description" : " Converts the $value to string.\n", "summary" : "

    Converts the $value to string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the value
    " } ], "returns" : { "type" : "xs:string", "description" : "Converts the $value to string." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "trim", "qname" : "excel-text:trim", "signature" : "($text as xs:string?) as xs:string?", "description" : " Removes all spaces from text except for single spaces between words.\n", "summary" : "

    Removes all spaces from text except for single spaces between words.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "text", "type" : "xs:string", "occurrence" : "?", "description" : "
    from which you want spaces removed.
    " } ], "returns" : { "type" : "xs:string?", "description" : "Removes all spaces from text except for single spaces between words." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "upper", "qname" : "excel-text:upper", "signature" : "($text as xs:string?) as xs:string?", "description" : " Converts text to uppercase.\n", "summary" : "

    Converts text to uppercase.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "text", "type" : "xs:string", "occurrence" : "?", "description" : "
    text you want converted to uppercase.
    " } ], "returns" : { "type" : "xs:string?", "description" : "Converts text to uppercase." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "value-except", "qname" : "excel-text:value-except", "signature" : "($arg1 as xs:anyAtomicType*, $arg2 as xs:anyAtomicType*) as xs:anyAtomicType*", "description" : " Returns the values in one sequence that do not appear in the second sequence in an implementation-defined order.\n", "summary" : "

    Returns the values in one sequence that do not appear in the second sequence in an implementation-defined order.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the first sequence.
    " }, { "name" : "arg2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the second sequence.
    " } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "The values in one sequence that do not appear in the second sequence in an implementation-defined order." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "value", "qname" : "excel-text:value", "signature" : "($arg as xs:anyAtomicType?) as xs:anyAtomicType?", "description" : " Converts a text string that represents a number to a number.\n", "summary" : "

    Converts a text string that represents a number to a number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the value.
    " } ], "returns" : { "type" : "xs:anyAtomicType?", "description" : "Converts a text string that represents a number to a number." }, "errors" : [ "excel-err:Value provided value is not a number." ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/http/response" : { "ns" : "http://www.28msec.com/modules/http/response", "description" : " The Sausalito response module can be used to modify the HTTP response\n that will be send as a result of this request. For example, the\n set-content-type function can be used to set the Content-Type\n header and determine the encoding of data in the response.\n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "http" }, { "uri" : "http://www.w3.org/2010/xslt-xquery-serialization", "prefix" : "output" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "resp" }, { "uri" : "http://zorba.io/modules/schema", "prefix" : "s" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "code-for-status", "qname" : "resp:code-for-status", "signature" : "($status as xs:QName) as xs:int", "description" : " Convert between the HTTP status code as QName and\n the integer value of that status code.\n", "summary" : "

    Convert between the HTTP status code as QName and\n the integer value of that status code.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "status", "type" : "xs:QName", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:int", "description" : "the integer value of the given QName as xs:int" }, "errors" : [ "http:invalid-status if the given QName does not represent a valid http status code" ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-binary", "qname" : "resp:content-type-binary", "signature" : "($type as xs:string) as xs:boolean external", "description" : "

    Test if a given content-type is a binary content-type. A\n content-type is considered to be binary if it's not a text\n content-type.

    \n", "summary" : "

    Test if a given content-type is a binary content-type.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is a binary content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-html", "qname" : "resp:content-type-html", "signature" : "($type as xs:string) as xs:boolean external", "description" : "

    Test if a given content-type is a HTML content-type, i.e.\n the content-type is the string \"text/html\".

    \n", "summary" : "

    Test if a given content-type is a HTML content-type, i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is the HTML content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-json", "qname" : "resp:content-type-json", "signature" : "($type as xs:string) as xs:boolean external", "description" : "

    Test if a given content-type is a JSON content-type, i.e.\n the content-type is the string \"application/json\".

    \n", "summary" : "

    Test if a given content-type is a JSON content-type, i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is the JSON content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-mixed-json-xml", "qname" : "resp:content-type-mixed-json-xml", "signature" : "($type as xs:string) as xs:boolean external", "description" : "

    Test if a given content-type is a mixed JSON-XML content-type, i.e.\n the content-type is the string \"application/mixed-json-xml\".

    \n", "summary" : "

    Test if a given content-type is a mixed JSON-XML content-type, i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is a mixed JSON-XML content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-text", "qname" : "resp:content-type-text", "signature" : "($type as xs:string) as xs:boolean external", "description" : "

    Test if a given content-type is a text content-type.

    \n

    A text content-type starts with \"text/\" or contains either of\n the strings \"xml\" or \"json\".

    \n", "summary" : "

    Test if a given content-type is a text content-type.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is a text content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-xhtml", "qname" : "resp:content-type-xhtml", "signature" : "($type as xs:string) as xs:boolean external", "description" : "

    Test if a given content-type is a XHTML content-type, i.e.\n the content-type is the string \"application/xhtml+xml\".

    \n", "summary" : "

    Test if a given content-type is a XHTML content-type, i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is the XHTML content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-xml", "qname" : "resp:content-type-xml", "signature" : "($type as xs:string) as xs:boolean external", "description" : "

    Test if a given content-type is a XML content-type

    \n

    A XML content-type is a content-type that is \"application/xml\"\n or ends : with the string \"+xml\".

    \n", "summary" : "

    Test if a given content-type is a XML content-type \n A XML content-type is a content-type that is \"application/xml\"\n or ends : with the string \"+xml\".

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is a XML content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "decode-binary", "qname" : "resp:decode-binary", "signature" : "() as xs:boolean external", "description" : "

    Returns the boolean indiciating whether base64Binaries returned by\n this request will be decoded.

    \n

    The default if not modified using resp:set-decode-binary is false.

    \n", "summary" : "

    Returns the boolean indiciating whether base64Binaries returned by\n this request will be decoded.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "the said boolean value" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "message-for-status", "qname" : "resp:message-for-status", "signature" : "($status as xs:QName) as xs:string", "description" : " Convert between the HTTP status code as QName and\n the name/message of that status code.\n", "summary" : "

    Convert between the HTTP status code as QName and\n the name/message of that status code.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "status", "type" : "xs:QName", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "the message of the given QName as xs:string" }, "errors" : [ "http:invalid-status if the given QName does not represent a valid http status code" ] }, { "isDocumented" : true, "arity" : 0, "name" : "serialization-parameters", "qname" : "resp:serialization-parameters", "signature" : "() as element(output:serialization-parameters)", "description" : "

    Returns the serialization parameters that are currently\n active, i.e. the ones that will be used to serialize the result\n of this request.

    \n

    This will either be the default, the defaults set when\n calling resp:set-content-type(), or the ones set by\n resp:set-serialization-parameters().

    \n", "summary" : "

    Returns the serialization parameters that are currently\n active, i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "element(output:serialization-parameters)", "description" : "the said serialization parameters" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "serializer-defaults-html", "qname" : "resp:serializer-defaults-html", "signature" : "() as element(*)*", "description" : "

    Returns an element that can be used to specify the\n settings of serialization parameters for the HTML serialization\n method.

    \n

    The defaults are\n

      \n
    • encoding: UTF-8
    • \n
    • indent: yes
    • \n
    • version: 4.01
    • \n
    • doctype-system: http://www.w3.org/TR/html4/loose.dtd
    • \n
    • doctype-public: -//W3C//DTD HTML 4.01 Transitional//EN
    • \n
    • include-content-type: yes
    • \n
    \n

    \n

    For example, those defaults are used when setting\n the content-type to some HTML content-type (i.e. text/html).

    \n", "summary" : "

    Returns an element that can be used to specify the\n settings of serialization parameters for the HTML serialization\n method.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "element(*)*", "description" : "an element that can be used to specify the above serialization parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "serializer-defaults-json-xml-hybrid", "qname" : "resp:serializer-defaults-json-xml-hybrid", "signature" : "() as element(output:serialization-parameters)", "description" : "

    Returns an element that can be used to specify the\n settings of serialization parameters for the json-xml-hybrid\n serialization method.

    \n

    The defaults are\n

      \n
    • encoding: UTF-8
    • \n
    • indent: yes
    • \n
    • method: json-xml-hybrid
    • \n
    • omit-xml-declaration: yes
    • \n
    • version: 1.0
    • \n
    \n

    \n

    For example, those defaults are used when setting\n the content-type to application/mixed-json-xml.

    \n", "summary" : "

    Returns an element that can be used to specify the\n settings of serialization parameters for the json-xml-hybrid\n serialization method.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "element(output:serialization-parameters)", "description" : "an element that can be used to specify the above serialization parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "serializer-defaults-json", "qname" : "resp:serializer-defaults-json", "signature" : "() as element(output:serialization-parameters)", "description" : "

    Returns an element that can be used to specify the\n settings of serialization parameters for the json\n serialization method.

    \n

    The defaults are\n

      \n
    • encoding: UTF-8
    • \n
    • indent: yes
    • \n
    • method: json
    • \n
    \n

    \n

    For example, those defaults are used when setting\n the content-type to some JSON content-type (e.g. application/json).

    \n", "summary" : "

    Returns an element that can be used to specify the\n settings of serialization parameters for the json\n serialization method.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "element(output:serialization-parameters)", "description" : "an element that can be used to specify the above serialization parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "serializer-defaults-text", "qname" : "resp:serializer-defaults-text", "signature" : "() as element(*)*", "description" : "

    Returns an element that can be used to specify the\n settings of serialization parameters for the text serialization\n method.

    \n

    The only default used is\n

      \n
    • encoding: UTF-8
    • \n
    \n

    \n

    For example, this default is used when setting\n the content-type to some text content-type (e.g. text/plain).

    \n", "summary" : "

    Returns an element that can be used to specify the\n settings of serialization parameters for the text serialization\n method.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "element(*)*", "description" : "an element that can be used to specify the above serialization parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "serializer-defaults-xhtml", "qname" : "resp:serializer-defaults-xhtml", "signature" : "() as element(*)*", "description" : "

    Returns an element that can be used to specify the\n settings of serialization parameters for the XHTML serialization\n method.

    \n

    The defaults are\n

      \n
    • encoding: UTF-8
    • \n
    • indent: yes
    • \n
    • omit-xml-declaration: yes
    • \n
    • version: 1.0
    • \n
    • doctype-system: http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
    • \n
    • doctype-public: -//W3C//DTD XHTML 1.0 Transitional//EN
    • \n
    \n

    \n

    For example, those defaults are used when setting\n the content-type to some XHTML content-type (i.e. application/xhtml+xml).

    \n", "summary" : "

    Returns an element that can be used to specify the\n settings of serialization parameters for the XHTML serialization\n method.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "element(*)*", "description" : "an element that can be used to specify the above serialization parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "serializer-defaults-xml", "qname" : "resp:serializer-defaults-xml", "signature" : "() as element(output:serialization-parameters)", "description" : "

    Returns an element that can be used to specify the\n settings of serialization parameters for the XML serialization\n method.

    \n

    The defaults are\n

      \n
    • encoding: UTF-8
    • \n
    • indent: yes
    • \n
    • omit-xml-declaration: yes
    • \n
    • version: 1.0
    • \n
    \n

    \n

    For example, those defaults are used when setting\n the content-type to some XML content-type (e.g. application/atom+xml).

    \n", "summary" : "

    Returns an element that can be used to specify the\n settings of serialization parameters for the XML serialization\n method.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "element(output:serialization-parameters)", "description" : "an element that can be used to specify the above serialization parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "set-content-type", "qname" : "resp:set-content-type", "signature" : "($type as xs:string) as empty-sequence()", "description" : "

    Sets the Content-Type header for the response.

    \n

    \n For example,\n resp:set-content-type(\"text/plain\") will cause the\n header\n Content-Type: text/plain to be added for the response.

    \n

    In addtion to setting the Content-Type header, the function also\n sets the serialization parameters to the default values for serialization\n method for the given content-type. For example, if the content-type is set to\n text/plain, the default serialization parameters for the text\n serialization method will be used. For application/atom+xml, the default\n serialization parameters for the XML serialization method will be used.

    \n

    The functions resp:content-type-text/xml/html/xhtml/binary may be used\n to figure out which serialization method will be used for a specific\n content-type.

    \n

    If the given content-type contains a charset declaration (e.g.\n resp:set-content-type(\"text/plain;charset=ISO-8859-1\")), the\n content of the response will be transcoded to the given encoding.

    \n

    The default serialization parameters set by this function can\n be overwritten using the resp:set-serialization-parameters() function.

    \n", "summary" : "

    Sets the Content-Type header for the response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to be set
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and returns the empty sequence" }, "errors" : [ "http:invalid-encoding if the given encoding is invalid or not supported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "set-content-type", "qname" : "resp:set-content-type", "signature" : "($type as xs:string, $params as element(output:serialization-parameters)) as empty-sequence()", "description" : "

    Sets the Content-Type header for the response.

    \n

    For example,\n resp:set-content-type(\"text/plain\") will cause the\n header\n Content-Type: text/plain to be added for the response.

    \n

    In addition to the content-type, the function also allows to\n specify the serialization method and parameters that will be used\n for serializing the result. For details about this parameter, please\n refer to resp:set-serialization-parameters().

    \n

    If the given content-type contains a charset declaration (e.g.\n resp:set-content-type(\"text/plain;charset=ISO-8859-1\")), the\n content of the response will be transcoded to the given encoding.\n If the serialization parameters also contain a charset declaration,\n the charset contained in the content-type will be used. to transcode\n the result.

    \n", "summary" : "

    Sets the Content-Type header for the response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to be set
    " }, { "name" : "params", "type" : "element(output:serialization-parameters)", "occurrence" : null, "description" : "
    the serialization parameters that will be used for serialization the result.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and returns the empty sequence" }, "errors" : [ "http:invalid-encoding if the given encoding is invalid or not supported." ] }, { "isDocumented" : true, "arity" : 1, "name" : "set-decode-binary", "qname" : "resp:set-decode-binary", "signature" : "($decode as xs:boolean) as empty-sequence() external", "description" : "

    If this function is invoked with true, the result of the request\n will not be serialized. Instead, the result will be the binary values\n of any item that is of type xs:base64Binary. The values of all other\n items will not be part of the result.

    \n

    Please note that all serialization parameters which have been set using\n resp:set-serialization-parameters will be ignored. Also, the output encoding\n is ignored for binaries.

    \n", "summary" : "

    If this function is invoked with true, the result of the request\n will not be serialized.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "decode", "type" : "xs:boolean", "occurrence" : null, "description" : "
    boolean value indicating whether base64Binaries should be decoded.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and returns the empty sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "set-encoding", "qname" : "resp:set-encoding", "signature" : "($encoding as xs:string) as empty-sequence() external", "description" : "

    The function sets the output encoding that will be\n used for the payload of the response.

    \n

    For example,\n resp:set-encoding(\"ISO-8859-1\") will cause the\n content in the response to be encoded using ISO-8859-1.

    \n

    Please note that the encoding only applies to textual data.\n It is not used if the function set-decode-binary()\n was invoked passing true as parameter.

    \n", "summary" : "

    The function sets the output encoding that will be\n used for the payload of the response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "
    the encoding to be used for the payload of the response.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and returns the empty sequence" }, "errors" : [ "http:invalid-encoding if the given encoding is invalid or not supported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "set-header-impl", "qname" : "resp:set-header-impl", "signature" : "($name as xs:string, $value as xs:string) as xs:string? external", "description" : "

    Set an HTTP header in the response.

    \n

    This function is only used for internal purposes and should\n not be called by the user.

    \n", "summary" : "

    Set an HTTP header in the response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name for the header to set
    " }, { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    the value for the header to set
    " } ], "returns" : { "type" : "xs:string?", "description" : "the value of the header previously set or the empty sequence if no header has been set with the same name." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "set-header", "qname" : "resp:set-header", "signature" : "($name as xs:string, $value as xs:string) as xs:string?", "description" : "

    Set a HTTP header in the response.

    \n

    If a header with the same name was already set, the\n value is overwritten and the function returns the old value. As defined\n in the HTTP specification, multiple headers with the same name\n can be combined into one header whose value is a comma-separated\n list of the values.

    \n

    The following headers must not be set using this function.\n Instead, other functions of this module should be used in order\n to implemented the required semantics:\n

      \n
    • Status: use set-status() instead
    • \n
    • Content-Type: use set-content-type() instead
    • \n
    \n

    \n", "summary" : "

    Set a HTTP header in the response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the header to set
    " }, { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    the value of the header to set `
    " } ], "returns" : { "type" : "xs:string?", "description" : "the value of the header previously set or the empty sequence if no header has been set with the same name." }, "errors" : [ "resp:invalid-header-name if an invalid name is used for the header." ] }, { "isDocumented" : true, "arity" : 1, "name" : "set-redirect", "qname" : "resp:set-redirect", "signature" : "($url as xs:string) as empty-sequence()", "description" : " This function sets the HTTP 302 redirect status code in the response. As\n a result, a redirect to the URL given as parameter will be made.\n", "summary" : "

    This function sets the HTTP 302 redirect status code in the response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "url", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL to which the redirect will be made.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The empty-sequence is returned." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "set-serialization-parameters", "qname" : "resp:set-serialization-parameters", "signature" : "($params as element(output:serialization-parameters)) as empty-sequence()", "description" : "

    Set the serialization parameters used for serializing the result\n of the request.

    \n

    The following example shows how to set several options\n for the HTML serialization method. Specifically, it sets the\n HTML method to HTML 4.01, set the doctype-system and\n doctype-public makes sure that the output is indented. In addition,\n the output is UTF-8 encoded and\n

    \n <output:serialization-parameters>\n   <output:encoding value=\"UTF-8\"/>\n   <output:doctype-system value=\"http://www.w3.org/TR/html4/loose.dtd\"/>\n   <output:doctype-public value=\"-//W3C//DTD HTML 4.01 Transitional//EN\"/>\n </output:serialization-parameters>\n 
    \n

    \n

    The element passed as parameter need to be valid according\n to the schema http://www.w3.org/2010/xslt-xquery-serialization. This\n function validates its input (if it has not already been validated)\n and may raise an error if the input is not valid.

    \n

    Please note that serialization options set by this function can\n be overwritten by a subsequent call to resp:set-content-type. In this\n case, the options will be reset to the default for the given\n content-type. Also note, that the output encoding can be overwritten\n by subsequently calling the resp:set-encoding function.

    \n", "summary" : "

    Set the serialization parameters used for serializing the result\n of the request.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "params", "type" : "element(output:serialization-parameters)", "occurrence" : null, "description" : "
    the serialization parameters that will be used to serialize the result of the request
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and, on success, returns the empty sequence." }, "errors" : [ "err:XQDY0027 if the input is not valid according to the schema http://www.w3.org/2010/xslt-xquery-serialization.", "http:invalid-encoding if the encoding specified in the serialization options is invalid or not supported." ] }, { "isDocumented" : true, "arity" : 1, "name" : "set-status-code", "qname" : "resp:set-status-code", "signature" : "($status as xs:integer) as empty-sequence() external", "description" : "

    Sets the status code of the HTTP response to the integer given as\n parameter.

    \n For example,\n resp:set-status(204)\n will result in \"HTTP/1.1 204 No Content\".\n", "summary" : "

    Sets the status code of the HTTP response to the integer given as\n parameter.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "status", "type" : "xs:integer", "occurrence" : null, "description" : "
    The status code of the HTTP response as integer.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "On success, the empty-sequence is returned" }, "errors" : [ "http:invalid-status-code if the given integer does not reflect a valid HTTP status code" ] }, { "isDocumented" : true, "arity" : 1, "name" : "set-status", "qname" : "resp:set-status", "signature" : "($status as xs:QName) as empty-sequence()", "description" : "

    Sets the status code of the HTTP response to the QName given as\n parameter.

    \n For example,\n resp:set-status($http:no-content)\n will result in \"HTTP/1.1 204 No Content\".\n", "summary" : "

    Sets the status code of the HTTP response to the QName given as\n parameter.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "status", "type" : "xs:QName", "occurrence" : null, "description" : "
    The status code of the HTTP response as a QName (e.g. $http:no-content)
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "On success, the empty-sequence is returned" }, "errors" : [ "http:invalid-status if the given QName does not represent a valid HTTP status code;" ] }, { "isDocumented" : true, "arity" : 1, "name" : "valid-status", "qname" : "resp:valid-status", "signature" : "($status as xs:QName) as xs:boolean", "description" : " Test whether the given QName refers to a valid HTTP status code.\n", "summary" : "

    Test whether the given QName refers to a valid HTTP status code.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "status", "type" : "xs:QName", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given QName refers to a valid HTTP status code, false otherwise." }, "errors" : [ ] } ], "variables" : [ { "name" : "http:precondition-required", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 428 Precondition Required (RFC 6585)\n" }, { "name" : "http:gone", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 410 GONE\n" }, { "name" : "http:length-required", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 411 Length Required\n" }, { "name" : "http:precondition-failed", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 412 Precondition Failed\n" }, { "name" : "http:request-entity-too-large", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 413 Request Entity Too Large\n" }, { "name" : "http:request-entity-too-long", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 414 Request Entity Too Long\n" }, { "name" : "http:unsupported-media-type", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 415 Unsupported Media Type\n" }, { "name" : "http:request-range-not-satisfiable", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 416 Request Range Not Satisfiable\n" }, { "name" : "http:expectation-failed", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 417 Expectation Failed\n" }, { "name" : "http:im-a-teapot", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 418 I'm a teapot (RFC 2324)\n" }, { "name" : "http:enhance-your-calm", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 420 Enhance Your Calm\n" }, { "name" : "http:unprocessable-entity", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 422 Unprocessable Entity (WebDAV; RFC 4918)\n" }, { "name" : "http:locked", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 423 Locked (WebDAV; RFC 4918)\n" }, { "name" : "http:failed-dependency", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 424 Failed Dependency (WebDAV; RFC 4918)\n" }, { "name" : "http:unordered-collection", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 425 Unordered Collection\n" }, { "name" : "http:upgrade-required", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 426 Upgrade Required\n" }, { "name" : "http:conflict", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 409 Conflict\n" }, { "name" : "http:too-many-requests", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 429 Too Many Requests (RFC 6585)\n" }, { "name" : "http:request-header-fields-too-large", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 431 Request Header Fields Too Large (RFC 6585)\n" }, { "name" : "http:internal-server-error", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 500 Internal Server Error\n" }, { "name" : "http:not-implemented", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 501 Not Implemented\n" }, { "name" : "http:bad-gateway", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 502 Bad Gateway\n" }, { "name" : "http:service-unavailable", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 503 Service Unavailable\n" }, { "name" : "http:gateway-timeout", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 504 Gateway Timeout\n" }, { "name" : "http:http-version-not-supported", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 505 HTTP Version Not Supported\n" }, { "name" : "http:variant-also-negotiates", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 506 Variant Also Negotiates (RFC 2295)\n" }, { "name" : "http:insufficient-storage", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 507 Insufficient Storage (WebDAV; RFC 4918)\n" }, { "name" : "http:loop-detected", "type" : "xs:QName", "description" : " QName representing the HTTP status code 508 Loop Detected (webdav; rfc 5842)\n" }, { "name" : "http:not-extended", "type" : "xs:QName", "description" : " QName representing the HTTP status code 510 Not Extended (RFC 2774)\n" }, { "name" : "http:network-authentication-required", "type" : "xs:QName", "description" : " QName representing the HTTP status code 511 Network Authentication Required (RFC 6585)\n" }, { "name" : "resp:status-info", "type" : "item()*", "description" : " Variable containing a description for all the HTTP Status Codes\n" }, { "name" : "http:see-other", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 303 See Other\n" }, { "name" : "http:switching-protocols", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 101 Switching Protocols\n" }, { "name" : "http:processing", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 102 Processing (Web; RFC 2518)\n" }, { "name" : "http:ok", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 200 OK\n" }, { "name" : "http:created", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 201 Created\n" }, { "name" : "http:accepted", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 202 Accepted\n" }, { "name" : "http:non-authoritative", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 203 Non-Authoritative\n" }, { "name" : "http:no-content", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 204 No Content\n" }, { "name" : "http:reset-content", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 205 Reset Content\n" }, { "name" : "http:partial-content", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 206 Partial Content\n" }, { "name" : "http:multi-status", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 207 Multi-Status (WebDAV; RFC 5842)\n" }, { "name" : "http:already-reported", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 208 Already Reported (WebDAV; RFC 5842)\n" }, { "name" : "http:im-used", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 226 IM Used (RFC 3229)\n" }, { "name" : "http:multiple-choices", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 300 Multiple Choices\n" }, { "name" : "http:moved-permanently", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 301 Moved Permantently\n" }, { "name" : "http:found", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 302 Found\n" }, { "name" : "http:continue", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 100 Continue\n" }, { "name" : "http:not-modified", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 304 Not Modified\n" }, { "name" : "http:use-proxy", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 305 Use Proxy\n" }, { "name" : "http:switch-proxy", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 306 Switch Proxy\n" }, { "name" : "http:temporary-redirect", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 307 Temporary Redirect\n" }, { "name" : "http:permanent-redirect", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 308 Permanent Redirect (http://tools.ietf.org/html/draft-reschke-http-status-308-07)\n" }, { "name" : "http:bad-request", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 400 Bad Request\n" }, { "name" : "http:unauthorized", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 401 Unauthorized\n" }, { "name" : "http:payment-required", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 402 Payment Required\n" }, { "name" : "http:forbidden", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 403 Forbidden\n" }, { "name" : "http:not-found", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 404 Not Found\n" }, { "name" : "http:not-allowed", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 405 Not Allowed\n" }, { "name" : "http:not-acceptable", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 406 Not Acceptable\n" }, { "name" : "http:proxy-authentication-required", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 407 Proxy Authentication Required\n" }, { "name" : "http:request-timeout", "type" : "xs:QName", "description" : " QName representing the HTTP Status Code 408 Request Timeout\n" } ] }, "http://zorba.io/modules/uri" : { "ns" : "http://zorba.io/modules/uri", "description" : " This module provides functions for processing URIs and URLs.\n", "sees" : [ ], "authors" : [ "Matthias Brantner, Luis Rodriguez Gonzalez" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/uri", "prefix" : "uri" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "decode", "qname" : "uri:decode", "signature" : "($u as xs:string) as xs:string", "description" : " Percent-decodes (aka URL decoding) the given string.\n All percent encoded octets will be translated into their\n decoded UTF-8 representation.\n Please note that the percent encoding guarantees that a string\n consists of ASCII characters only. Passing a string that contains\n non-ASCII characters results in undefined behavior.\n", "summary" : "

    Percent-decodes (aka URL decoding) the given string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "u", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "the percent decoded string" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "decode", "qname" : "uri:decode", "signature" : "($u as xs:string, $decode-plus as xs:boolean) as xs:string", "description" : " Percent-decodes (aka URL decoding) the given string.\n All percent encoded octets will be translated into their\n decoded UTF-8 representation.\n If $decode-plus is specified all occurrences of the char '+'\n will be replaced with a space ' ' before the percent decoding\n happens.\n Please note that the percent encoding guarantees that a string\n consists of ASCII characters only. Passing a string that contains\n non-ASCII characters results in undefined behavior.\n", "summary" : "

    Percent-decodes (aka URL decoding) the given string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "u", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "decode-plus", "type" : "xs:boolean", "occurrence" : null, "description" : "
    whether '+' chars will be replaced with spaces
    " } ], "returns" : { "type" : "xs:string", "description" : "the percent decoded string" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "decode", "qname" : "uri:decode", "signature" : "($s as xs:string, $decode-plus as xs:boolean, $charset as xs:string) as xs:string external", "description" : " Percent-decodes (aka URL decoding) the given string.\n All percent encoded octets will be translated into their\n decoded UTF-8 representation.\n If $decode-plus is specified all occurrences of the char '+'\n will be replaced with a space ' ' before the percent decoding\n happens.\n The $charset parameter specifies the source charset after precent\n decoding. It is used to convert the decoded string into UTF-8.\n Please note that the percent encoding guarantees that a string\n consists of ASCII characters only. Passing a string that contains\n non-ASCII characters results in undefined behavior.\n", "summary" : "

    Percent-decodes (aka URL decoding) the given string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "xs:string", "occurrence" : null, "description" : "
    the string to decode
    " }, { "name" : "decode-plus", "type" : "xs:boolean", "occurrence" : null, "description" : "
    whether '+' chars will be replaced with spaces
    " }, { "name" : "charset", "type" : "xs:string", "occurrence" : null, "description" : "
    the source charset of the string after percent decoding
    " } ], "returns" : { "type" : "xs:string", "description" : "the percent decoded string" }, "errors" : [ "uri:CHARSET_UNKNOWN if the given charset is unknown or not supported", "zerr:ZOSE0006 if there is an error transcoding the string" ] }, { "isDocumented" : true, "arity" : 1, "name" : "parse", "qname" : "uri:parse", "signature" : "($uri as xs:string) as object() external", "description" : " Parses the URI passed as string. The returned object\n contains only members with field names declared as constants in\n this module.\n For example,\n
    \n let my-uri := \"http://www.my.project.com/a/b/c?user=john;pass=1234#profile\"\n return uri:parse(my-uri)\n 
    \n returns\n
    \n { \"squeme\" : \"http\", \"host\" : \"www.my.project.com\", \"path\" : \"/a/b/c\",\n   \"query\" : \"user=john;pass=123\", \"fragment\" : \"profile\" }\n 
    \n", "summary" : "

    Parses the URI passed as string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    the URI to parse
    " } ], "returns" : { "type" : "object()", "description" : "the JSON object" }, "errors" : [ "err:XQST0046 if the URI is textually invalid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "serialize", "qname" : "uri:serialize", "signature" : "($uri as object()) as xs:string external", "description" : " Serialize the URI passed as object into a string.\n", "summary" : "

    Serialize the URI passed as object into a string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "object()", "occurrence" : null, "description" : "
    the object representing the URI
    " } ], "returns" : { "type" : "xs:string", "description" : "the URI as string" }, "errors" : [ "uri:OPAQUE_COMB_NOT_VALID if opaque part is specified in conjunction with host/port/path/user-info/query.", "uri:OPAQUE_WITHOUT_SCHEME if opaque part is present but no scheme is present.", "uri:INVALID_ABSOLUTE_PATH if a path component for an absolute URI doesn't start with \"/\"." ] } ], "variables" : [ { "name" : "uri:SCHEME", "type" : "xs:string", "description" : " Constant for the \"scheme\" part of a URI object.\n" }, { "name" : "uri:AUTHORITY", "type" : "xs:string", "description" : " Constant for the \"authority\" part of a URI object.\n" }, { "name" : "uri:USER-INFO", "type" : "xs:string", "description" : " Constant for the \"user-info\" part of a URI object.\n" }, { "name" : "uri:HOST", "type" : "xs:string", "description" : " Constant for the \"host\" part of a URI object.\n" }, { "name" : "uri:PORT", "type" : "xs:string", "description" : " Constant for the \"port\" part of a URI object.\n" }, { "name" : "uri:PATH", "type" : "xs:string", "description" : " Constant for the \"path\" part of a URI object.\n" }, { "name" : "uri:QUERY", "type" : "xs:string", "description" : " Constant for the \"query\" part of a URI object.\n" }, { "name" : "uri:FRAGMENT", "type" : "xs:string", "description" : " Constant for the \"fragment\" part of a URI object.\n" }, { "name" : "uri:OPAQUE-PART", "type" : "xs:string", "description" : " Constant for the \"opaque-part\" part of a URI object.\n If this is set in a URI object, then none of $uri:PATH, $uri:HOST,\n $uri:PORT, $uri:USER-INFO, or : $uri:QUERY may be specified.\n If this is set in a URI object, $uri:SCHEME must also be specified\n (ie, it must be an absolute URI).\n" } ] }, "http://xbrl.io/modules/bizql/profiles/sec/fiscal/core" : { "ns" : "http://xbrl.io/modules/bizql/profiles/sec/fiscal/core", "description" : "

    This module provides functionality for querying fiscal reports (10-K, 10-Q)\n submitted to the SEC.

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/archives", "prefix" : "archives" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/companies", "prefix" : "companies" }, { "uri" : "http://xbrl.io/modules/bizql/components", "prefix" : "components" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://xbrl.io/modules/bizql/facts", "prefix" : "facts" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/filings", "prefix" : "filings" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/fiscal/core", "prefix" : "fiscal-core" }, { "uri" : "http://jsoniq.org/function-library", "prefix" : "j" }, { "uri" : "http://www.28msec.com/modules/mongodb", "prefix" : "mongo" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/core", "prefix" : "sec" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/networks", "prefix" : "sec-networks" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 3, "name" : "balance-sheets-for-fiscal-periods-and-years", "qname" : "fiscal-core:balance-sheets-for-fiscal-periods-and-years", "signature" : "($entity-or-ids as item()*, $fiscal-period-focus as string*, $fiscal-year-focus as integer*) as object()*", "description" : "

    Retrieves the balance sheet for the given entities and fiscal periods and years.

    \n", "summary" : "

    Retrieves the balance sheet for the given entities and fiscal periods and years.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "entity-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a list of entities or their EIDs.
    " }, { "name" : "fiscal-period-focus", "type" : "string", "occurrence" : "*", "description" : "
    the periods (YTD1, YTD2, YTD3, Q1, Q2, Q3 or FY) or $fiscal-core:ALL_FISCAL_PERIODS to accept all.
    " }, { "name" : "fiscal-year-focus", "type" : "integer", "occurrence" : "*", "description" : "
    the years (2012) or $fiscal-core:ALL_FISCAL_YEARS to accept all.
    " } ], "returns" : { "type" : "object()*", "description" : "the balance sheet at that date and for that formType." }, "errors" : [ "entities:INVALID_PARAMETER if the CIK or entity is not valid." ] }, { "isDocumented" : true, "arity" : 3, "name" : "facts-for-aspects-and-fiscal-periods-and-years", "qname" : "fiscal-core:facts-for-aspects-and-fiscal-periods-and-years", "signature" : "($aspects as object()?, $fiscal-period-focus as string*, $fiscal-year-focus as integer*) as object()*", "description" : "

    Retrieves facts for the given aspects, fiscal periods and years.

    \n", "summary" : "

    Retrieves facts for the given aspects, fiscal periods and years.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "aspects", "type" : "object()", "occurrence" : "?", "description" : "
    an object containing aspects to filter, among which xbrl:Concept, xbrl:Entity and xbrl:Period (all optional).
    " }, { "name" : "fiscal-period-focus", "type" : "string", "occurrence" : "*", "description" : "
    the periods (YTD1, YTD2, YTD3, Q1, Q2, Q3 or FY).
    " }, { "name" : "fiscal-year-focus", "type" : "integer", "occurrence" : "*", "description" : "
    the years (2012)
    " } ], "returns" : { "type" : "object()*", "description" : "all facts matching the given aspects, fiscal period and year." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "facts-for-aspects-and-fiscal-periods-and-years", "qname" : "fiscal-core:facts-for-aspects-and-fiscal-periods-and-years", "signature" : "($aspects as object()?, $fiscal-period-focus as string*, $fiscal-year-focus as integer*, $options as object()?) as object()*", "description" : "

    Retrieves facts for the given aspects, fiscal periods and years.

    \n", "summary" : "

    Retrieves facts for the given aspects, fiscal periods and years.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "aspects", "type" : "object()", "occurrence" : "?", "description" : "
    an object containing aspects to filter, among which xbrl:Concept, xbrl:Entity and xbrl:Period (all optional).
    " }, { "name" : "fiscal-period-focus", "type" : "string", "occurrence" : "*", "description" : "
    the periods (YTD1, YTD2, YTD3, Q1, Q2, Q3 or FY) or $fiscal-core:ALL_FISCAL_PERIODS to accept all.
    " }, { "name" : "fiscal-year-focus", "type" : "integer", "occurrence" : "*", "description" : "
    the years (2012) or $fiscal-core:ALL_FISCAL_YEARS to accept all.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "all facts matching the given aspects, fiscal period and year." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "facts-for-entities-and-concepts-and-fiscal-periods-and-years", "qname" : "fiscal-core:facts-for-entities-and-concepts-and-fiscal-periods-and-years", "signature" : "($entities-or-ids as item()*, $concepts as string*, $fiscal-period-focus as string*, $fiscal-year-focus as integer*) as object()*", "description" : "

    Retrieves facts for the given entities, concepts, fiscal periods and years.

    \n", "summary" : "

    Retrieves facts for the given entities, concepts, fiscal periods and years.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "entities-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a list of entities or their EIDs.
    " }, { "name" : "concepts", "type" : "string", "occurrence" : "*", "description" : "
    a list of concept names (us-gaap:Assets)
    " }, { "name" : "fiscal-period-focus", "type" : "string", "occurrence" : "*", "description" : "
    the periods (YTD1, YTD2, YTD3, Q1, Q2, Q3 or FY) or $fiscal-core:ALL_FISCAL_PERIODS to accept all.
    " }, { "name" : "fiscal-year-focus", "type" : "integer", "occurrence" : "*", "description" : "
    the years (2012) or $fiscal-core:ALL_FISCAL_YEARS to accept all.
    " } ], "returns" : { "type" : "object()*", "description" : "all facts matching entities, concepts, fiscal periods and years" }, "errors" : [ "entities:INVALID_PARAMETER if the CIK or entity is not valid." ] }, { "isDocumented" : true, "arity" : 5, "name" : "facts-for-entities-and-concepts-and-fiscal-periods-and-years", "qname" : "fiscal-core:facts-for-entities-and-concepts-and-fiscal-periods-and-years", "signature" : "($entities-or-ids as item()*, $concepts as string*, $fiscal-period-focus as string*, $fiscal-year-focus as integer*, $options as object()?) as object()*", "description" : "

    Retrieves facts for the given entities, concepts, fiscal periods and years.

    \n", "summary" : "

    Retrieves facts for the given entities, concepts, fiscal periods and years.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "entities-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a list of entities or their EIDs.
    " }, { "name" : "concepts", "type" : "string", "occurrence" : "*", "description" : "
    a list of concept names (us-gaap:Assets)
    " }, { "name" : "fiscal-period-focus", "type" : "string", "occurrence" : "*", "description" : "
    the periods (YTD1, YTD2, YTD3, Q1, Q2, Q3 or FY) or $fiscal-core:ALL_FISCAL_PERIODS to accept all.
    " }, { "name" : "fiscal-year-focus", "type" : "integer", "occurrence" : "*", "description" : "
    the years (2012) or $fiscal-core:ALL_FISCAL_YEARS to accept all.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "all facts matching entities, concepts, fiscal periods and years" }, "errors" : [ "entities:INVALID_PARAMETER if the CIK or entity is not valid." ] }, { "isDocumented" : true, "arity" : 3, "name" : "filings-for-entities-and-fiscal-periods-and-years", "qname" : "fiscal-core:filings-for-entities-and-fiscal-periods-and-years", "signature" : "($entities-or-ids as item()*, $fiscal-period-focus as string*, $fiscal-year-focus as integer*) as object()*", "description" : "

    Retrieves all filings by entities and for given fiscal periods and years.

    \n", "summary" : "

    Retrieves all filings by entities and for given fiscal periods and years.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "entities-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    entities or their ids.
    " }, { "name" : "fiscal-period-focus", "type" : "string", "occurrence" : "*", "description" : "
    fiscal periods (FY, YTD1, YTD2, YTD3, Q1, Q2, Q3, Q4) or $fiscal-core:ALL_FISCAL_PERIODS to accept all..
    " }, { "name" : "fiscal-year-focus", "type" : "integer", "occurrence" : "*", "description" : "
    fiscal years or $fiscal-core:ALL_FISCAL_YEARS to accept all..
    " } ], "returns" : { "type" : "object()*", "description" : "all filings that match the criteria." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "fiscal-period", "qname" : "fiscal-core:fiscal-period", "signature" : "($filing-fact-or-id as item()?) as string?", "description" : "

    Retrieves the fiscal period of a filing or a fact.

    \n", "summary" : "

    Retrieves the fiscal period of a filing or a fact.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filing-fact-or-id", "type" : "item()", "occurrence" : "?", "description" : "
    a filing, a fact, or its id.
    " } ], "returns" : { "type" : "string?", "description" : "the fiscal period (FY, YTD2, YTD3, Q1, Q2 or Q3)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "fiscal-year", "qname" : "fiscal-core:fiscal-year", "signature" : "($filing-fact-or-id as item()?) as integer?", "description" : "

    Retrieves the fiscal year of a filing or a fact.

    \n", "summary" : "

    Retrieves the fiscal year of a filing or a fact.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filing-fact-or-id", "type" : "item()", "occurrence" : "?", "description" : "
    a filing, a fact, or its id.
    " } ], "returns" : { "type" : "integer?", "description" : "the fiscal year (e.g., 2012)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "latest-reported-fiscal-period", "qname" : "fiscal-core:latest-reported-fiscal-period", "signature" : "($entity-or-id as item()) as object()*", "description" : "

    Retrieves the latest reported fiscal period and year for the\n supplied entity.

    \n", "summary" : "

    Retrieves the latest reported fiscal period and year for the\n supplied entity.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "entity-or-id", "type" : "item()", "occurrence" : null, "description" : "
    an entity or its EID.
    " } ], "returns" : { "type" : "object()*", "description" : "an object with two fields: period and year." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "latest-reported-fiscal-period", "qname" : "fiscal-core:latest-reported-fiscal-period", "signature" : "($entity-or-id as item(), $type as string) as object()*", "description" : "

    Retrieves the latest fiscal period and year for the\n supplied entity.

    \n", "summary" : "

    Retrieves the latest fiscal period and year for the\n supplied entity.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "entity-or-id", "type" : "item()", "occurrence" : null, "description" : "
    an entity or its EID.
    " }, { "name" : "type", "type" : "string", "occurrence" : null, "description" : "
    10-K or 10-Q or FY, YTD1, YTD2, YTD3, Q1, Q2, or Q3.
    " } ], "returns" : { "type" : "object()*", "description" : "an object with two fields: period and year." }, "errors" : [ ] } ], "variables" : [ { "name" : "fiscal-core:ALL_FISCAL_PERIODS", "type" : "string", "description" : " Joker for all fiscal periods.\n" }, { "name" : "fiscal-core:ALL_FISCAL_YEARS", "type" : "integer", "description" : " Joker for all fiscal years.\n" } ] }, "http://zorba.io/modules/base64" : { "ns" : "http://zorba.io/modules/base64", "description" : "

    Base64 encoding and decoding.

    \n", "sees" : [ ], "authors" : [ "Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/base64", "prefix" : "base64" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "decode", "qname" : "base64:decode", "signature" : "($base64 as base64Binary) as string external", "description" : "

    Decode a base64Binary.

    \n

    The function assumes that the content after decoding is valid\n UTF-8.

    \n", "summary" : "

    Decode a base64Binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "base64", "type" : "base64Binary", "occurrence" : null, "description" : "
    The base64Binary item to decode
    " } ], "returns" : { "type" : "string", "description" : "the base64-decoded value as string" }, "errors" : [ "zerr:ZOSE0006 if $base64 contains invalid base-64 data." ] }, { "isDocumented" : true, "arity" : 2, "name" : "decode", "qname" : "base64:decode", "signature" : "($base64 as base64Binary, $encoding as string) as string external", "description" : "

    Decode a base64Binary.

    \n

    The function assumes that the content after decoding has\n the given encoding.

    \n", "summary" : "

    Decode a base64Binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "base64", "type" : "base64Binary", "occurrence" : null, "description" : "
    The base64Binary item to decode
    " }, { "name" : "encoding", "type" : "string", "occurrence" : null, "description" : "
    The encoding of the string after base64-decoding it. The encoding parameter is case insensitive.
    " } ], "returns" : { "type" : "string", "description" : "the base64-decoded value as a string" }, "errors" : [ "zerr:ZXQP0006 if the given encoding is invalid or not supported. \"ASCII\" and \"UTF-8\" are guaranteed to be supported; other encodings may be supported depending on the installation.", "zerr:ZOSE0006 if $base64 contains invalid base-64 data." ] }, { "isDocumented" : true, "arity" : 1, "name" : "encode", "qname" : "base64:encode", "signature" : "($string as string) as base64Binary external", "description" : "

    Encode a string as base64Binary.

    \n", "summary" : "

    Encode a string as base64Binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "string", "type" : "string", "occurrence" : null, "description" : "
    The item whose string-value should be encoded
    " } ], "returns" : { "type" : "base64Binary", "description" : "the base64-encoded string-value of the item parameter" }, "errors" : [ ] } ], "variables" : [ ] }, "http://xbrl.io/modules/bizql/networks" : { "ns" : "http://xbrl.io/modules/bizql/networks", "description" : "

    This module provides functionality for handling networks.

    \n

    A network is a graph of concepts and resources, of which the edges\n share the same semantics.

    \n

    There are several kinds of networks.\n A network can be a tree or a DAG of concepts. It can be a bipartite\n graph mapping concepts to resources.

    \n

    XBRL defines a number of standard networks: presentation, calculation,\n definition (essence-alias, general-special, requires-element, similar-tuples, domain-member),\n and label networks.

    \n

    With this module, you can retrieve the networks contained in a component, and you\n can retrieve a standard XBRL network with the provided short names.

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/components", "prefix" : "components" }, { "uri" : "http://xbrl.io/modules/bizql/networks", "prefix" : "networks" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "networks-for-components-and-short-names", "qname" : "networks:networks-for-components-and-short-names", "signature" : "($components as item()*, $short-name as string*) as object()*", "description" : "

    Retrieves the standardized networks in the supplied components with the given short names.

    \n", "summary" : "

    Retrieves the standardized networks in the supplied components with the given short names.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "components", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of components.
    " }, { "name" : "short-name", "type" : "string", "occurrence" : "*", "description" : "
    the short names of the networks.
    " } ], "returns" : { "type" : "object()*", "description" : "the standardized networks with these short names." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "networks-for-components", "qname" : "networks:networks-for-components", "signature" : "($components as item()*) as object()*", "description" : "

    Retrieves all networks in the supplied components.

    \n", "summary" : "

    Retrieves all networks in the supplied components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "components", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of components.
    " } ], "returns" : { "type" : "object()*", "description" : "all networks." }, "errors" : [ ] } ], "variables" : [ { "name" : "networks:PRESENTATION_NETWORK", "type" : "xs:string", "description" : " Short name of the presentation network.\n" }, { "name" : "networks:CALCULATION_NETWORK", "type" : "xs:string", "description" : " Short name of the calculation network.\n" }, { "name" : "networks:ESSENCE_ALIAS_NETWORK", "type" : "xs:string", "description" : " Short name of the essence-alias definition network.\n" }, { "name" : "networks:GENERAL_SPECIAL_NETWORK", "type" : "xs:string", "description" : " Short name of the general-special definition network.\n" }, { "name" : "networks:REQUIRES_ELEMENT_NETWORK", "type" : "xs:string", "description" : " Short name of the requires-element definition network.\n" }, { "name" : "networks:SIMILAR_TUPLES_NETWORK", "type" : "xs:string", "description" : " Short name of the similar-tuples definition network.\n" }, { "name" : "networks:DOMAIN_MEMBER_NETWORK", "type" : "xs:string", "description" : " Short name of the domain-member definition network.\n" } ] }, "http://jsound.io/modules/validate/map" : { "ns" : "http://jsound.io/modules/validate/map", "description" : " Map utility\n", "sees" : [ ], "authors" : [ "Chris Hillery, Cezar Andrei" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://jsound.io/modules/validate/map", "prefix" : "map" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "get", "qname" : "map:get", "signature" : "($map as object(), $key as string) as item()", "description" : " Returns the value under the key.\n", "summary" : "

    Returns the value under the key.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "map", "type" : "object()", "occurrence" : null, "description" : "
    the map JSON object
    " }, { "name" : "key", "type" : "string", "occurrence" : null, "description" : "
    the key
    " } ], "returns" : { "type" : "item()", "description" : "the value under the $key, () if empty Example:" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "has-key", "qname" : "map:has-key", "signature" : "($map as object(), $key as string) as boolean", "description" : " Returns true if $key exists in the map.\n", "summary" : "

    Returns true if $key exists in the map.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "map", "type" : "object()", "occurrence" : null, "description" : "
    the map JSON object
    " }, { "name" : "key", "type" : "string", "occurrence" : null, "description" : "
    the key
    " } ], "returns" : { "type" : "boolean", "description" : "true if $key exists, false otherwise Example:" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "set-if-empty", "qname" : "map:set-if-empty", "signature" : "($map as object(), $key as xs:string, $value as item()) as boolean", "description" : " Only if key doesn't exist, inserts new key and value into the map and\n returns true. Otherwise returns false.\n", "summary" : "

    Only if key doesn't exist, inserts new key and value into the map and\n returns true.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "map", "type" : "object()", "occurrence" : null, "description" : "
    the map JSON object
    " }, { "name" : "key", "type" : "xs:string", "occurrence" : null, "description" : "
    the key
    " }, { "name" : "value", "type" : "item()", "occurrence" : null, "description" : "
    the value
    " } ], "returns" : { "type" : "boolean", "description" : "true if $key is empty, false otherwise Example:" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "set", "qname" : "map:set", "signature" : "($map as object(), $key as xs:string, $value as item()) as boolean", "description" : " Inserts new key and value into the map or replaces value under the exiting key.\n Returns true all the time.\n", "summary" : "

    Inserts new key and value into the map or replaces value under the exiting key.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "map", "type" : "object()", "occurrence" : null, "description" : "
    the map JSON object
    " }, { "name" : "key", "type" : "xs:string", "occurrence" : null, "description" : "
    the key
    " }, { "name" : "value", "type" : "item()", "occurrence" : null, "description" : "
    the value
    " } ], "returns" : { "type" : "boolean", "description" : "true Example:" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/xml" : { "ns" : "http://zorba.io/modules/xml", "description" : "

    \n This module provides functions for reading XML files from string inputs.\n It allows reading of well-formed XML documents as well as well-formed\n external parsed entities, described by\n XML 1.0 Well-Formed\n Parsed Entities. The functions can also perform Schema and DTD\n validation of the input documents.\n

    \n

    The following example parses a sequence of XML elements and returns\n them in a streaming fashion - each at a time:

    \n
    \n import module namespace x = \"http://zorba.io/modules/xml\";\n import schema namespace opt = \"http://zorba.io/modules/xml-options\";\n x:parse(\n   \"<from1>Jani</from1><from2>Jani</from2><from3>Jani</from3>\",\n   <opt:options>\n     <opt:parse-external-parsed-entity/>\n   </opt:options>\n )\n 
    \n

    Another useful option allows to skip an arbitrary number of levels\n before returning a sequence of nodes as shown in the following example:

    \n
    \n import module namespace x = \"http://zorba.io/modules/xml\";\n import schema namespace opt = \"http://zorba.io/modules/xml-options\";\n x:parse(\n   \"<root>\n     <from1>Jani1</from1>\n     <from2>Jani2</from2>\n     <from3>Jani3</from3>\n   </root>\",\n   <opt:options>\n     <opt:parse-external-parsed-entity opt:skip-root-nodes=\"1\"/>\n   </opt:options>\n )\n 
    \n", "sees" : [ "XML 1.0 Well-Formed Parsed Entities", " fn:parse-xml() function in XPath and XQuery Functions and Operators 3.0", "LibXml2 parser" ], "authors" : [ "Nicolae Brinza, Juan Zacarias" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/xqt-errors", "prefix" : "err" }, { "uri" : "http://zorba.io/modules/xml-options", "prefix" : "opt" }, { "uri" : "http://zorba.io/modules/schema", "prefix" : "schema" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/modules/xml", "prefix" : "x" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "canonicalize", "qname" : "x:canonicalize", "signature" : "($xml-string as xs:string) as xs:string", "description" : "

    A function to canonicalize the given XML string, that is, transform\n it into Canonical XML as defined by Canonical XML.

    \n

    Note: This function is not streamable. If a streamable string is used\n as input for the function it will be materialized.

    \n

    Note: This function sets the\n XML_PARSE_NOERROR\n option when parsing the XML input.

    \n", "summary" : "

    A function to canonicalize the given XML string, that is, transform\n it into Canonical XML as defined by Canonical XML .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "xml-string", "type" : "xs:string", "occurrence" : null, "description" : "
    a string representation of a well formed XML to canonicalize. XML fragments are not allowed.
    " } ], "returns" : { "type" : "xs:string", "description" : "the canonicalized XML string." }, "errors" : [ "err:CANO0001 invalid input." ] }, { "isDocumented" : true, "arity" : 2, "name" : "canonicalize", "qname" : "x:canonicalize", "signature" : "($xml-string as xs:string, $options as element(opt:options)) as xs:string", "description" : "

    A function to canonicalize the given XML string, that is, transform\n it into Canonical XML as defined by Canonical XML.

    \n

    This version of the function allows specifying certain options to be\n used when initially parsing the XML string. These are of the same form\n as the options to x:parse#2(), although the following options are\n currently ignored for this function:\n

      \n
    • <opt:no-error/>
    • \n
    • <opt:base-uri/>
    • \n
    • <opt:schema-validate/>
    • \n
    • <opt:parse-external-parsed-entity/>
    • \n
    \n

    \n

    Note: This function is not streamable, if a streamable string is used\n as input for the function it will be materialized.

    \n

    Note: This function sets the\n XML_PARSE_NOERROR\n option when parsing the XML input.

    \n", "summary" : "

    A function to canonicalize the given XML string, that is, transform\n it into Canonical XML as defined by Canonical XML .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "xml-string", "type" : "xs:string", "occurrence" : null, "description" : "
    a string representation of a well formed XML to canonicalize. XML fragments are not allowed.
    " }, { "name" : "options", "type" : "element(opt:options)", "occurrence" : null, "description" : "
    an XML containg options for the canonicalize function.
    " } ], "returns" : { "type" : "xs:string", "description" : "the canonicalized XML string." }, "errors" : [ "err:CANO0001 invalid input." ] }, { "isDocumented" : true, "arity" : 2, "name" : "parse", "qname" : "x:parse", "signature" : "($xml-string as xs:string?, $options as element(opt:options)?) as node()* external", "description" : "

    A function to parse XML files and fragments (i.e.\n external general parsed\n entities).

    \n

    The functions takes two arguments: the first one is the\n string to be parsed and the second argument is an <options/> element that\n passes a list of options to the parsing function. They are described below.\n The options element must conform to the xml-options:options element type\n from the xml-options.xsd schema. Some of these\n will be passed to the underlying library (LibXml2) and further documentation\n for them can be found at \n LibXml2 parser.

    \n The list of available options:\n
      \n
    • \n <base-uri/> - the element must have a \"value\" attribute, which will provide\n the baseURI that will be used as the baseURI for every node returned by this\n function.\n
    • \n
    • \n <no-error/> - if present, the option will disable fatal error processing. Any\n failure to parse or validate the input in the requested manner will result\n in the function returning an empty sequence and no error will raised.\n
    • \n
    • \n <schema-validate/> - if present, it will request that the input string be Schema\n validated. The element accepts an attribute named \"mode\" which can have two\n values: \"strict and \"lax\". Enabling the option will produce a result that is\n equivalent to processing the input with the option disabled, and then copying\n the result using the XQuery \"validate strict|lax\" expression. This option can not\n be used together with either the <DTD-validate/> or the <parse-external-parsed-entity/>\n option. Doing so will raise a zerr:ZXQD0003 error.\n
    • \n
    • \n <DTD-validate/> - the option will enable the DTD-based validation. If this\n option is enabled and the input references a DTD, then the input must be a\n well-formed and DTD-valid XML document. The <DTD-load/> option must be used for\n external DTD files to be loaded. If the option is enabled and the input does\n not reference a DTD then the option is ignored. If the option is disabled, the\n input is not required to reference a DTD and if it does reference a DTD then\n the DTD is ignored for validation purposes. This option can not\n be used together with either the <schema-validate/> or the <parse-external-parsed-entity>\n option. Doing so will raise a zerr:ZXQD0003 error.\n
    • \n
    • \n <DTD-load/> - if present, it will enable loading of external DTD files.\n
    • \n
    • \n <default-DTD-attributes/> - if present, it will enable the default DTD attributes.\n
    • \n
    • \n <parse-external-parsed-entity/> - if present, it will enable the processing of XML\n external entities. If the option\n is enabled, the input must conform to the syntax extParsedEnt (production\n [78] in XML 1.0, see \n Well-Formed Parsed Entities). In addition, by default a DOCTYPE declaration is allowed,\n as described by the [28] doctypedecl production, see \n Document Type Definition. A parameter is available to forbid the appearance of the DOCTYPE.\n The result of the function call is a list\n of nodes corresponding to the top-level components of the content of the\n external entity: that is, elements, processing instructions, comments, and\n text nodes. CDATA sections and character references are expanded, and\n adjacent characters are merged so the result contains no adjacent text\n nodes. If the option is disabled, the input must be a well-formed XML\n document conforming to the Document production\n (production [1] in XML 1.0).\n This option can not be used together with either the <schema-validate/> or the <DTD-validate/>\n option. Doing so will raise a zerr:ZXQD0003 error.\n The <parse-external-parsed-entity/> option has three parameters, given by attributes. The first\n attribute is \"skip-root-nodes\" and it can have a non-negative value. Specifying the paramter\n tells the parser to skip the given number of root nodes and return only their children. E.g.\n skip-root-nodes=\"1\" is equivalent to parse-xml($xml-string)/node()/node() . skip-root-nodes=\"2\" is equivalent\n to parse-xml($xml-string)/node()/node()/node() , etc. The second attribute is \"skip-top-level-text-nodes\" with a\n boolean value. Specifying \"true\" will tell the parser to skip top level text nodes, returning\n only the top level elements, comments, PIs, etc. This parameter works in combination with\n the \"skip-root-nodes\" paramter, thus top level text nodes are skipped after \"skip-root-nodes\" has\n been applied. The third paramter is \"error-on-doctype\" and will generate an error if a DOCTYPE\n declaration appears in the input, which by default is allowed.\n
    • \n
    • \n <substitute-entities/> - if present, it will enable the XML entities substitutions.\n
    • \n
    • \n <remove-redundant-ns/> - if present, the parser will remove redundant namespaces declarations.\n
    • \n
    • \n <no-CDATA/> - if present, the parser will merge CDATA nodes as text nodes.\n
    • \n
    • \n <xinclude-substitutions/> - if present, it will enable the XInclude substitutions.\n
    • \n
    • \n <no-xinclude-nodes/> - if present, the parser will not generate XInclude START/END nodes.\n
    • \n
    \n

    \n An example that sets the base-uri of the parsed external entities:\n

    \n
    \n   import module namespace x = \"http://zorba.io/modules/xml\";\n   import schema namespace opt = \"http://zorba.io/modules/xml-options\";\n   x:parse(\"<from1>Jani</from1><from2>Jani</from2><from3>Jani</from3>\",\n     <opt:options>\n       <opt:base-uri opt:value=\"urn:test\"/>\n       <opt:parse-external-parsed-entity/>\n     </opt:options>\n   )\n 
    \n", "summary" : "

    A function to parse XML files and fragments (i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "xml-string", "type" : "xs:string", "occurrence" : "?", "description" : "
    The string that holds the XML to be parsed. If empty, the function will return an empty sequence
    " }, { "name" : "options", "type" : "element(opt:options)", "occurrence" : "?", "description" : "
    The options for the parsing
    " } ], "returns" : { "type" : "node()*", "description" : "The parsed XML as a document node or a list of nodes, or an empty sequence." }, "errors" : [ "zerr:ZXQD0003 The error will be raised if the options to the function are inconsistent.", "err:FODC0006 The error will be raised if the input string is not a valid XML document or fragment (external general parsed entity) or if DTD validation was enabled and the document has not passed it.", "err:XQDY0027 The error will be raised if schema validation was enabled and the input document has not passed it or if the parsing options are not conformant to the xml-options.xsd schema." ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/process" : { "ns" : "http://www.zorba-xquery.com/modules/process", "description" : " This module provides functions to create a native process and return the result\n (i.e. exit code, result on standard out and error).\n

    \n Example:\n

    \n  import module namespace proc = \"http://www.zorba-xquery.com/modules/process\";\n  proc:exec(\"ls\")\n
    \n

    \n

    \n Potential result:\n

    \n <result xmlns=\"http://www.zorba-xquery.com/modules/process\">\n   <stdout>myfile.txt</stout>\n   <stderr/>\n   <exit-code>0</exit-code>\n </result>\n 
    \n

    \n", "sees" : [ ], "authors" : [ "Cezar Andrei" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.zorba-xquery.com/modules/process", "prefix" : "process" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "exec", "qname" : "process:exec", "signature" : "($cmd as xs:string) as element(process:result) external", "description" : " Executes the specified string command in a separate process.\n This function does not allow arguments to be passed to\n the command.\n", "summary" : "

    Executes the specified string command in a separate process.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "cmd", "type" : "xs:string", "occurrence" : null, "description" : "
    command to be executed (without arguments)
    " } ], "returns" : { "type" : "element(process:result)", "description" : "the result of the execution as an element as shown in the documentation of this module. The exit-code element returns the exit code of the child process. For POSIX compliant platforms: returns the process exit code. If process is terminated or stopped: 128 + termination signal code. For Windows platforms: returns the return value of the process or the exit or terminate process specified value." }, "errors" : [ "process:PROC01 if an error occurred while communicating with the executed process." ] }, { "isDocumented" : true, "arity" : 2, "name" : "exec", "qname" : "process:exec", "signature" : "($cmd as xs:string, $args as xs:string*) as element(process:result) external", "description" : " Executes the specified string command in a separate process.\n Each of the strings in the sequence passed in as the second\n argument is passed as an argument to the executed command.\n", "summary" : "

    Executes the specified string command in a separate process.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "cmd", "type" : "xs:string", "occurrence" : null, "description" : "
    command to be executed (without arguments)
    " }, { "name" : "args", "type" : "xs:string", "occurrence" : "*", "description" : "
    the arguments passed to the executed command (e.g. \"-la\")
    " } ], "returns" : { "type" : "element(process:result)", "description" : "the result of the execution as an element as shown in the documentation of this module. The exit-code element returns the exit code of the child process. For POSIX compliant platforms: returns the process exit code. If process is terminated or stopped: 128 + termination signal code. For Windows platforms: returns the return value of the process or the exit or terminate process specified value." }, "errors" : [ "process:PROC01 if an error occurred while communicating with the executed process." ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/maps" : { "ns" : "http://www.28msec.com/modules/maps", "description" : "

    This module defines a set of functions for working with maps. A map\n is identified by a string and can be created using the map:create function\n and dropped using the map:drop function.

    \n

    It is possible to create persistent and transient maps. The lifetime of a\n transient map is limited by the execution of the current query.\n A persistent map lives until it is explicitly dropped.\n Accordingly, it is also available to other requests.

    \n

    For example,\n

    map:create(\"my-map\", [\"string\", \"integer\"], { \"persistent\" : false })
    \n will create a transient map named my-map having two keys.\n The types of the keys are string and integer.\n

    \n

    The key of a particular entry in the map can consist of a tuple of\n atomic values (called key attributes). The actual type of each attribute\n is determined when the map is created. The value of each entry is a\n sequence of items. If an item in this sequence is a object or array,\n this item needs to belong to a collection, otherwise, an error is raised.

    \n

    For every persistent map, 28.io will create a new collection\n in your MongoDB database. The collection will have the prefix _28.map.\n For example, if your map is called foo, the according collection will\n be named _28.map.foo.

    \n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/maps", "prefix" : "map" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "available-maps", "qname" : "map:available-maps", "signature" : "() as string* external", "description" : " The function returns a sequence of names of the maps that are\n available (persistent and non-persistent). The sequence will be\n empty if there are no maps.\n", "summary" : "

    The function returns a sequence of names of the maps that are\n available (persistent and non-persistent).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "string*", "description" : "A sequence of string, one for each available map, or an emtpy sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "create", "qname" : "map:create", "signature" : "($name as string, $key-types as item()) as empty-sequence() external", "description" : " Create a persistent map with a given name and type identifiers for the key\n attributes.\n If the map has only one key attribute, a single type identifier is given,\n for more than one key attribute an array of type identifiers is given.\n Calling this function is equivalent to calling create with the options\n
    { \"persistent\" : true }
    \n Note that the function is sequential and immediately creates the map.\n

    Each key-type should be specified as string (e.g. \"integer\",\n \"string\", \"boolean\", \"double\", or \"datetime\").

    \n

    For example,\n

    map:create(\"my-map\", \"string\")
    or\n
    map:create(\"my-map\", [\"string\", \"integer\"])
    .

    \n", "summary" : "

    Create a persistent map with a given name and type identifiers for the key\n attributes.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map (the restrictons on collection names apply)
    " }, { "name" : "key-types", "type" : "item()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and immediately creates the corresponding map. It returns the empty-sequence." }, "errors" : [ "err:XPTY0004 if any of the key attribute types is not a subtype of anyAtomicType.", "zerr:ZSTR0001 if a map with the given name already exists.", "zerr:ZDDY1000 if the given name is not a legal collection name", "zerr:ZDDY0043 if any of the given options has an invalid type" ] }, { "isDocumented" : true, "arity" : 3, "name" : "create", "qname" : "map:create", "signature" : "($name as string, $key-types as item(), $options as object()) as empty-sequence() external", "description" : " Create a map with a given name, type identifiers for the key attributes, and\n options.\n If the map has only one key attribute, a single type identifier is given,\n for more than one key attribute an array of type identifiers is given.\n Currently only one option is supported: To create a transient map the object\n { \"persistent\" : false }\n has to be passed to the $options parameter.\n Note that the function is sequential and immediately creates the map in the\n store.\n", "summary" : "

    Create a map with a given name, type identifiers for the key attributes, and\n options.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map (the restrictons on collection names apply)
    " }, { "name" : "key-types", "type" : "item()", "occurrence" : null, "description" : "" }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    an object describing options for the map
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and immediately creates the corresponding map but returns the empty-sequence." }, "errors" : [ "err:XPTY0004 if any of the attribute types is not a subtype of anyAtomicType.", "zerr:ZSTR0001 if a map with the given name already exists.", "zerr:ZDDY1000 if the given name is not a legal collection name", "zerr:ZDDY0043 if any of the given options has an invalid type" ] }, { "isDocumented" : true, "arity" : 2, "name" : "delete", "qname" : "map:delete", "signature" : "($name as string, $key as item()) as empty-sequence() external", "description" : " Removes an entry identified by the given key from the map.\n If the map has only one key attribute, a single key value is given, for\n more than one key attribute an array of key values is given.\n Note that it is possible to insert entries with empty key attributes.\n However as the removing the entries is based on the \"eq\" comparison and\n as \"eq\" with an empty sequence always return false, it is not possible\n to delete these entries.\n", "summary" : "

    Removes an entry identified by the given key from the map.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map
    " }, { "name" : "key", "type" : "item()", "occurrence" : null, "description" : "
    either a single attribute key or an array of keys
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and immediately deletes the entry into the map but returns the empty-sequence." }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist.", "zerr:ZDDY0025 if the given number of key attributes does not match the number of key attributes specified when creating the map (see the map:create function).", "zerr:ZXQD0005 if any of the given key attributes can not be cast (or is not a subtype) of the corresponding key attribute specified when creating the map." ] }, { "isDocumented" : true, "arity" : 1, "name" : "drop", "qname" : "map:drop", "signature" : "($name as string) as empty-sequence() external", "description" : " Deletes the map with the given name.\n", "summary" : "

    Deletes the map with the given name.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map to drop
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and immediately drops the map. It returns the empty-sequence." }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist." ] }, { "isDocumented" : true, "arity" : 2, "name" : "get", "qname" : "map:get", "signature" : "($name as string, $key as item()) as item()* external", "description" : " Returns the value of the entry with the given key from the map.\n If the map has only one key attribute, a single key value is given, for\n more than one key attribute an array of key values is given.\n Note that it is possible to insert entries with empty key attributes.\n However as the getting the entries is based on the \"eq\" comparison and\n as \"eq\" with an empty sequence always return false, it is not possible\n to retrieve these entries.\n

    For example,\n

    map:get(\"my-map\", \"key\")
    or\n
    map:get(\"my-map\", [ \"key1\", \"key2\" ])
    .

    \n", "summary" : "

    Returns the value of the entry with the given key from the map.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map
    " }, { "name" : "key", "type" : "item()", "occurrence" : null, "description" : "
    either a single attribute key or an array of keys
    " } ], "returns" : { "type" : "item()*", "description" : "the value of the entry in the map identified by the given key. The empty-sequence will be returned if no entry with the given key is contained in the map." }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist.", "zerr:ZDDY0025 if the given number of key attributes does not match the number of key attributes specified when creating the map (see the map:create function).", "zerr:ZXQD0005 if any of the given key attributes can not be cast (or is not a subtype) of the corresponding key attribute specified when creating the map." ] }, { "isDocumented" : true, "arity" : 3, "name" : "insert", "qname" : "map:insert", "signature" : "($name as string, $key as item(), $value as item()*) as empty-sequence() external", "description" : " Inserts a new entry into the map with the given name.\n If the map has only one key attribute, a single key value is given, for\n more than one key attribute an array of key values is given.\n If an entry with the given key already exists in the map, the value\n sequences of the existing entry and the sequence passed using $value\n argument are concatenated.\n

    If a map is persistent and if an item in the value sequence\n is an object or array, this item needs to belong to a collection,\n otherwise, an an error is raised.

    \n Note that it is possible to insert entries with empty key attributes\n or key attributes having the value null. However, as\n the comparison with an empty sequence or null always returns false,\n it is not possible to retrieve these entries.\n

    For example,\n

    map:insert(\"my-map\", \"key\", \"value\")
    or\n
    map:insert(\"my-map\", [ \"key1\", \"key2\" ] , (42, \"value\"))
    .

    \n", "summary" : "

    Inserts a new entry into the map with the given name.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map
    " }, { "name" : "key", "type" : "item()", "occurrence" : null, "description" : "
    either a single attribute key or an array of keys
    " }, { "name" : "value", "type" : "item()", "occurrence" : "*", "description" : "
    the value of the entry to insert
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and immediately inserts the entry into the map. It returns the empty-sequence." }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist.", "zerr:ZDDY0025 if the given number of key attributes does not match the number of key attributes specified when creating the map (see the map:create function).", "zerr:ZXQD0005 if any of the given key attributes can not be cast (or is not a subtype) of the corresponding key attribute specified when creating the map.", "zerr:ZDDY1003 if the value to insert is an object or array it must belong to a collection." ] }, { "isDocumented" : true, "arity" : 1, "name" : "keys", "qname" : "map:keys", "signature" : "($name as string) as array()* external", "description" : " Returns the keys of all entries of a map. The keys\n are returned as sequence of arrays.\n The following condition always holds:\n map:size($name) eq count(map:keys($name))\n", "summary" : "

    Returns the keys of all entries of a map.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map
    " } ], "returns" : { "type" : "array()*", "description" : "an sequence of arrays each array containing the values of all attributes of one key." }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist." ] }, { "isDocumented" : true, "arity" : 1, "name" : "options", "qname" : "map:options", "signature" : "($name as string) as object() external", "description" : " The function returns the options that were passed during creation or the\n default options if no options were passed.\n", "summary" : "

    The function returns the options that were passed during creation or the\n default options if no options were passed.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map
    " } ], "returns" : { "type" : "object()", "description" : "an options object" }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist." ] }, { "isDocumented" : true, "arity" : 1, "name" : "size", "qname" : "map:size", "signature" : "($name as string) as integer external", "description" : " The number of entries in a map.\n The following condition always holds:\n map:size($name) eq count(map:keys($name))\n", "summary" : "

    The number of entries in a map.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    the name of the map
    " } ], "returns" : { "type" : "integer", "description" : "the number of entries in the map." }, "errors" : [ "zerr:ZDDY0023 if a map with the given name does not exist." ] } ], "variables" : [ ] }, "http://www.w3.org/2005/xpath-functions/math" : { "ns" : "http://www.w3.org/2005/xpath-functions/math", "description" : " This module contains all the functions part of the\n W3C XPath and XQuery Functions and Operators 3.0\n section \"4.7 Trigonometric and exponential functions\".\n", "sees" : [ "http://www.w3.org/TR/xpath-functions-30/#trigonometry" ], "authors" : [ "www.w3c.org" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xpath-functions/math", "prefix" : "math" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "acos", "qname" : "math:acos", "signature" : "($arg as xs:double?) as xs:double? external", "description" : "

    Returns the arc cosine of the argument, the result being in the range zero to\n +π radians.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise the result is the arc cosine of $θ,\n treated as an angle in radians, as defined in the \n specification of the acos function applied to 64-bit binary floating point\n values.

    The treatment of the invalidOperation exception is defined in .

    If $arg is NaN, or if its absolute value is greater than one,\n then the result is NaN.

    In other cases the result is an xs:double value representing an angle\n θ in radians in the range 0 <= $θ <=\n +π.

    \n", "summary" : "

    Returns the arc cosine of the argument, the result being in the range zero to\n + π radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "asin", "qname" : "math:asin", "signature" : "($arg as xs:double?) as xs:double? external", "description" : "

    Returns the arc sine of the argument, the result being in the range\n -π/2 to +π/2 radians.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise the result is the arc sine of $θ,\n treated as an angle in radians, as defined in the \n specification of the asin function applied to 64-bit binary floating point\n values.

    The treatment of the invalidOperation and underflow exceptions\n is defined in .

    If $arg is positive or negative zero, the result is $arg.

    If $arg is NaN, or if its absolute value is greater than one,\n then the result is NaN.

    In other cases the result is an xs:double value representing an angle\n θ in radians in the range -π/2 <=\n $θ <= +π/2.

    \n", "summary" : "

    Returns the arc sine of the argument, the result being in the range\n - π /2 to + π /2 radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "atan", "qname" : "math:atan", "signature" : "($arg as xs:double?) as xs:double? external", "description" : "

    Returns the arc tangent of the argument, the result being in the range\n -π/2 to +π/2 radians.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise the result is the arc tangent of $θ,\n treated as an angle in radians, as defined in the \n specification of the atan function applied to 64-bit binary floating point\n values.

    The treatment of the underflow exception is defined in .

    If $arg is positive or negative zero, the result is $arg.

    If $arg is NaN then the result is NaN.

    In other cases the result is an xs:double value representing an angle\n θ in radians in the range -π/2 <=\n $θ <= +π/2.

    \n", "summary" : "

    Returns the arc tangent of the argument, the result being in the range\n - π /2 to + π /2 radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "atan2", "qname" : "math:atan2", "signature" : "($y as xs:double, $x as xs:double) as xs:double external", "description" : "

    Returns the angle in radians subtended at the origin by the point on a plane\n with coordinates (x, y) and the positive x-axis, the result being in the range\n -π to +π.

    This function is deterministic, context-independent, and focus-independent.

    The result is the value of atan2(y, x) as defined in the\n specification of the atan2 function applied\n to 64-bit binary floating point values.

    The treatment of the underflow exception is defined in .

    If either argument is NaN\n then the result is NaN.

    If $y is positive and $x is positive and finite, then\n (subject to rules for overflow, underflow and approximation)\n the value of atan2($y, $x) is atan($y div $x).

    If $y is positive and $x is negative and finite, then\n (subject to the same caveats)\n the value of atan2($y, $x) is π - atan($y div $x).

    Some results for special values of the arguments are shown in the examples below.

    \n", "summary" : "

    Returns the angle in radians subtended at the origin by the point on a plane\n with coordinates (x, y) and the positive x-axis, the result being in the range\n - π to + π .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "y", "type" : "xs:double", "occurrence" : null, "description" : "" }, { "name" : "x", "type" : "xs:double", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:double", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "cos", "qname" : "math:cos", "signature" : "($theta as xs:double?) as xs:double? external", "description" : "

    Returns the cosine of the argument, expressed in radians.

    This function is deterministic, context-independent, and focus-independent.

    If $θ is the empty sequence, the function returns the empty\n sequence.

    If $θ is positive or negative infinity, or NaN,\n then the result is NaN.

    Otherwise the result is the cosine of $θ,\n treated as an angle in radians, as defined in the \n specification of the cos function applied to 64-bit binary floating point\n values.

    The treatment of the invalidOperation exception is defined in .

    If $θ is positive or negative zero, the result is\n $θ.

    If $θ is positive or negative infinity, or NaN,\n then the result is NaN.

    Otherwise the result is always in the range -1.0e0 to +1.0e0

    \n", "summary" : "

    Returns the cosine of the argument, expressed in radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "theta", "type" : "xs:double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "exp", "qname" : "math:exp", "signature" : "($arg as xs:double?) as xs:double? external", "description" : "

    Returns the value of ex.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise the result is the mathematical constant e\n raised to the power of $arg, as defined in the \n specification of the exp function applied to 64-bit binary floating point\n values.

    The treatment of overflow and underflow is defined in .

    \n", "summary" : "

    Returns the value of e x .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "exp10", "qname" : "math:exp10", "signature" : "($arg as xs:double?) as xs:double? external", "description" : "

    Returns the value of 10x.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise the result is ten raised to the power of $arg,\n as defined in the specification of the exp10\n function applied to 64-bit binary floating point values.

    The treatment of overflow and underflow is defined in .

    \n", "summary" : "

    Returns the value of 10 x .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "log", "qname" : "math:log", "signature" : "($arg as xs:double?) as xs:double? external", "description" : "

    Returns the natural logarithm of the argument.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise the result is the natural logarithm of $arg, as\n defined in the specification of the log\n function applied to 64-bit binary floating point values.

    The treatment of divideByZero and invalidOperation exceptions\n is defined in . The effect is that if the argument is less\n than or equal to zero, the result is NaN.

    \n", "summary" : "

    Returns the natural logarithm of the argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "log10", "qname" : "math:log10", "signature" : "($arg as xs:double?) as xs:double? external", "description" : "

    Returns the base-ten logarithm of the argument.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise the result is the base-10 logarithm of $arg, as\n defined in the specification of the log10\n function applied to 64-bit binary floating point values.

    The treatment of divideByZero and invalidOperation exceptions\n is defined in . The effect is that if the argument is less\n than or equal to zero, the result is NaN.

    \n", "summary" : "

    Returns the base-ten logarithm of the argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "pi", "qname" : "math:pi", "signature" : "() as xs:double external", "description" : "

    Returns an approximation to the mathematical constant π.

    This function is deterministic, context-independent, and focus-independent.

    This function returns the xs:double value whose lexical representation is\n 3.141592653589793e0

    The expression 2*math:pi() returns 6.283185307179586e0.

    The expression 60 * (math:pi() div 180) converts an angle of 60 degrees\n to radians.

    \n", "summary" : "

    Returns an approximation to the mathematical constant π .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:double", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "pow", "qname" : "math:pow", "signature" : "($x as xs:double?, $y as numeric) as xs:double? external", "description" : "

    Returns the result of raising the first argument to the power of the\n second.

    This function is deterministic, context-independent, and focus-independent.

    If $x is the empty sequence, the function returns the empty sequence.

    If $y is an instance of xs:integer, the result is\n $x raised to the power of $y as defined in the specification of the pown function applied to a\n 64-bit binary floating point value and an integer.

    Otherwise $y is converted to an xs:double by numeric\n promotion, and the result is the value of $x raised to the power of\n $y as defined in the specification of the\n pow function applied to two 64-bit binary floating point values.

    The treatment of the divideByZero and invalidOperation\n exceptions is defined in . Some of the consequences are\n illustrated in the examples below.

    \n", "summary" : "

    Returns the result of raising the first argument to the power of the\n second.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x", "type" : "xs:double", "occurrence" : "?", "description" : "" }, { "name" : "y", "type" : "numeric", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sin", "qname" : "math:sin", "signature" : "($theta as xs:double?) as xs:double? external", "description" : "

    Returns the sine of the argument, expressed in radians.

    This function is deterministic, context-independent, and focus-independent.

    If $θ is the empty sequence, the function returns the empty\n sequence.

    Otherwise the result is the sine of $θ,\n treated as an angle in radians, as defined in the \n specification of the sin function applied to 64-bit binary floating point\n values.

    The treatment of the invalidOperation and underflow exceptions\n is defined in .

    If $θ is positive or negative zero, the result is\n $θ.

    If $θ is positive or negative infinity, or NaN,\n then the result is NaN.

    Otherwise the result is always in the range -1.0e0 to +1.0e0

    \n", "summary" : "

    Returns the sine of the argument, expressed in radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "theta", "type" : "xs:double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sqrt", "qname" : "math:sqrt", "signature" : "($arg as xs:double?) as xs:double? external", "description" : "

    Returns the non-negative square root of the argument.

    This function is deterministic, context-independent, and focus-independent.

    If $arg is the empty sequence, the function returns the empty sequence.

    Otherwise the result is the mathematical non-negative square root of\n $arg as defined in the specification of the\n squareRoot function applied to 64-bit binary floating point values.

    The treatment of the invalidOperation exception is defined in . The effect is that if the argument is less than zero, the result\n is NaN.

    If $arg is positive or negative zero, positive infinity, or\n NaN, then the result is $arg. (Negative zero is the only\n case where the result can have negative sign)

    \n", "summary" : "

    Returns the non-negative square root of the argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "tan", "qname" : "math:tan", "signature" : "($theta as xs:double?) as xs:double? external", "description" : "

    Returns the tangent of the argument, expressed in radians.

    This function is deterministic, context-independent, and focus-independent.

    If $θ is the empty sequence, the function returns the empty\n sequence.

    Otherwise the result is the tangent of $θ,\n treated as an angle in radians, as defined in the \n specification of the tan function applied to 64-bit binary floating point\n values.

    The treatment of the invalidOperation and underflow exceptions\n is defined in .

    If $θ is positive or negative infinity, or NaN,\n then the result is NaN.

    \n", "summary" : "

    Returns the tangent of the argument, expressed in radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "theta", "type" : "xs:double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:double?", "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/oauth/client" : { "ns" : "http://www.zorba-xquery.com/modules/oauth/client", "description" : " This module provides the functions necessary to acquire access to the personal\n resources of a user through the open standard called\n OAuth.\n The application/mashup creator does not need to know the\n specifics of OAuth to use this module.\n", "sees" : [ "OAuth Website" ], "authors" : [ "Stephanie Russell", "William Candillon" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://zorba.io/modules/base64", "prefix" : "base64" }, { "uri" : "http://zorba.io/features", "prefix" : "f" }, { "uri" : "http://zorba.io/modules/hmac", "prefix" : "hmac" }, { "uri" : "http://expath.org/ns/http-client", "prefix" : "http" }, { "uri" : "http://expath.org/ns/http-client", "prefix" : "http-client" }, { "uri" : "http://www.zorba-xquery.com/modules/oauth/client", "prefix" : "oauth" }, { "uri" : "http://www.zorba-xquery.com/modules/oauth/error", "prefix" : "oerr" }, { "uri" : "http://zorba.io/options/features", "prefix" : "op" }, { "uri" : "http://www.zorba-xquery.com/schemas/oauth/parameters", "prefix" : "p" }, { "uri" : "http://zorba.io/modules/random", "prefix" : "ra" }, { "uri" : "http://www.zorba-xquery.com/schemas/oauth/service-provider", "prefix" : "sp" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "access-token", "qname" : "oauth:access-token", "signature" : "($service-provider as schema-element(sp:service-provider), $parameters as schema-element(p:parameters)) as schema-element(p:parameters)", "description" : " This function allows the client to obtain a set of token credentials from the service provider by making an authenticated HTTP request to the Token Request endpoint.\n This function is provided for convenience.\n", "summary" : "

    This function allows the client to obtain a set of token credentials from the service provider by making an authenticated HTTP request to the Token Request endpoint.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "service-provider", "type" : "schema-element(sp:service-provider)", "occurrence" : null, "description" : "
    Contains service provider information
    " }, { "name" : "parameters", "type" : "schema-element(p:parameters)", "occurrence" : null, "description" : "
    parameters
    " } ], "returns" : { "type" : "schema-element(p:parameters)", "description" : "token credentials correctly parsed as parameter elements, or an error if http response status is not 200 OK
     let $service-provider := oauth:service-provider(...) let $parameters := oauth:parameters(\"oauth_token\", \"#\") let $parameters := oauth:add-parameter($parameters, \"oauth_token_secret\", \"#\") let $tokens := oauth:access-token($service-provider, $parameters) ... 
    " }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "add-parameter", "qname" : "oauth:add-parameter", "signature" : "($parameters as schema-element(p:parameters)?, $name as xs:string, $value as xs:string) as schema-element(p:parameters)", "description" : " Adds an OAuth parameter to an OAuth Parameters instance.\n Instances of OAuth parameters are used to\n contain value/pair data such as oauth_token\n and oauth_token_secret.\n For instance the following code snippet:\n
    \n  let $params := oauth:parameters(\"oauth_token\", \"#\")\n  let $params := oauth:add-parameter($params, \"oauth_token_secret\", \"#\")\n  return $params\n 
    \n Returns the following XML schema instance:\n
    \n \n   \n   \n \n 
    \n", "summary" : "

    Adds an OAuth parameter to an OAuth Parameters instance.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "parameters", "type" : "schema-element(p:parameters)", "occurrence" : "?", "description" : "
    parameters
    " }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    parameter name
    " }, { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    parameter value
    " } ], "returns" : { "type" : "schema-element(p:parameters)", "description" : "instance of the OAuth parameters XML schema." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "parameter", "qname" : "oauth:parameter", "signature" : "($params as schema-element(p:parameters), $string as xs:string) as xs:string", "description" : " This function returns the string value of the parameters whose key matches a $string input.\n", "summary" : "

    This function returns the string value of the parameters whose key matches a $string input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "params", "type" : "schema-element(p:parameters)", "occurrence" : null, "description" : "
    element parameters
    " }, { "name" : "string", "type" : "xs:string", "occurrence" : null, "description" : "
    string as the \"key\" name
    " } ], "returns" : { "type" : "xs:string", "description" : "string value of the parameter with key $string
     let $params := oauth:parameters(\"oauth_token\", \"token\") let $params := oauth:add-parameter($params, \"oauth_token_secret\", \"secret\") let $token-secret := oauth:parameter($params, \"oauth_token_secret\") return $token-secret 
    " }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "parameters", "qname" : "oauth:parameters", "signature" : "($name as xs:string, $value as xs:string) as element(p:parameters)", "description" : " Create an OAuth Parameters instance.\n Instances of OAuth parameters are used to\n contain value/pair data such as oauth_token\n and oauth_token_secret.\n For instance the following code snippet:\n
    \n  oauth:parameters(\"oauth_token\", \"#\")\n 
    \n Returns the following XML schema instance:\n
    \n \n   \n \n 
    \n", "summary" : "

    Create an OAuth Parameters instance.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    parameter name
    " }, { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    parameter value
    " } ], "returns" : { "type" : "element(p:parameters)", "description" : "instance of the OAuth parameters XML schema." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "protected-resource", "qname" : "oauth:protected-resource", "signature" : "($protected-resource as schema-element(http:request), $service-provider as schema-element(sp:service-provider), $parameters as schema-element(p:parameters)) as item()*", "description" : " This function allows the client access to the protected resources of the user.\n This function is provided for convenience.\n", "summary" : "

    This function allows the client access to the protected resources of the user.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "protected-resource", "type" : "schema-element(http:request)", "occurrence" : null, "description" : "
    (Not schema-validated) http:request element with http method and href.
    " }, { "name" : "service-provider", "type" : "schema-element(sp:service-provider)", "occurrence" : null, "description" : "
    Information about the service provider
    " }, { "name" : "parameters", "type" : "schema-element(p:parameters)", "occurrence" : null, "description" : "
    parameters
    " } ], "returns" : { "type" : "item()*", "description" : "protected resources parsed as parameter elements, or an error if http response status is not 200 OK
     let $tokens := oauth:parameters(\"oauth_token\", \"#\") let $tokens := oauth:add-parameter($tokens, \"oauth_token_secret\", \"#\") let $service-provider := oauth:service-provider(...) let $request := validate {  } return oauth:protected-resource($request, $service-provider, $tokens) 
    " }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "request-token", "qname" : "oauth:request-token", "signature" : "($service-provider as schema-element(sp:service-provider)) as schema-element(p:parameters)", "description" : " This function allows the client to obtain a set of temporary credentials from the service provider by making an authenticated HTTP request to the Temporary Credential Request endpoint.\n This function is provided for convenience for request-token#2.\n Invoking this function is equivalent to:\n
    \n oauth:request-token($service-provider, ())\n 
    \n", "summary" : "

    This function allows the client to obtain a set of temporary credentials from the service provider by making an authenticated HTTP request to the Temporary Credential Request endpoint.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "service-provider", "type" : "schema-element(sp:service-provider)", "occurrence" : null, "description" : "
    Information about the service provider
    " } ], "returns" : { "type" : "schema-element(p:parameters)", "description" : "temporary credentials correctly parsed as parameter elements, or an error if http response status is not 200 OK" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "request-token", "qname" : "oauth:request-token", "signature" : "($service-provider as schema-element(sp:service-provider), $parameters as schema-element(p:parameters)?) as schema-element(p:parameters)", "description" : " This function allows the client to obtain a set of temporary credentials from the service provider by making an authenticated HTTP request to the Temporary Credential Request endpoint.\n This function is provided for convenience.\n", "summary" : "

    This function allows the client to obtain a set of temporary credentials from the service provider by making an authenticated HTTP request to the Temporary Credential Request endpoint.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "service-provider", "type" : "schema-element(sp:service-provider)", "occurrence" : null, "description" : "
    Information about the service provider
    " }, { "name" : "parameters", "type" : "schema-element(p:parameters)", "occurrence" : "?", "description" : "
    Additionnal parameters to the request
    " } ], "returns" : { "type" : "schema-element(p:parameters)", "description" : "temporary credentials correctly parsed as parameter elements, or an error if http response status is not 200 OK
     let $twitter-config := oauth:service-provider(...) let $additional-parameter := oauth:parameters(\"foo\", \"bar\") let $tokens := oauth:request-token($twitter-config, $additional-parameter) let $token := oauth:parameter($tokens, \"oauth_token\") let $token-secret := oauth:parameter($tokens, \"oauth_token_secret\") ... 
    " }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 10, "name" : "service-provider", "qname" : "oauth:service-provider", "signature" : "($consumer-key as xs:string, $consumer-secret as xs:string, $signature-method as xs:string, $realm as xs:string, $authorize-url as xs:string, $request-token-method as xs:string, $request-token-url as xs:string, $request-token-callback-url as xs:string, $access-token-method as xs:string, $access-token-url as xs:string) as schema-element(sp:service-provider)", "description" : " Utility function to build a service provider object.\n This object contains the information required by the\n OAuth client to interact with an OAuth service provider.\n For instance the following expression:\n
    \n let $consumer-key     := \"#\"\n let $consumer-secret  := \"#\"\n let $signature-method := \"HMAC-SHA1\"\n let $realm            := \"twitter.com\"\n let $authorize-url    := \"http://api.twitter.com/oauth/authorize\"\n let $request-token-method := \"POST\"\n let $request-token-url := \"https://twitter.com/oauth/request_token\"\n let $request-token-callback-url := \"https://twitter.com/oauth/request_token\"\n let $access-token-method := \"POST\"\n let $access-token-url := \"https://api.twitter.com/oauth/access_token\"\n return oauth:service-provider(\n   $consumer-key, $consumer-secret, $signature-method,\n   $realm, $authorize-url, $request-token-method,\n   $request-token-url, $request-token-callback-url,\n   $access-token-method, $access-token-url\n )\n 
    \n Will return the following XML schema instance:\n
    \n \n   \n   \n \n 
    \n", "summary" : "

    Utility function to build a service provider object.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "consumer-key", "type" : "xs:string", "occurrence" : null, "description" : "
    Client Identifier, also known as the consumer-key
    " }, { "name" : "consumer-secret", "type" : "xs:string", "occurrence" : null, "description" : "
    Client Shared-Secret, also known as the consumer-secret
    " }, { "name" : "signature-method", "type" : "xs:string", "occurrence" : null, "description" : "
    Method with which the signing key is signed (typically HMAC-SHA1)
    " }, { "name" : "realm", "type" : "xs:string", "occurrence" : null, "description" : "
    Realm that defines the protection space
    " }, { "name" : "authorize-url", "type" : "xs:string", "occurrence" : null, "description" : "
    authorize-url
    " }, { "name" : "request-token-method", "type" : "xs:string", "occurrence" : null, "description" : "
    request-token-method
    " }, { "name" : "request-token-url", "type" : "xs:string", "occurrence" : null, "description" : "
    request-token-url
    " }, { "name" : "request-token-callback-url", "type" : "xs:string", "occurrence" : null, "description" : "
    request-token-callback-url
    " }, { "name" : "access-token-method", "type" : "xs:string", "occurrence" : null, "description" : "
    access-token-method
    " }, { "name" : "access-token-url", "type" : "xs:string", "occurrence" : null, "description" : "
    access-token-url
    " } ], "returns" : { "type" : "schema-element(sp:service-provider)", "description" : "instance of the OAuth service provider XML schema." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/http/util/multipart" : { "ns" : "http://www.28msec.com/modules/http/util/multipart", "description" : " This module provides utility functions to help dealing with the\n content of multipart requests.\n In their implementation, all the functions use the multipart\n related functions of the request module (e.g. parts() or text-part()).\n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.28msec.com/modules/http/util/multipart", "prefix" : "multipart" }, { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "req" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "binary-content", "qname" : "multipart:binary-content", "signature" : "($name as xs:string) as xs:base64Binary*", "description" : " Returns the contents of the parts/files in the multipart requests with\n the given part name as xs:base64Binary.\n", "summary" : "

    Returns the contents of the parts/files in the multipart requests with\n the given part name as xs:base64Binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the requested part.
    " } ], "returns" : { "type" : "xs:base64Binary*", "description" : "the said content or the empty sequence if no part with the given name exists." }, "errors" : [ "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 1, "name" : "binary-file", "qname" : "multipart:binary-file", "signature" : "($filename as xs:string) as xs:base64Binary*", "description" : " Returns the contents of the part/file in the multipart requests with\n the given filename as xs:base64Binary.\n Please note that the file is identified by the filename (and not the\n name of the part) that is contained in the Content-Disposition header\n of the part.\n", "summary" : "

    Returns the contents of the part/file in the multipart requests with\n the given filename as xs:base64Binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filename", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the requested file.
    " } ], "returns" : { "type" : "xs:base64Binary*", "description" : "the said content or the empty sequence if no part with the given filename exists." }, "errors" : [ "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-length", "qname" : "multipart:content-length", "signature" : "($name as xs:string) as xs:integer*", "description" : " Returns the content length of the parts/files in the multipart requests with\n the given part name as xs:integer.\n", "summary" : "

    Returns the content length of the parts/files in the multipart requests with\n the given part name as xs:integer.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the requested part.
    " } ], "returns" : { "type" : "xs:integer*", "description" : "The content-length in bytes of the parts/files or the empty sequence if the part does not exist" }, "errors" : [ "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type", "qname" : "multipart:content-type", "signature" : "($name as xs:string) as xs:string*", "description" : " Returns the content type of the parts/files in the multipart requests with\n the given part name as xs:string.\n", "summary" : "

    Returns the content type of the parts/files in the multipart requests with\n the given part name as xs:string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the requested part.
    " } ], "returns" : { "type" : "xs:string*", "description" : "The content-types of the parts/files or the empty sequence if the part does not exist" }, "errors" : [ "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 1, "name" : "filename", "qname" : "multipart:filename", "signature" : "($name as xs:string) as xs:string*", "description" : " Returns the filenames of the parts/files in the multipart requests with\n the given part name as xs:string.\n", "summary" : "

    Returns the filenames of the parts/files in the multipart requests with\n the given part name as xs:string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the requested part.
    " } ], "returns" : { "type" : "xs:string*", "description" : "The filename of the parts/files or the empty sequence if the part does not exist" }, "errors" : [ "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 0, "name" : "filenames", "qname" : "multipart:filenames", "signature" : "() as xs:string*", "description" : " Returns the filenames of all the parts contained in the multipart\n content of the given request.\n", "summary" : "

    Returns the filenames of all the parts contained in the multipart\n content of the given request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string*", "description" : "the said filenames" }, "errors" : [ "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 0, "name" : "names", "qname" : "multipart:names", "signature" : "() as xs:string*", "description" : " Returns the names of all the parts contained in the multipart\n content of the given request.\n", "summary" : "

    Returns the names of all the parts contained in the multipart\n content of the given request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string*", "description" : "the said names" }, "errors" : [ "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 1, "name" : "part", "qname" : "multipart:part", "signature" : "($name as xs:string) as element(req:part)*", "description" : " Returns the req:part element among all the parts contained\n in the multipart requests with the given name.\n", "summary" : "

    Returns the req:part element among all the parts contained\n in the multipart requests with the given name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the requested part.
    " } ], "returns" : { "type" : "element(req:part)*", "description" : "the said part elements or the empty sequence if no part with the given name exists." }, "errors" : [ "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 1, "name" : "text-content", "qname" : "multipart:text-content", "signature" : "($name as xs:string) as xs:string*", "description" : " Returns the contents of the parts/files in the multipart requests with\n the given part name as a string.\n It is assumed that the character set of the file is UTF-8.\n", "summary" : "

    Returns the contents of the parts/files in the multipart requests with\n the given part name as a string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the requested part.
    " } ], "returns" : { "type" : "xs:string*", "description" : "the said content or the empty sequence if no part with the given filename exists." }, "errors" : [ "request:no-text-content if the value of the part cannot be treated as text", "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 1, "name" : "text-file", "qname" : "multipart:text-file", "signature" : "($filename as xs:string) as xs:string*", "description" : " Returns the contents of the part/file in the multipart requests with\n the given filename as a string.\n It is assumed that the character set of the file is UTF-8.\n Please note that the file is identified by the filename (and not the\n name of the part) that is contained in the Content-Disposition header\n of the part.\n", "summary" : "

    Returns the contents of the part/file in the multipart requests with\n the given filename as a string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filename", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the requested file.
    " } ], "returns" : { "type" : "xs:string*", "description" : "the said content or the empty sequence if no part with the given filename exists." }, "errors" : [ "request:no-text-content if the value of the part cannot be treated as text", "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] } ], "variables" : [ ] }, "http://zorba.io/modules/excel/statistical-zorba" : { "ns" : "http://zorba.io/modules/excel/statistical-zorba", "description" : " This module implements some Excel 2003 statistical functions\n that cannot be implemented with standard XQuery functions.\n It uses Zorba specific functions.\n", "sees" : [ "http://office.microsoft.com/en-us/excel/CH062528311033.aspx" ], "authors" : [ "Daniel Turcanu" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/excel/statistical-zorba", "prefix" : "excel" }, { "uri" : "http://zorba.io/modules/excel/errors", "prefix" : "excel-err" }, { "uri" : "http://zorba.io/modules/excel/math", "prefix" : "excel-math" }, { "uri" : "http://zorba.io/modules/excel/statistical", "prefix" : "excel-statistical" }, { "uri" : "http://www.w3.org/2005/xpath-functions/math", "prefix" : "math" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "stdev", "qname" : "excel:stdev", "signature" : "($numbers as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " Estimates standard deviation based on a sample.\n The standard deviation is a measure of how widely values are dispersed\n from the average value (the mean).\n It is computed with formula:\n sqrt( sum((x-average_x)^2) / (n-1) ) = sqrt ( VAR(numbers) )\n", "summary" : "

    Estimates standard deviation based on a sample.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of numbers or values castable to numeric The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the standard deviation, as numeric type" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "stdeva", "qname" : "excel:stdeva", "signature" : "($numbers as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " Estimates standard deviation based on a sample.\n The standard deviation is a measure of how widely values are dispersed\n from the average value (the mean).\n It is computed with formula:\n sqrt( sum((x-average_x)^2) / (n-1) ) = sqrt ( VARA(numbers) )\n", "summary" : "

    Estimates standard deviation based on a sample.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of numbers or values castable to numeric The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the standard deviation, as numeric type" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "stdevp", "qname" : "excel:stdevp", "signature" : "($numbers as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " Calculates standard deviation based on the entire population given as arguments.\n The standard deviation is a measure of how widely values are dispersed from\n the average value (the mean).\n It is computed with formula:\n sqrt( sum((x-average_x)^2) / n ) = sqrt ( VARP(numbers) )\n", "summary" : "

    Calculates standard deviation based on the entire population given as arguments.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of numbers or values castable to numeric The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the standard deviation, as numeric type" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 1, "name" : "stdevpa", "qname" : "excel:stdevpa", "signature" : "($numbers as xs:anyAtomicType+) as xs:anyAtomicType", "description" : " Calculates standard deviation based on the entire population given as arguments.\n The standard deviation is a measure of how widely values are dispersed from\n the average value (the mean).\n It is computed with formula:\n sqrt( sum((x-average_x)^2) / n ) = sqrt ( VARPA(numbers) )\n", "summary" : "

    Calculates standard deviation based on the entire population given as arguments.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "+", "description" : "
    the sequence of numbers or values castable to numeric The sequence can be of any length, from 1 up.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "the standard deviation, as numeric type" }, "errors" : [ "excel-err:Value if the parameters cannot be casted to numeric type" ] }, { "isDocumented" : true, "arity" : 2, "name" : "subtotal", "qname" : "excel:subtotal", "signature" : "($function_num as xs:integer, $numbers as xs:anyAtomicType*) as xs:anyAtomicType", "description" : " Moved from math module.\n Returns a subtotal in a sequence of numbers.\n The function applied is given by $function_num.\n", "summary" : "

    Moved from math module.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "function_num", "type" : "xs:integer", "occurrence" : null, "description" : "
    defines the function to be applied on sequence values. The possible values are:
    1 or 101
    AVERAGE
    2 or 102
    COUNT
    3 or 103
    COUNTA
    4 or 104
    MAX
    5 or 105
    MIN
    6 or 106
    PRODUCT
    7 or 107
    STDEV
    8 or 108
    STDEVP
    9 or 109
    SUM
    10 or 110
    VAR
    11 or 111
    VARP
    In this implementation there is no difference between x and 10x.

    " }, { "name" : "numbers", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of numbers or values castable to numeric. The sequence can be of any length.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The function result, as numeric type" }, "errors" : [ "depends on the function called", "excel-err:Num if $function_num is not a value between 1 .. 11 or 101 .. 111" ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/debug" : { "ns" : "http://www.28msec.com/modules/debug", "description" : " This module contains internal debug functions.\n", "sees" : [ ], "authors" : [ "Federico Cavalieri" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/debug", "prefix" : "debug" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "non-seeakable-streamable-string", "qname" : "debug:non-seeakable-streamable-string", "signature" : "() as string external", "description" : " Returns a non seekable streamable string\n", "summary" : "

    Returns a non seekable streamable string\n

    ", "annotation_str" : " %an:deterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "deterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "string", "description" : "a non seekable streamable string" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "test-01-cache", "qname" : "debug:test-01-cache", "signature" : "($arg as xs:integer) as item()* external", "description" : " Equivalent to:\n declare %an:cache function local:test-01-cache($x as xs:integer)\n {\n if ($x < 10)\n then $x * $x\n else if ($x < 20)\n then ()\n else ($x, \" == \", $x * $x)\n };\n", "summary" : "

    Equivalent to:\n declare %an:cache function local:test-01-cache($x as xs:integer)\n {\n if ($x < 10)\n then $x * $x\n else if ($x < 20)\n then ()\n else ($x, \" == \", $x * $x)\n };\n

    ", "annotation_str" : " %an:cache", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "cache", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:integer", "occurrence" : null, "description" : "
    as described above
    " } ], "returns" : { "type" : "item()*", "description" : "as described above" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "test-01-sd", "qname" : "debug:test-01-sd", "signature" : "($arg as xs:integer) as item()* external", "description" : " Equivalent to:\n declare %an:strictlydeterministic function local:test-01-sd($x as xs:integer)\n {\n if ($x < 10)\n then $x * $x\n else if ($x < 20)\n then ()\n else ($x, \" == \", $x * $x)\n };\n", "summary" : "

    Equivalent to:\n declare %an:strictlydeterministic function local:test-01-sd($x as xs:integer)\n {\n if ($x < 10)\n then $x * $x\n else if ($x < 20)\n then ()\n else ($x, \" == \", $x * $x)\n };\n

    ", "annotation_str" : " %an:strictlydeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "strictlydeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:integer", "occurrence" : null, "description" : "
    as described above
    " } ], "returns" : { "type" : "item()*", "description" : "as described above" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "test-02-cache", "qname" : "debug:test-02-cache", "signature" : "($arg) as item()* external", "description" : " Equivalent to:\n declare %an:cache function local:test-02-cache($arg)\n {\n serialize($arg),\n uuid:uuid()\n };\n", "summary" : "

    Equivalent to:\n declare %an:cache function local:test-02-cache($arg)\n {\n serialize($arg),\n uuid:uuid()\n };\n

    ", "annotation_str" : " %an:cache", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "cache", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : null, "occurrence" : null, "description" : "
    as described above
    " } ], "returns" : { "type" : "item()*", "description" : "as described above" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "test-02-sd", "qname" : "debug:test-02-sd", "signature" : "($arg) as item()* external", "description" : " Equivalent to:\n declare %an:strictlydeterministic function local:test-02-sd($arg)\n {\n serialize($arg),\n uuid:uuid()\n };\n", "summary" : "

    Equivalent to:\n declare %an:strictlydeterministic function local:test-02-sd($arg)\n {\n serialize($arg),\n uuid:uuid()\n };\n

    ", "annotation_str" : " %an:strictlydeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "strictlydeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : null, "occurrence" : null, "description" : "
    as described above
    " } ], "returns" : { "type" : "item()*", "description" : "as described above" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "test-03-cache", "qname" : "debug:test-03-cache", "signature" : "() as item()* external", "description" : " Equivalent to:\n declare %an:cache function local:test-03-cache()\n {\n { \"a\" : 1 },\n [1],\n <a/>,\n 1\n };\n", "summary" : "

    Equivalent to:\n declare %an:cache function local:test-03-cache()\n {\n { \"a\" : 1 },\n [1],\n <a/>,\n 1\n };\n

    ", "annotation_str" : " %an:cache", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "cache", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "item()*", "description" : "as described above" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "test-03-sd", "qname" : "debug:test-03-sd", "signature" : "() as item()* external", "description" : " Equivalent to:\n declare %an:strictlydeterministic function local:test-03-sd()\n {\n { \"a\" : 1 },\n [1],\n <a/>,\n 1\n };\n", "summary" : "

    Equivalent to:\n declare %an:strictlydeterministic function local:test-03-sd()\n {\n { \"a\" : 1 },\n [1],\n <a/>,\n 1\n };\n

    ", "annotation_str" : " %an:strictlydeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "strictlydeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "item()*", "description" : "as described above" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "test-04-cache", "qname" : "debug:test-04-cache", "signature" : "($x, $y) as item()* external", "description" : " Equivalent to:\n declare %an:cache function local:test-04-cache($x, $y)\n {\n debug:non-seeakable-streamable-string(),\n {\"key\" : debug:non-seeakable-streamable-string()},\n [debug:non-seeakable-streamable-string()],\n <a>{debug:non-seeakable-streamable-string()}</a>\n serialize($x),\n serialize($y)\n };\n", "summary" : "

    Equivalent to:\n declare %an:cache function local:test-04-cache($x, $y)\n {\n debug:non-seeakable-streamable-string(),\n {\"key\" : debug:non-seeakable-streamable-string()},\n [debug:non-seeakable-streamable-string()],\n <a>{debug:non-seeakable-streamable-string()}</a>\n serialize($x),\n serialize($y)\n };\n

    ", "annotation_str" : " %an:cache", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "cache", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "x", "type" : null, "occurrence" : null, "description" : "
    as described above
    " }, { "name" : "y", "type" : null, "occurrence" : null, "description" : "
    as described above
    " } ], "returns" : { "type" : "item()*", "description" : "as described above" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "test-04-sd", "qname" : "debug:test-04-sd", "signature" : "($x, $y) as item()* external", "description" : " Equivalent to:\n declare %an:strictlydeterministic function local:test-04-sd($x, $y)\n {\n debug:non-seeakable-streamable-string(),\n {\"key\" : debug:non-seeakable-streamable-string()},\n [debug:non-seeakable-streamable-string()],\n <a>{debug:non-seeakable-streamable-string()}</a>\n serialize($x),\n serialize($y)\n };\n", "summary" : "

    Equivalent to:\n declare %an:strictlydeterministic function local:test-04-sd($x, $y)\n {\n debug:non-seeakable-streamable-string(),\n {\"key\" : debug:non-seeakable-streamable-string()},\n [debug:non-seeakable-streamable-string()],\n <a>{debug:non-seeakable-streamable-string()}</a>\n serialize($x),\n serialize($y)\n };\n

    ", "annotation_str" : " %an:strictlydeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "strictlydeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "x", "type" : null, "occurrence" : null, "description" : "
    as described above
    " }, { "name" : "y", "type" : null, "occurrence" : null, "description" : "
    as described above
    " } ], "returns" : { "type" : "item()*", "description" : "as described above" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "test-05-cache", "qname" : "debug:test-05-cache", "signature" : "($x as xs:boolean, $y) as item()* external", "description" : " Equivalent to:\n declare %an:cache function local:test-05-cache($x as xs:boolean, $y)\n {\n if ($x)\n then $y\n else $x\n };\n", "summary" : "

    Equivalent to:\n declare %an:cache function local:test-05-cache($x as xs:boolean, $y)\n {\n if ($x)\n then $y\n else $x\n };\n

    ", "annotation_str" : " %an:cache", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "cache", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "x", "type" : "xs:boolean", "occurrence" : null, "description" : "
    as described above
    " }, { "name" : "y", "type" : null, "occurrence" : null, "description" : "
    as described above
    " } ], "returns" : { "type" : "item()*", "description" : "as described above" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "test-05-sd", "qname" : "debug:test-05-sd", "signature" : "($x as xs:boolean, $y) as item()* external", "description" : " Equivalent to:\n declare %an:strictlydeterministic function local:test-05-sd($x as xs:boolean, $y)\n {\n if ($x)\n then $y\n else $x\n };\n", "summary" : "

    Equivalent to:\n declare %an:strictlydeterministic function local:test-05-sd($x as xs:boolean, $y)\n {\n if ($x)\n then $y\n else $x\n };\n

    ", "annotation_str" : " %an:strictlydeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "strictlydeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "x", "type" : "xs:boolean", "occurrence" : null, "description" : "
    as described above
    " }, { "name" : "y", "type" : null, "occurrence" : null, "description" : "
    as described above
    " } ], "returns" : { "type" : "item()*", "description" : "as described above" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "uuid", "qname" : "debug:uuid", "signature" : "() as string external", "description" : " This function is not deterministic despite the annotation\n", "summary" : "

    This function is not deterministic despite the annotation\n

    ", "annotation_str" : " %an:deterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "deterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "string", "description" : "a uuid" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/json-xml" : { "ns" : "http://zorba.io/modules/json-xml", "description" : " Using this module, you can parse JSON data into XML, manipulate it like any\n other XML data using XQuery, and serialize the result back as JSON.

    \n There are many ways to represent JSON data in XML, some loss-less (\"round\n tripable\") and some lossy (\"one way\"). Loss-less representations preserve\n the JSON data types boolean, number, and null; lossy\n representations convert all data to strings.\n

    \n For a loss-less representation, this module implements that proposed by\n John Snelson.\n For example:\n

    \n   {\n     \"firstName\" : \"John\",\n     \"lastName\" : \"Smith\",\n     \"address\" : {\n       \"streetAddress\" : \"21 2nd Street\",\n       \"city\" : \"New York\",\n       \"state\" : \"NY\",\n       \"postalCode\" : 10021\n     },\n     \"phoneNumbers\" : [ \"212 732-1234\", \"646 123-4567\" ]\n   }\n 
    \n would be represented as:\n
    \n   <json type=\"object\">\n     <pair name=\"firstName\" type=\"string\">John</pair>\n     <pair name=\"lastName\" type=\"string\">Smith</pair>\n     <pair name=\"address\" type=\"object\">\n       <pair name=\"streetAddress\" type=\"string\">21 2nd Street</pair>\n       <pair name=\"city\" type=\"string\">New York</pair>\n       <pair name=\"state\" type=\"string\">NY</pair>\n       <pair name=\"postalCode\" type=\"number\">10021</pair>\n     </pair>\n     <pair name=\"phoneNumbers\" type=\"array\">\n       <item type=\"string\">212 732-1234</item>\n       <item type=\"string\">646 123-4567</item>\n     </pair>\n   </json>\n 
    \n For a lossy representation, this module implements\n JsonML (the array form).\n For example:\n
    \n   [ \"person\",\n     { \"created\" : \"2006-11-11T19:23\",\n       \"modified\" : \"2006-12-31T23:59\" },\n     [ \"firstName\", \"Robert\" ],\n     [ \"lastName\", \"Smith\" ],\n     [ \"address\",\n       { \"type\" : \"home\" },\n       [ \"street\", \"12345 Sixth Ave\" ],\n       [ \"city\", \"Anytown\" ],\n       [ \"state\", \"CA\" ],\n       [ \"postalCode\", \"98765-4321\" ]\n     ]\n   ]\n 
    \n would be represented as:\n
    \n   <person created=\"2006-11-11T19:23\" modified=\"2006-12-31T23:59\">\n     <firstName>Robert</firstName>\n     <lastName>Smith</lastName>\n     <address type=\"home\">\n       <street>12345 Sixth Ave</street>\n       <city>Anytown</city>\n       <state>CA</state>\n       <postalCode>98765-4321</postalCode>\n     </address>\n   </person>\n 
    \n", "sees" : [ ], "authors" : [ "Paul J. Lucas" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://zorba.io/modules/json-xml", "prefix" : "jx" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "json-to-xml", "qname" : "jx:json-to-xml", "signature" : "($json as json-item()?) as element(*,xs:untyped)?", "description" : " Converts JSON data into an XDM instance using the Snelson representation\n described above.

    \n", "summary" : "

    Converts JSON data into an XDM instance using the Snelson representation\n described above.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "json", "type" : "json-item()", "occurrence" : "?", "description" : "
    The JSON data.
    " } ], "returns" : { "type" : "element(*,xs:untyped)?", "description" : "said XDM instance." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "json-to-xml", "qname" : "jx:json-to-xml", "signature" : "($json as json-item()?, $options as object()) as element(*,xs:untyped)?", "description" : " Converts JSON data into an XDM instance using one of the representations\n described above.

    \n", "summary" : "

    Converts JSON data into an XDM instance using one of the representations\n described above.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "json", "type" : "json-item()", "occurrence" : "?", "description" : "
    The JSON data.
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    The JSON conversion options, for example:
     { \"json-format\" : \"JsonML-array\" } 
    " } ], "returns" : { "type" : "element(*,xs:untyped)?", "description" : "said XDM instance." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "xml-to-json", "qname" : "jx:xml-to-json", "signature" : "($xml as item()*) as json-item()*", "description" : " Converts XML data into a JSON item using the Snelson representation\n described above.

    \n", "summary" : "

    Converts XML data into a JSON item using the Snelson representation\n described above.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "xml", "type" : "item()", "occurrence" : "*", "description" : "
    The XML data to convert.
    " } ], "returns" : { "type" : "json-item()*", "description" : "said JSON items." }, "errors" : [ "zerr:ZJSE0001 if $xml is not a document or element node.", "zerr:ZJSE0002 if $xml contains an element that is missing a required attribute.", "zerr:ZJSE0003 if $xml contains an attribute having an illegal value.", "zerr:ZJSE0004 if $xml contains an illegal element. type.", "zerr:ZJSE0007 if $xml contains an element that is missing a required value.", "zerr:ZJSE0008 if $xml contains an illegal value for a JSON type." ] }, { "isDocumented" : true, "arity" : 2, "name" : "xml-to-json", "qname" : "jx:xml-to-json", "signature" : "($xml as item()*, $options as object()) as json-item()*", "description" : " Converts XML data into a JSON item using one of the respresentations\n described above.

    \n", "summary" : "

    Converts XML data into a JSON item using one of the respresentations\n described above.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "xml", "type" : "item()", "occurrence" : "*", "description" : "
    The XML data to convert.
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    The conversion options, for example:
     { \"json-format\" : \"JsonML-array\" } 
    " } ], "returns" : { "type" : "json-item()*", "description" : "said JSON items." }, "errors" : [ "zerr:ZJSE0001 if $xml is not a document or element node.", "zerr:ZJSE0002 if $xml contains an element that is missing a required attribute.", "zerr:ZJSE0003 if $xml contains an attribute having an illegal value.", "zerr:ZJSE0004 if $xml contains an illegal element. type.", "zerr:ZJSE0007 if $xml contains an element that is missing a required value.", "zerr:ZJSE0008 if $xml contains an illegal value for a JSON type." ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/image/manipulation" : { "ns" : "http://www.zorba-xquery.com/modules/image/manipulation", "description" : " This module provides functions to handle image manipulations like resizing, zooming,\n special effects etc.\n

    The errors raised by functions of this module have the namespace\n http://www.zorba-xquery.com/modules/image/error (associated with prefix ierr).

    \n", "sees" : [ ], "authors" : [ "Daniel Thomas" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://www.zorba-xquery.com/modules/image/error", "prefix" : "ierr" }, { "uri" : "http://www.zorba-xquery.com/modules/image/image", "prefix" : "image" }, { "uri" : "http://www.zorba-xquery.com/modules/image/manipulation", "prefix" : "man" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "add-noise", "qname" : "man:add-noise", "signature" : "($image as xs:base64Binary, $noise-type as xs:string) as xs:base64Binary", "description" : " Add noise to an image.\n Allowed noise types are:\n
      \n
    • UniformNoise
    • \n
    • GaussianNoise
    • \n
    • MultiplicativeGaussianNoise
    • \n
    • ImpulseNoise
    • \n
    • LaplaceianNoise
    • \n
    • PoissonNoise
    • \n
    \n", "summary" : "

    Add noise to an image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "noise-type", "type" : "xs:string", "occurrence" : null, "description" : "
    specifies the type of noise to add
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A copy of $image with added noise" }, "errors" : [ "ierr:IM001 passed image is invalid", "err:FORG0001 unsupported noise type" ] }, { "isDocumented" : true, "arity" : 3, "name" : "blur", "qname" : "man:blur", "signature" : "($image as xs:base64Binary, $radius as xs:int, $sigma as xs:int) as xs:base64Binary external", "description" : " Blur an image.\n", "summary" : "

    Blur an image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "radius", "type" : "xs:int", "occurrence" : null, "description" : "
    is the radius of the Gaussian in pixels.
    " }, { "name" : "sigma", "type" : "xs:int", "occurrence" : null, "description" : "
    is the standard deviation of the Laplacian in pixels.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A blured copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 3, "name" : "charcoal", "qname" : "man:charcoal", "signature" : "($image as xs:base64Binary, $radius as xs:double, $sigma as xs:double) as xs:base64Binary external", "description" : " Apply a charcoal effect to the image (looks like a charcoal sketch).\n", "summary" : "

    Apply a charcoal effect to the image (looks like a charcoal sketch).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "radius", "type" : "xs:double", "occurrence" : null, "description" : "
    radius of the Gaussian in pixels
    " }, { "name" : "sigma", "type" : "xs:double", "occurrence" : null, "description" : "
    standard deviation of the Laplacian in pixels
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A charcoaled copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 3, "name" : "chop", "qname" : "man:chop", "signature" : "($image as xs:base64Binary, $upper-left-x as xs:unsignedInt, $upper-left-y as xs:unsignedInt) as xs:base64Binary external", "description" : " Copy a part of a source image as new image.\n The copied part is all right of $upper-left-x and below $upper-left-y.\n", "summary" : "

    Copy a part of a source image as new image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    source image
    " }, { "name" : "upper-left-x", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    x position of the upper left corner of the part to copy
    " }, { "name" : "upper-left-y", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    y position of the upper left corner of the part to copy
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A new image copied from a part of source image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 2, "name" : "contrast", "qname" : "man:contrast", "signature" : "($image as xs:base64Binary, $sharpen as xs:double) as xs:base64Binary external", "description" : " Contrast an image (enhances image intensity differences) by a given value.\n", "summary" : "

    Contrast an image (enhances image intensity differences) by a given value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "sharpen", "type" : "xs:double", "occurrence" : null, "description" : "
    defines how much the image is contrasted.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A contrasted copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 3, "name" : "crop", "qname" : "man:crop", "signature" : "($image as xs:base64Binary, $lower-right-x as xs:unsignedInt, $lower-right-y as xs:unsignedInt) as xs:base64Binary external", "description" : " Copy a part of a source image as new image.\n The copied part is all left of $lower-right-x and above $lower-right-y.\n", "summary" : "

    Copy a part of a source image as new image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    source image
    " }, { "name" : "lower-right-x", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    x position of the lower right corner of the part to copy
    " }, { "name" : "lower-right-y", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    y position of the lower right corner of the part to copy
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A new image copied from a part of source image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "despeckle", "qname" : "man:despeckle", "signature" : "($image as xs:base64Binary) as xs:base64Binary external", "description" : " Despeckle an image.\n", "summary" : "

    Despeckle an image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A despeckled copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 2, "name" : "edge", "qname" : "man:edge", "signature" : "($image as xs:base64Binary, $radius as xs:unsignedInt) as xs:base64Binary external", "description" : " Highlight edges in an image.\n", "summary" : "

    Highlight edges in an image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "radius", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    radius of the pixel neighborhood (0 for automatic selection)
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "An edged copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 3, "name" : "emboss", "qname" : "man:emboss", "signature" : "($image as xs:base64Binary, $radius as xs:double, $sigma as xs:double) as xs:base64Binary external", "description" : " Emboss an images (highlights edges with 3D effect).\n", "summary" : "

    Emboss an images (highlights edges with 3D effect).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "radius", "type" : "xs:double", "occurrence" : null, "description" : "
    radius of the Gaussian in pixels
    " }, { "name" : "sigma", "type" : "xs:double", "occurrence" : null, "description" : "
    standard deviation of the Laplacian in pixels
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "An embossed copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "enhance", "qname" : "man:enhance", "signature" : "($image as xs:base64Binary) as xs:base64Binary external", "description" : " Enhance an images (minimizes noise).\n", "summary" : "

    Enhance an images (minimizes noise).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "An enhanced copy of $image." }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "equalize", "qname" : "man:equalize", "signature" : "($image as xs:base64Binary) as xs:base64Binary external", "description" : " Equalize an images (histogramm equalization).\n", "summary" : "

    Equalize an images (histogramm equalization).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "An equalized copy of $image." }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "erase", "qname" : "man:erase", "signature" : "($image as xs:base64Binary) as xs:base64Binary external", "description" : " Set all pixels of the image to the current backround color.\n In most cases, this will result in all pixels to be set to white.\n", "summary" : "

    Set all pixels of the image to the current backround color.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    image to erase
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A copy of image with all pixels set to the current background color" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "flip", "qname" : "man:flip", "signature" : "($image as xs:base64Binary) as xs:base64Binary external", "description" : " Flip an image (vertical rotation).\n", "summary" : "

    Flip an image (vertical rotation).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    source image
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A vertically rotated copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "flop", "qname" : "man:flop", "signature" : "($image as xs:base64Binary) as xs:base64Binary external", "description" : " Flop an image (horizontal rotation).\n", "summary" : "

    Flop an image (horizontal rotation).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    source image
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A horizontally rotated copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 2, "name" : "gamma", "qname" : "man:gamma", "signature" : "($image as xs:base64Binary, $gamma-value as xs:double) as xs:base64Binary external", "description" : " Gamma correct an image.\n Gamma values less than zero will erase the image.\n", "summary" : "

    Gamma correct an image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "gamma-value", "type" : "xs:double", "occurrence" : null, "description" : "
    value for which to gamma correct the image
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A gamma corrected copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 4, "name" : "gamma", "qname" : "man:gamma", "signature" : "($image as xs:base64Binary, $gamma-red as xs:double, $gamma-green as xs:double, $gamma-blue as xs:double) as xs:base64Binary external", "description" : " Gamma correct an image for every color channel seperately.\n Gamma values less than zero for any color will erase the corresponding color.\n", "summary" : "

    Gamma correct an image for every color channel seperately.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "gamma-red", "type" : "xs:double", "occurrence" : null, "description" : "
    value to gamma correct the red channel of the image
    " }, { "name" : "gamma-green", "type" : "xs:double", "occurrence" : null, "description" : "
    value to gamma correct the green channel of the image
    " }, { "name" : "gamma-blue", "type" : "xs:double", "occurrence" : null, "description" : "
    value to gamma correct the blue channel of the image
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A gamma corrected copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 2, "name" : "implode", "qname" : "man:implode", "signature" : "($image as xs:base64Binary, $factor as xs:double) as xs:base64Binary external", "description" : " Apply an implode effect to an image (a sort of special effect).\n", "summary" : "

    Apply an implode effect to an image (a sort of special effect).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "factor", "type" : "xs:double", "occurrence" : null, "description" : "
    factor to implode to
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "An imploded copy of $image." }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 2, "name" : "oil-paint", "qname" : "man:oil-paint", "signature" : "($image as xs:base64Binary, $radius as xs:double) as xs:base64Binary external", "description" : " Apply an oil paint effect to an image (makes the image look as if it was\n an oil paint).\n", "summary" : "

    Apply an oil paint effect to an image (makes the image look as if it was\n an oil paint).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "radius", "type" : "xs:double", "occurrence" : null, "description" : "
    radius with which to oil paint
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A oil-painted copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 5, "name" : "overlay", "qname" : "man:overlay", "signature" : "($image as xs:base64Binary, $overlay-image as xs:base64Binary, $overlay-upper-left-x as xs:unsignedInt, $overlay-upper-left-y as xs:unsignedInt, $operator as xs:string) as xs:base64Binary", "description" : " Overlay $image with $overlay-image at the specfied position.\n The $operator defines the details of the overlay and can have one of the\n following values:\n
      \n
    • OverCompositeOp: The result is the union of the two image shapes\n with the overlay image obscuring image in the region of overlap.
    • \n
    • InCompositeOp: The result is a simple overlay image cut by the shape\n of image. None of the image data of image is included in the result.
    • \n
    • OutCompositeOp: The resulting image is the overlay image with the shape\n of image cut out.
    • \n
    • AtopCompositeOp: The result is the same shape as image, with overlay\n image obscuring image there the image shapes overlap. Note that this\n differs from OverCompositeOp because the portion of composite image\n outside of image's shape does not appear in the result.
    • \n
    • XorCompositeOp: The result is the image data from both overlay image\n and image that is outside the overlap region. The overlap region will\n be blank.
    • \n
    • PlusCompositeOp: The result is just the sum of the image data of both\n images. Output values are cropped to 255 (no overflow). This operation\n is independent of the matte channels.
    • \n
    • MinusCompositeOp: The result of overlay image - image, with overflow\n cropped to zero. The matte chanel is ignored (set to 255, full\n coverage).
    • \n
    • AddCompositeOp: The result of overlay image + image, with overflow\n wrapping around (mod 256).
    • \n
    • SubtractCompositeOp: The result of overlay image - image, with underflow\n wrapping around (mod 256). The add and subtract operators can be used to\n perform reverible transformations.
    • \n
    • DifferenceCompositeOp: The result of abs(overlay image - image). This is\n useful for comparing two very similar images.
    • \n
    • BumpmapCompositeOp: The result image shaded by overlay image.
    • \n
    \n", "summary" : "

    Overlay $image with $overlay-image at the specfied position.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    base image
    " }, { "name" : "overlay-image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    image to overlay.
    " }, { "name" : "overlay-upper-left-x", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    horizontal position within $image where the left upper edge of the $overlay-image is placed
    " }, { "name" : "overlay-upper-left-y", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    vertical position within $image where the left upper edge of the $overlay-image is placed
    " }, { "name" : "operator", "type" : "xs:string", "occurrence" : null, "description" : "
    defines how the overlay image should be overlayed (see details in operator listing above)
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A new image consisting of $image overlayed with $overlay-image." }, "errors" : [ "ierr:IM001 passed image is invalid", "err:FORG0001 unsupported operator" ] }, { "isDocumented" : true, "arity" : 2, "name" : "reduce-noise", "qname" : "man:reduce-noise", "signature" : "($image as xs:base64Binary, $order as xs:double) as xs:base64Binary external", "description" : " Reduce noise of an image using a noise peak elemination filter.\n", "summary" : "

    Reduce noise of an image using a noise peak elemination filter.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "order", "type" : "xs:double", "occurrence" : null, "description" : "
    defines how much the noise is reduced
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A copy of $image with reduced noise" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 3, "name" : "resize", "qname" : "man:resize", "signature" : "($image as xs:base64Binary, $width as xs:unsignedInt, $height as xs:unsignedInt) as xs:base64Binary external", "description" : " Get a copy of the passed image with changed width and height (without\n zooming the image's content).\n To change the size of the actual contents of an image, use the zoom function.\n More in detail: If the new dimensions are greater than the current dimensions\n the new image will have the passed image in the upper left corner and the rest\n will be filled with the current background color.\n If the passed dimensions are less than the current dimensions, the new image\n will contain the specified rectangle of the passed image beginning at the upper\n left corner.\n", "summary" : "

    Get a copy of the passed image with changed width and height (without\n zooming the image's content).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    image to resize
    " }, { "name" : "width", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    new width
    " }, { "name" : "height", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    new height
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "resized copy of the source image" }, "errors" : [ "ierr:IM001 passed image is invalid." ] }, { "isDocumented" : true, "arity" : 2, "name" : "rotate", "qname" : "man:rotate", "signature" : "($image as xs:base64Binary, $angle as xs:int) as xs:base64Binary external", "description" : " Get a new image as rotated copy of a passed source image (rotated by -360 to\n 360 degrees).\n The image is enlarged if this is required for containing the rotated image,\n but never shrunk even if the rotation would make a smaller image possible.\n", "summary" : "

    Get a new image as rotated copy of a passed source image (rotated by -360 to\n 360 degrees).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    source image.
    " }, { "name" : "angle", "type" : "xs:int", "occurrence" : null, "description" : "
    between -360 to 360 degrees. Other values will be adjusted by modulo 360
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A rotated copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 2, "name" : "solarize", "qname" : "man:solarize", "signature" : "($image as xs:base64Binary, $factor as xs:double) as xs:base64Binary external", "description" : " Apply a solarize effect to the image (similar to the effect seen when\n exposing a photographic film to light during the development process).\n", "summary" : "

    Apply a solarize effect to the image (similar to the effect seen when\n exposing a photographic film to light during the development process).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "factor", "type" : "xs:double", "occurrence" : null, "description" : "
    strength of the solarization (0 to 65535; 65535=100%)
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A solarized copy of $image." }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 2, "name" : "stereo", "qname" : "man:stereo", "signature" : "($left-image as xs:base64Binary, $right-image as xs:base64Binary) as xs:base64Binary external", "description" : " Make two passed images appear as stereo image when viewed with red-blue glasses.\n Both images should be same but from a slightly different angle for this to work.\n Both images should have the same size, if not, the size of the left image will\n be taken.\n", "summary" : "

    Make two passed images appear as stereo image when viewed with red-blue glasses.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "left-image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    left image for the stereo image.
    " }, { "name" : "right-image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    right image for the stereo image.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A new image as combined stereo image of both source images" }, "errors" : [ "ierr:IM001 one of the passed images is invalid" ] }, { "isDocumented" : true, "arity" : 5, "name" : "sub-image", "qname" : "man:sub-image", "signature" : "($image as xs:base64Binary, $left-upper-x as xs:unsignedInt, $left-upper-y as xs:unsignedInt, $width as xs:unsignedInt, $height as xs:unsignedInt) as xs:base64Binary external", "description" : " Copy a part of the source image specified by a rectangle.\n If the passed parameters for the sub-image specify a rectangle that isn't\n entirely within the source image only the area that lies within the image\n boundaries will be returned.\n", "summary" : "

    Copy a part of the source image specified by a rectangle.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the image from which to extract a sub-image
    " }, { "name" : "left-upper-x", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    is the x value of the upper left corner of the rectangle to cut out
    " }, { "name" : "left-upper-y", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    is the y value of the upper left corner of the rectangle to cut out.
    " }, { "name" : "width", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    width of the rectangle to cut out
    " }, { "name" : "height", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    height of the rectangle to cut out
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A new image containing parts of the source image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 2, "name" : "swirl", "qname" : "man:swirl", "signature" : "($image as xs:base64Binary, $degree as xs:double) as xs:base64Binary external", "description" : " Swirl an image (image pixels are rotated by degree).\n", "summary" : "

    Swirl an image (image pixels are rotated by degree).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "degree", "type" : "xs:double", "occurrence" : null, "description" : "
    degree to swirl image pixels
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A swirled copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 2, "name" : "transparent", "qname" : "man:transparent", "signature" : "($image as xs:base64Binary, $color as xs:string) as xs:base64Binary", "description" : " Make all pixels of the specfied color transparent.\n This works correctly only with image types supporting transparency\n (e.g GIF or PNG).\n", "summary" : "

    Make all pixels of the specfied color transparent.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "color", "type" : "xs:string", "occurrence" : null, "description" : "
    color to make transparent (e.g. '#FFFFFF')
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A copy of $image with the specified color made transparent." }, "errors" : [ "ierr:IM001 passed image is invalid", "err:FORG0001 unsupported color" ] }, { "isDocumented" : true, "arity" : 1, "name" : "trim", "qname" : "man:trim", "signature" : "($image as xs:base64Binary) as xs:base64Binary external", "description" : " Trim edges of the image's background color from the image.\n", "summary" : "

    Trim edges of the image's background color from the image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A trimmed copy of $image" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 2, "name" : "watermark", "qname" : "man:watermark", "signature" : "($image as xs:base64Binary, $watermark as xs:base64Binary) as xs:base64Binary external", "description" : " Add a $watermark image to $image.\n", "summary" : "

    Add a $watermark image to $image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the source image
    " }, { "name" : "watermark", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the watermark image
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A watermarked copy of $image" }, "errors" : [ "ierr:IM001 one of the passed images is invalid" ] }, { "isDocumented" : true, "arity" : 2, "name" : "zoom-by-height", "qname" : "man:zoom-by-height", "signature" : "($image as xs:base64Binary, $height as xs:unsignedInt) as xs:base64Binary external", "description" : " Zoom the passed image to a given new height while keeping the ratio between\n width and height.\n So, the width is scaled accordingly.\n Important note: this function does not change the size information stored\n in the image (e.g. basic:width will not show a different value).\n", "summary" : "

    Zoom the passed image to a given new height while keeping the ratio between\n width and height.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    image to resize
    " }, { "name" : "height", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    new height for the image in pixels
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A copy of $image with given $height and width adjusted accordingly" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 2, "name" : "zoom-by-width", "qname" : "man:zoom-by-width", "signature" : "($image as xs:base64Binary, $width as xs:unsignedInt) as xs:base64Binary external", "description" : " Zoom the passed image to a given new width while keeping the ratio between\n width and height.\n So, the height is scaled accordingly.\n Important note: this function does not change the size information stored\n in the image (e.g. basic:width will not show a different value).\n", "summary" : "

    Zoom the passed image to a given new width while keeping the ratio between\n width and height.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    image to resize
    " }, { "name" : "width", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    new width for the image in pixels
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A copy of $image with given $width and height changed accordingly" }, "errors" : [ "ierr:IM001 passed image is invalid" ] }, { "isDocumented" : true, "arity" : 2, "name" : "zoom", "qname" : "man:zoom", "signature" : "($image as xs:base64Binary, $ratio as xs:double) as xs:base64Binary external", "description" : " Zoom the passed image by the specified factor while keeping the ratio between\n width and height.\n A ratio of less than 1 will make the image smaller.\n A ratio of less or equal than 0 will not effect the image.\n Important note: this function does not change the size information stored in the\n image (e.g. basic:width will not show a different value).\n", "summary" : "

    Zoom the passed image by the specified factor while keeping the ratio between\n width and height.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "image", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    image to resize
    " }, { "name" : "ratio", "type" : "xs:double", "occurrence" : null, "description" : "
    ratio to zoom width and height by
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "A copy of $image with resized content" }, "errors" : [ "ierr:IM001 passed image is invalid" ] } ], "variables" : [ ] }, "http://zorba.io/modules/http-client-wrapper" : { "ns" : "http://zorba.io/modules/http-client-wrapper", "description" : "

    This module provides conversion functions between the\n XML Expath http-client request and response formats and the\n JSON http-client request and response formats used by the\n http://zorba.io/modules/http-client module.\n

    \n

    This module is reserved for internal use by the\n http://www.zorba-xquery.com/modules/http-client and the\n http://expath.org/ns/http-client modules.\n This module may be removed at any time. Method signature and\n semantics may change.\n

    \n", "sees" : [ ], "authors" : [ "Federico Cavalieri" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://expath.org/ns/error", "prefix" : "error" }, { "uri" : "http://expath.org/ns/http-client", "prefix" : "http-schema" }, { "uri" : "http://zorba.io/modules/http-client-wrapper", "prefix" : "http-wrapper" }, { "uri" : "http://jsoniq.org/functions", "prefix" : "jn" }, { "uri" : "http://zorba.io/modules/http-client", "prefix" : "json-http" }, { "uri" : "http://jsoniq.org/function-library", "prefix" : "libjn" }, { "uri" : "http://www.w3.org/2010/xslt-xquery-serialization", "prefix" : "ser" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 3, "name" : "http-nondeterministic-request", "qname" : "http-wrapper:http-nondeterministic-request", "signature" : "($request as element(*)?, $href as xs:string?, $bodies as item()*) as item()+", "description" : "

    This function sends an HTTP request and returns the corresponding response.\n This function is declared non-deterministic and should only be used to issue\n requests which do not change the state of the server.

    \n

    Its inputs, outputs, and behavior are identical to the\n EXPath http-client's\n send-request() function (except that HTML responses are not tidied\n into XML - see the note above). It\n is provided here for use in Zorba installations that do not have\n the EXPath module available. If you have the option of using the\n EXPath module instead of this function, please do so, as it will\n allow your application to be more interoperable between different\n XQuery engines.

    \n

    Full documentation of the $request parameter can be found in\n the EXPath\n specification.

    \n", "summary" : "

    This function sends an HTTP request and returns the corresponding response.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "request", "type" : "element(*)", "occurrence" : "?", "description" : "
    Contains the various parameters of the request (see above).
    " }, { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "
    The URL to which the request will be made (see note above). If this parameter is specified, it will override the \"href\" attribute of $request.
    " }, { "name" : "bodies", "type" : "item()", "occurrence" : "*", "description" : "
    is the request body content, for HTTP methods that can contain a body in the request (i.e. POST and PUT). It is an error if this param is not the empty sequence for methods
    " } ], "returns" : { "type" : "item()+", "description" : "standard http-client return type." }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC002 Error parsing the response content as XML.", "error:HC003 With a multipart response, the override-media-type must be either a multipart media type or application/octet-stream.", "error:HC004 The src attribute on the body element is mutually exclusive with all other attribute (except the media-type).", "error:HC005 The input request element is not valid.", "error:HC006 A timeout occurred waiting for the response.", "error:HCV02 Trying to follow a redirect of a POST, PUT, or DELETE request" ] }, { "isDocumented" : true, "arity" : 3, "name" : "http-sequential-request", "qname" : "http-wrapper:http-sequential-request", "signature" : "($request as element(*)?, $href as xs:string?, $bodies as item()*) as item()+", "description" : "

    This function sends an HTTP request and returns the corresponding response.\n This function is declared sequential and can be used to issue\n requests which change the state of the server.

    \n

    Its inputs, outputs, and behavior are identical to the\n EXPath http-client's\n send-request() function (except that HTML responses are not tidied\n into XML - see the note above). It\n is provided here for use in Zorba installations that do not have\n the EXPath module available. If you have the option of using the\n EXPath module instead of this function, please do so, as it will\n allow your application to be more interoperable between different\n XQuery engines.

    \n

    Full documentation of the $request parameter can be found in\n the EXPath\n specification.

    \n", "summary" : "

    This function sends an HTTP request and returns the corresponding response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "request", "type" : "element(*)", "occurrence" : "?", "description" : "
    Contains the various parameters of the request (see above).
    " }, { "name" : "href", "type" : "xs:string", "occurrence" : "?", "description" : "
    The URL to which the request will be made (see note above). If this parameter is specified, it will override the \"href\" attribute of $request.
    " }, { "name" : "bodies", "type" : "item()", "occurrence" : "*", "description" : "
    is the request body content, for HTTP methods that can contain a body in the request (i.e. POST and PUT). It is an error if this param is not the empty sequence for methods
    " } ], "returns" : { "type" : "item()+", "description" : "standard http-client return type." }, "errors" : [ "error:HC001 An HTTP error occurred.", "error:HC002 Error parsing the response content as XML.", "error:HC003 With a multipart response, the override-media-type must be either a multipart media type or application/octet-stream.", "error:HC004 The src attribute on the body element is mutually exclusive with all other attribute (except the media-type).", "error:HC005 The input request element is not valid.", "error:HC006 A timeout occurred waiting for the response.", "error:HCV02 Trying to follow a redirect of a POST, PUT, or DELETE request" ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/cloudsearch" : { "ns" : "http://www.28msec.com/modules/cloudsearch", "description" : "

    This module offers functionality to search, add, update and remove documents in\n an Amazon CloudSearch domain.

    \n

    For each functionality two methods are provided\n

      \n
    • one which accepts a single $options parameter. In this case the default\n credentials for the \"CloudSearch\" category will be used to determine the\n CloudSearch endpoint to use.
    • \n
    • one which accepts both an $endpoint and an $options parameter.\n In this case, if the $endpoint parameter is of type string, it will be\n interpreted as the name of a credentials in the \"CloudSearch\" category.\n Otherwise, if the $endpoint parameter is of type anyURI, it will be\n interpreted as the endpoint URI.
    • \n
    \n

    \n

    Important Notice Regarding Function Determinism

    \n

    The search functions (search#1 and\n search#2) are declared deterministic, which means that\n their results could be cached when invoked multiple times with the same arguments\n in the same query execution.

    \n

    To not use cached results you can use two alternative search functions\n (search-nondeterministic#1 and\n search-nondeterministic#2), which have\n been declared as being non deterministic.

    \n

    Search options

    \n

    The search settings are specified by means of an object whose form\n is described in the following. The two most important fields are the\n \"q\" and \"bq\" fields. At least one of them must be specified. If the \"bq\"\n field is specified in conjunction with the \"q\" parameter, the values\n are joined with a top-level AND.\n

      \n
    • bq: one or more match expressions that define a Boolean search. Multiple\n expressions are joined with a top-level AND.\n

      Type: string

      \n
    • \n
    • q: the string to search for. You use the q parameter to perform simple text\n searches. This searches the default search field for the specified text.\n

      Type: string

      \n
    • \n
    \n

    \n

    Additional documentation on the format of the query and boolean query strings can\n be found at:\n \n Expression Syntax for Boolean Queries.

    \n

    The following additional optional parameters can be specified.\n

      \n
    • facet: a comma-separated list of the fields for which you want to compute facets.\n The specified fields must be numeric fields or defined as facet enabled in the\n domain configuration.\n

      Type: string

      \n
    • \n
    • facet-FIELD-constraints: the field values (facet constraints) that\n you want to count for a particular field. FIELD is the name of the field.\n Constraints are specified as a comma-separated list of ranges or\n single-quoted strings. If you don't specify facet constraints, counts\n are computed for all field values.\n

      Type: string

      \n
    • \n
    • facet-FIELD-sort: how you want to sort facet values for a\n particular field. FIELD is the name of the field. There are four sorting options:\n
        \n
      • alpha: Sort the facet values alphabetically (in ascending order).
      • \n
      • count: Sort the facet values by their counts (in descending order).
      • \n
      • max: Sort the facet values according to the maximum values in the specified\n field. This option is specified as max(FIELD). By default, the\n facet values are sorted in ascending order. To sort in descending order,\n prefix the sort option with - (minus): -max(FIELD).\n
      • \n
      • sum: Sort the facet values according to the sum of the values in the\n specified field (in ascending order). This option is specified as\n sum(FIELD).\n
      • \n
      \n
    • \n
    • facet-FIELD-top-n: set the maximum number of facet constraints to\n be included for the specified field in the search results. By default,\n the results include counts for the top 40 constraints.\n

      Type: integer

      \n
    • \n
    • no-cache: if false, a cached result can be returned. If true, a revalidation of the\n results is forced. Default is false.\n

      Type: boolean

      \n
    • \n
    • rank: a comma-separated list of fields or rank expressions to use for ranking. A\n maximum of 10 fields and rank expressions can be specified. You can use any uint\n field to rank results numerically. Any result-enabled text or literal field can be\n used to rank results alphabetically. To rank results by relevance, you can specify\n the name of a custom rank expression or text_relevance. Hits are ordered according\n to the specified rank field(s). By default, hits are ranked in ascending order.\n

      You can prefix a field name with a minus (-) to rank in descending order. If no\n rank parameter is specified, it defaults to rank=-text_relevance, which\n lists results according to their text_relevance scores with the highest-scoring\n documents first.

      \n

      Type: string

      \n
    • \n
    • rank-RANKNAME: define a rank expression that can be used with the\n rank parameter. You can also specify the new rank expression as a return\n field and use it to set thresholds for the search results with the\n t-FIELD parameter. For more information about constructing\n rank expressions, see\n \n Customizing Result Ranking with Amazon CloudSearch.\n

      Type: string

      \n
    • \n
    • return-fields: the document fields to include in the response. Up to 2 KB\n of data can be returned from a text field. If the field contents exceed\n 2 KB, only the first 2 KB is included in the results. Specified as a\n comma-separated list of field names. If no return-fields are specified,\n only the document ids of the hits are returned.\n

      Type: string

      \n
    • \n
    • size: the maximum number of search hits to return. The default is 10.\n

      Type: integer

      \n
    • \n
    • start: the offset of the first search hit you want to return. The default is 0\n (the first hit).\n

      Type: integer

      \n
    • \n
    • t-FIELD: restrict the match set used in subsequent post-processing\n steps according to the specified rank expression. Only hits that have a\n score within the specified range are included. Ranges are specified as\n described in\n \n Expression Syntax for Boolean Queries.\n

      Type: integer

      \n
    • \n
    \n For additional details on the search parameters you can refer to the\n \n Amazon CloudSearch search requests documentation.

    \n

    Search Results

    \n

    The format of the returned object is the following:\n

    \n {\n   \"rank\" : \"-text_relevance\",\n   \"match-expr\" : \"(label 'star wars')\",\n   \"hits\" :\n   {\n     \"found\" : 2,\n     \"start\" : 0,\n     \"hit\" :\n     [\n       {\n         \"id\" : \"tt1185834\",\n         \"data\" :\n         {\n           \"actor\" : [\"Abercrombie, Ian\",\"Baker, Dee\",\"Burton, Corey\"],\n           \"title\" : [\"Star Wars: The Clone Wars\"]\n         }\n       },\n       {\n         \"id\" :\"tt0121766\",\n         \"data\" :\n         {\n           \"actor\" : [\"Bai, Ling\",\"Bryant, Gene\",\"Castle-Hughes, Keisha\"],\n           \"title\" : [\"Star Wars: Episode III - Revenge of the Sith\"]\n         }\n       }\n     ]\n   },\n   \"info\" :\n   {\n     \"rid\" : \"b7c167f6c2da6d93531b9a7b314ad030b3a74803b4b7797edb905ba5a6a08\",\n     \"time-ms\" : 2,\n     \"cpu-time-ms\" : 0\n   }\n }\n 
    \n

    \n

    The returned object fields have the following meaning:\n

      \n
    • match-expr: Shows the match expression constructed from the search\n parameters.
    • \n
    • hits: Contains hit statistics (found, start) and a hit array that lists\n the document ids and data for each hit.
    • \n
    • found: The total number of hits that match the search request after\n Amazon CloudSearch finished processing the match set.
    • \n
    • start: The index of the first hit returned in this response.
    • \n
    • hit: An array that lists the document ids and data for each hit.
    • \n
    • id: The unique identifier for a document.
    • \n
    • data: A list of returned fields.
    • \n
    • facets: Contains facet information and facet counts.
    • \n
    • FacetFieldName: A field for which facets were calculated.
    • \n
    • constraints: An array of the facet values and counts.
    • \n
    • value: The facet value being counted.
    • \n
    • count: The number of hits that contain the facet value in FacetFieldName.\n
    • \n
    • info: Contains information about the request processing.
    • \n
    • rank: Lists the fields that were used to rank the search hits.
    • \n
    • rid: The encrypted Resource ID.
    • \n
    • time-ms: How long it took to process the search request in milliseconds.\n
    • \n
    • cpu-time-ms: The CPU time required to process the search request in\n milliseconds.
    • \n
    • messages: Contains any error messages returned by the search service.\n The severity, code, and message properties are included for each item.
    • \n
    • severity: The severity of the message. It is always warning, which indicates\n a problem with the query string that did not prevent the request from being\n processed.
    • \n
    • code: The error code. The search service returns the following error codes:\n
        \n
      • CS-InvalidFieldOrRankAliasInRankParameter: the specified ranking field\n could not be found.
      • \n
      • CS-RankExpressionParseError: one of the specified rank expressions could\n not be parsed. No query-time rank expressions will be used.
      • \n
      • CS-RankExpressionValidationError: one of the specified rank expressions\n could not be validated. No query-time rank expressions will be used.
      • \n
      • CS-UndefinedField: an unknown field was specified in the match\n expression.
      • \n
      • CS-UnknownFieldInMatchExpression: a field specified in the bq parameter\n could not be found.
      • \n
      • CS-WildcardTermLimit: more than 2000 terms matched the wildcard in the\n search request. The number of terms matched was limited to 2000.
      • \n
      \n
    • \n
    • message: A description of the error that was returned by the search service.
    • \n
    \n

    \n", "sees" : [ ], "authors" : [ "Federico Cavalieri" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/cloudsearch", "prefix" : "cloudsearch" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://zorba.io/modules/http-client", "prefix" : "http" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "add-document", "qname" : "cloudsearch:add-document", "signature" : "($options as object()) as object()", "description" : "

    Adds or replaces a document in the default Amazon CloudSearch domain.

    \n

    An add operation is applied only if a document with the same id is not\n present or if the version number specified in the operation is greater than\n the existing document's version number.

    \n

    The document to add or replace is specified through an object with\n the following form:\n

    \n {\n   \"id\" : \"tt0484562\",\n   \"version\" : 1,\n   \"lang\" : \"en\",\n   \"fields\" :\n   {\n     \"title\" : \"The Seeker: The Dark Is Rising\",\n     \"genre\" : [\"Adventure\",\"Drama\",\"Fantasy\",\"Thriller\"]\n   }\n }\n 
    \n

    \n

    Specifically, the fields in the request object have the following meaning:\n

      \n
    • id: An alphanumeric string. Allowed characters are: a-z, 0-9, and _.\n Document IDs cannot begin with an underscore. The max length is 128\n characters.
    • \n
    • version: Any non-negative number less than 2^32.
    • \n
    • lang: An ISO-639-1 two-letter language code.
    • \n
    • fields: An object containing one or more fields. Each field specifies\n a field within the document being added. Field names must begin with a\n lowercase letter and can contain the following characters: a-z, 0-9,\n and _. Field names must be at least 3 and no more than 64 characters.\n The names \"body\", \"docid\", and \"text_relevance\" are reserved names and\n cannot be used as field names. To specify multiple values for a field,\n you can specify an array of values instead of a single value.
    • \n
    \n

    \n

    The returned object lists all warnings that were generated.\n

    \n {\n   \"status\" : \"success\",\n   \"warning\" :\n   [\n     {\"message\" : \"Warning message.\"}\n   ]\n }\n 
    \n

    \n

    Specifically, the fields in the response object have the following meaning:\n

      \n
    • status: the result status, always \"success\". In case an error occurred\n processing the request, an error is raised.
    • \n
    • warning: provides information about warnings generated during parsing\n or validation. The field is not present if no warning were generated.
    • \n
    \n

    \n

    Example, specifying endpoint URI:\n

    \n cloudsearch:add-document(\n anyURI(\"http://doc-movies-h2pc7ftfnsdlqh6pqqawbftrhu.us-east-1.cloudsearch.amazonaws.com\"),\n {\n   \"id\" : \"tt0484562\",\n   \"version\" : 1,\n   \"lang\" : \"en\",\n   \"fields\" :\n   {\n     \"title\" : \"The Seeker: The Dark Is Rising\",\n     \"genre\" : [\"Adventure\",\"Drama\",\"Fantasy\",\"Thriller\"]\n   }\n });\n 
    \n

    \n

    Example, using stored credentials:\n

    \n cloudsearch:add-document(\"movies\",\n {\n   \"id\" : \"tt0484562\",\n   \"version\" : 1,\n   \"lang\" : \"en\",\n   \"fields\" :\n   {\n     \"title\" : \"The Seeker: The Dark Is Rising\",\n     \"genre\" : [\"Adventure\",\"Drama\",\"Fantasy\",\"Thriller\"]\n   }\n });\n 
    \n

    \n", "summary" : "

    Adds or replaces a document in the default Amazon CloudSearch domain.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying the request options
    " } ], "returns" : { "type" : "object()", "description" : "The request response" }, "errors" : [ "cloudsearch:ENDPOINT if the default credentials endpoint is invalid or not present", "cloudsearch:AUTHORIZATION if the request was unauthorized", "cloudsearch:HTTP if an HTTP error has occurred", "cloudsearch:REQUEST if the request is malformed", "cloudsearch:RESOURCES if the server storage or bandwidth resources are insufficient to execute the request", "cloudsearch:INTERNAL if an internal server error occurred", "cloudsearch:RESPONSE if the CloudSearch response cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "add-document", "qname" : "cloudsearch:add-document", "signature" : "($endpoint as atomic, $options as object()) as object()", "description" : "

    Adds or replaces a document in the specified Amazon CloudSearch domain.

    \n

    An add operation is applied only if a document with the same id is not\n present or if the version number specified in the operation is greater than\n the existing document's version number.

    \n

    The document to add or replace is specified through an object with\n the following form:\n

    \n {\n   \"id\" : \"tt0484562\",\n   \"version\" : 1,\n   \"lang\" : \"en\",\n   \"fields\" :\n   {\n     \"title\" : \"The Seeker: The Dark Is Rising\",\n     \"genre\" : [\"Adventure\",\"Drama\",\"Fantasy\",\"Thriller\"]\n   }\n }\n 
    \n

    \n

    Specifically, the fields in the request object have the following meaning:\n

      \n
    • id: An alphanumeric string. Allowed characters are: a-z, 0-9, and _.\n Document IDs cannot begin with an underscore. The max length is 128\n characters.
    • \n
    • version: Any non-negative number less than 2^32.
    • \n
    • lang: An ISO-639-1 two-letter language code.
    • \n
    • fields: An object containing one or more fields. Each field specifies\n a field within the document being added. Field names must begin with a\n lowercase letter and can contain the following characters: a-z, 0-9,\n and _. Field names must be at least 3 and no more than 64 characters.\n The names \"body\", \"docid\", and \"text_relevance\" are reserved names and\n cannot be used as field names. To specify multiple values for a field,\n you can specify an array of values instead of a single value.
    • \n
    \n

    \n

    The returned object lists all warnings that were generated.\n

    \n {\n   \"status\" : \"success\",\n   \"warning\" :\n   [\n     {\"message\" : \"Warning message.\"}\n   ]\n }\n 
    \n

    \n

    Specifically, the fields in the response object have the following meaning:\n

      \n
    • status: the result status, always \"success\". In case an error occurred\n processing the request, an error is raised.
    • \n
    • warning: provides information about warnings generated during parsing\n or validation. The field is not present if no warning were generated.
    • \n
    \n

    \n

    Example, specifying endpoint URI:\n

    \n cloudsearch:add-document(\n anyURI(\"http://doc-movies-h2pc7ftfnsdlqh6pqqawbftrhu.us-east-1.cloudsearch.amazonaws.com\"),\n {\n   \"id\" : \"tt0484562\",\n   \"version\" : 1,\n   \"lang\" : \"en\",\n   \"fields\" :\n   {\n     \"title\" : \"The Seeker: The Dark Is Rising\",\n     \"genre\" : [\"Adventure\",\"Drama\",\"Fantasy\",\"Thriller\"]\n   }\n });\n 
    \n

    \n

    Example, using stored credentials:\n

    \n cloudsearch:add-document(\"movies\",\n {\n   \"id\" : \"tt0484562\",\n   \"version\" : 1,\n   \"lang\" : \"en\",\n   \"fields\" :\n   {\n     \"title\" : \"The Seeker: The Dark Is Rising\",\n     \"genre\" : [\"Adventure\",\"Drama\",\"Fantasy\",\"Thriller\"]\n   }\n });\n 
    \n

    \n", "summary" : "

    Adds or replaces a document in the specified Amazon CloudSearch domain.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint", "type" : "atomic", "occurrence" : null, "description" : "
    The endpoint URI or the name of a stored CloudSearch credentials
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying the request options
    " } ], "returns" : { "type" : "object()", "description" : "The request response" }, "errors" : [ "cloudsearch:ENDPOINT if the specified endpoint is invalid", "cloudsearch:AUTHORIZATION if the request was unauthorized", "cloudsearch:HTTP if an HTTP error has occurred", "cloudsearch:REQUEST if the request is malformed", "cloudsearch:RESOURCES if the server storage or bandwidth resources are insufficient to execute the request", "cloudsearch:INTERNAL if an internal server error occurred", "cloudsearch:RESPONSE if the CloudSearch response cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "batch-document", "qname" : "cloudsearch:batch-document", "signature" : "($options as array()) as object()", "description" : "

    Adds, replaces or removes one or more documents from the default Amazon\n CloudSearch domain.

    \n

    An add or delete operation is only applied to an existing document if the\n version number specified in the operation is greater than the existing document\n version number.\n If multiple add or delete operations for the same document are specified, the\n operation with the highest version number is applied. If multiple operations in\n a batch specify the same document and version number, the document service\n arbitrarily picks which one to apply.

    \n

    The documents to add, replace or delete can be specified through an array with\n the following form:\n

    \n [\n   {\n     \"type\" : \"add\",\n     \"id\" :   \"tt0484562\",\n     \"version\" : 1,\n     \"lang\" : \"en\",\n     \"fields\" :\n     {\n       \"title\" : \"The Seeker: The Dark Is Rising\",\n       \"genre\" : [\"Adventure\",\"Drama\",\"Fantasy\",\"Thriller\"],\n     }\n   },\n   {\n     \"type\" : \"delete\",\n     \"id\" :   \"tt0484575\",\n     \"version\" : 2\n   }\n ]\n 
    \n

    \n

    Specifically, the fields in the request array have the following meaning:\n

      \n
    • type: The operation type, \"add\" or \"delete\".
    • \n
    • id: An alphanumeric string. Allowed characters are: a-z, 0-9, and _.\n Document IDs cannot begin with an underscore. The max length is 128\n characters.
    • \n
    • version: Any non-negative number less than 2^32.
    • \n
    • lang: An ISO-639-1 two-letter language code.
    • \n
    • fields: An object containing one or more fields. Each field specifies\n a field within the document being added. Field names must begin with a\n lowercase letter and can contain the following characters: a-z, 0-9,\n and _. Field names must be at least 3 and no more than 64 characters.\n The names \"body\", \"docid\", and \"text_relevance\" are reserved names and\n cannot be used as field names. To specify multiple values for a field,\n you can specify an array of values instead of a single value.
    • \n
    \n

    \n

    The response body lists any warning that was generated.\n

    \n {\n   \"status\" : \"success\",\n   \"adds\" : 1,\n   \"deletes: 1,\n   \"warning\" :\n   [\n     {\"message\" : \"Warning message.\"}\n   ]\n }\n 
    \n

    \n

    Specifically, the fields in the response object have the following meaning:\n

      \n
    • status: the result status, which is either success or error.
    • \n
    • adds: the number of add document operations that were performed.
    • \n
    • deletes: the number of delete document operations that were performed.
    • \n
    • warning: provides information about a warning generated during parsing\n or validation. The field is not present if no warning was generated.
    • \n
    \n

    \n

    Example, using specified endpoint URI:\n

    \n cloudsearch:batch-document(\n anyURI(\"http://doc-movies-h2pc7ftfnsdlqh6pqqawbftrhu.us-east-1.cloudsearch.amazonaws.com\"),\n [\n   {\n     \"type\" : \"add\",\n     \"id\" :   \"tt0484562\",\n     \"version\" : 1,\n     \"lang\" : \"en\",\n     \"fields\" :\n     {\n       \"title\" : \"The Seeker: The Dark Is Rising\",\n       \"genre\" : [\"Adventure\",\"Drama\",\"Fantasy\",\"Thriller\"],\n     }\n   },\n   {\n     \"type\" : \"delete\",\n     \"id\" :   \"tt0484575\",\n     \"version\" : 2\n   }\n ]);\n 
    \n

    \n

    Example, using specified endpoint URI:\n

    \n cloudsearch:batch-document(\"movies\",\n [\n   {\n     \"type\" : \"add\",\n     \"id\" :   \"tt0484562\",\n     \"version\" : 1,\n     \"lang\" : \"en\",\n     \"fields\" :\n     {\n       \"title\" : \"The Seeker: The Dark Is Rising\",\n       \"genre\" : [\"Adventure\",\"Drama\",\"Fantasy\",\"Thriller\"],\n     }\n   },\n   {\n     \"type\" : \"delete\",\n     \"id\" :   \"tt0484575\",\n     \"version\" : 2\n   }\n ]);\n 
    \n

    \n", "summary" : "

    Adds, replaces or removes one or more documents from the default Amazon\n CloudSearch domain.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "options", "type" : "array()", "occurrence" : null, "description" : "
    An object specifying the request options
    " } ], "returns" : { "type" : "object()", "description" : "The request response" }, "errors" : [ "cloudsearch:ENDPOINT if the default credentials endpoint is invalid or not present", "cloudsearch:AUTHORIZATION if the request was unauthorized", "cloudsearch:HTTP if an HTTP error has occurred", "cloudsearch:REQUEST if the request is malformed", "cloudsearch:RESOURCES if the server storage or bandwidth resources are insufficient to execute the request", "cloudsearch:INTERNAL if an internal server error occurred", "cloudsearch:RESPONSE if the CloudSearch response cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "batch-document", "qname" : "cloudsearch:batch-document", "signature" : "($endpoint as atomic, $options as array()) as object()", "description" : "

    Adds, replaces or removes one or more documents from the specified Amazon\n CloudSearch domain.

    \n

    An add or delete operation is only applied to an existing document if the\n version number specified in the operation is greater than the existing document\n version number.\n If multiple add or delete operations for the same document are specified, the\n operation with the highest version number is applied. If multiple operations in\n a batch specify the same document and version number, the document service\n arbitrarily picks which one to apply.

    \n

    The documents to add, replace or delete can be specified through an array with\n the following form:\n

    \n [\n   {\n     \"type\" : \"add\",\n     \"id\" :   \"tt0484562\",\n     \"version\" : 1,\n     \"lang\" : \"en\",\n     \"fields\" :\n     {\n       \"title\" : \"The Seeker: The Dark Is Rising\",\n       \"genre\" : [\"Adventure\",\"Drama\",\"Fantasy\",\"Thriller\"],\n     }\n   },\n   {\n     \"type\" : \"delete\",\n     \"id\" :   \"tt0484575\",\n     \"version\" : 2\n   }\n ]\n 
    \n

    \n

    Specifically, the fields in the request array have the following meaning:\n

      \n
    • type: The operation type, \"add\" or \"delete\".
    • \n
    • id: An alphanumeric string. Allowed characters are: a-z, 0-9, and _.\n Document IDs cannot begin with an underscore. The max length is 128\n characters.
    • \n
    • version: Any non-negative number less than 2^32.
    • \n
    • lang: An ISO-639-1 two-letter language code.
    • \n
    • fields: An object containing one or more fields. Each field specifies\n a field within the document being added. Field names must begin with a\n lowercase letter and can contain the following characters: a-z, 0-9,\n and _. Field names must be at least 3 and no more than 64 characters.\n The names \"body\", \"docid\", and \"text_relevance\" are reserved names and\n cannot be used as field names. To specify multiple values for a field,\n you can specify an array of values instead of a single value.
    • \n
    \n

    \n

    The response body lists any warning that was generated.\n

    \n {\n   \"status\" : \"success\",\n   \"adds\" : 1,\n   \"deletes: 1,\n   \"warning\" :\n   [\n     {\"message\" : \"Warning message.\"}\n   ]\n }\n 
    \n

    \n

    Specifically, the fields in the response object have the following meaning:\n

      \n
    • status: the result status, which is either success or error.
    • \n
    • adds: the number of add document operations that were performed.
    • \n
    • deletes: the number of delete document operations that were performed.
    • \n
    • warning: provides information about a warning generated during parsing\n or validation. The field is not present if no warning was generated.
    • \n
    \n

    \n

    Example, using specified endpoint URI:\n

    \n cloudsearch:batch-document(\n anyURI(\"http://doc-movies-h2pc7ftfnsdlqh6pqqawbftrhu.us-east-1.cloudsearch.amazonaws.com\"),\n [\n   {\n     \"type\" : \"add\",\n     \"id\" :   \"tt0484562\",\n     \"version\" : 1,\n     \"lang\" : \"en\",\n     \"fields\" :\n     {\n       \"title\" : \"The Seeker: The Dark Is Rising\",\n       \"genre\" : [\"Adventure\",\"Drama\",\"Fantasy\",\"Thriller\"],\n     }\n   },\n   {\n     \"type\" : \"delete\",\n     \"id\" :   \"tt0484575\",\n     \"version\" : 2\n   }\n ]);\n 
    \n

    \n

    Example, using specified endpoint URI:\n

    \n cloudsearch:batch-document(\"movies\",\n [\n   {\n     \"type\" : \"add\",\n     \"id\" :   \"tt0484562\",\n     \"version\" : 1,\n     \"lang\" : \"en\",\n     \"fields\" :\n     {\n       \"title\" : \"The Seeker: The Dark Is Rising\",\n       \"genre\" : [\"Adventure\",\"Drama\",\"Fantasy\",\"Thriller\"],\n     }\n   },\n   {\n     \"type\" : \"delete\",\n     \"id\" :   \"tt0484575\",\n     \"version\" : 2\n   }\n ]);\n 
    \n

    \n", "summary" : "

    Adds, replaces or removes one or more documents from the specified Amazon\n CloudSearch domain.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint", "type" : "atomic", "occurrence" : null, "description" : "
    The endpoint URI or the name of a stored CloudSearch credentials
    " }, { "name" : "options", "type" : "array()", "occurrence" : null, "description" : "
    An object specifying the request options
    " } ], "returns" : { "type" : "object()", "description" : "The request response" }, "errors" : [ "cloudsearch:ENDPOINT if the specified endpoint is invalid", "cloudsearch:AUTHORIZATION if the request was unauthorized", "cloudsearch:HTTP if an HTTP error has occurred", "cloudsearch:REQUEST if the request is malformed", "cloudsearch:RESOURCES if the server storage or bandwidth resources are insufficient to execute the request", "cloudsearch:INTERNAL if an internal server error occurred", "cloudsearch:RESPONSE if the CloudSearch response cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "delete-document", "qname" : "cloudsearch:delete-document", "signature" : "($options as object()) as object()", "description" : "

    Deletes a document from the default Amazon CloudSearch domain.

    \n

    A delete operation is only applied to an existing document if the\n version number specified in the operation is greater than the existing\n document's version number.

    \n

    The document to remove is specified through an object with the\n following form:\n

    \n {\n   \"id\" : \"tt0484562\",\n   \"version\" : 2\n }\n 
    \n

    \n

    Specifically, the fields in the request object have the following meaning:\n

      \n
    • id: An alphanumeric string. Allowed characters are: a-z, 0-9, and _.\n Document IDs cannot begin with an underscore. The max length is 128\n characters.
    • \n
    • version: Any non-negative number less than 2^32.
    • \n
    \n

    \n

    The response body lists any warning that was generated.\n

    \n {\n   \"status\" : \"success\",\n   \"warning\" :\n   [\n     {\"message\" : \"Warning message.\"}\n   ]\n }\n 
    \n

    \n

    Specifically, the fields in the response object have the following meaning:\n

      \n
    • status: the result status, always \"success\". In case of errors an error is\n raised.
    • \n
    • warning: provides information about a warning generated during parsing or\n validation. The field is not present if no warning was generated.
    • \n
    \n

    \n

    Example, using specified endpoint URI:\n

    \n cloudsearch:delete-document(\n anyURI(\"http://doc-movies-h2pc7ftfnsdlqh6pqqawbftrhu.us-east-1.cloudsearch.amazonaws.com\"),\n {\n   \"id\" : \"tt0484562\",\n   \"version\" : 2\n });\n 
    \n

    \n

    Example, using specified stored endpoing:\n

    \n cloudsearch:delete-document(\"movies\",\n {\n   \"id\" : \"tt0484562\",\n   \"version\" : 2\n });\n 
    \n

    \n", "summary" : "

    Deletes a document from the default Amazon CloudSearch domain.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying the request options
    " } ], "returns" : { "type" : "object()", "description" : "The request response" }, "errors" : [ "cloudsearch:ENDPOINT if the default credentials endpoint is invalid or not present", "cloudsearch:AUTHORIZATION if the request was unauthorized", "cloudsearch:HTTP if an HTTP error has occurred", "cloudsearch:REQUEST if the request is malformed", "cloudsearch:RESOURCES if the server storage or bandwidth resources are insufficient to execute the request", "cloudsearch:INTERNAL if an internal server error occurred", "cloudsearch:RESPONSE if the CloudSearch response cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "delete-document", "qname" : "cloudsearch:delete-document", "signature" : "($endpoint as atomic, $options as object()) as object()", "description" : "

    Deletes a document from the specified Amazon CloudSearch domain.

    \n

    A delete operation is only applied to an existing document if the\n version number specified in the operation is greater than the existing\n document's version number.

    \n

    The document to remove is specified through an object with the\n following form:\n

    \n {\n   \"id\" : \"tt0484562\",\n   \"version\" : 2\n }\n 
    \n

    \n

    Specifically, the fields in the request object have the following meaning:\n

      \n
    • id: An alphanumeric string. Allowed characters are: a-z, 0-9, and _.\n Document IDs cannot begin with an underscore. The max length is 128\n characters.
    • \n
    • version: Any non-negative number less than 2^32.
    • \n
    \n

    \n

    The response body lists any warning that was generated.\n

    \n {\n   \"status\" : \"success\",\n   \"warning\" :\n   [\n     {\"message\" : \"Warning message.\"}\n   ]\n }\n 
    \n

    \n

    Specifically, the fields in the response object have the following meaning:\n

      \n
    • status: the result status, always \"success\". In case of errors an error is\n raised.
    • \n
    • warning: provides information about a warning generated during parsing or\n validation. The field is not present if no warning was generated.
    • \n
    \n

    \n

    Example, using specified endpoint URI:\n

    \n cloudsearch:delete-document(\n anyURI(\"http://doc-movies-h2pc7ftfnsdlqh6pqqawbftrhu.us-east-1.cloudsearch.amazonaws.com\"),\n {\n   \"id\" : \"tt0484562\",\n   \"version\" : 2\n });\n 
    \n

    \n

    Example, using specified stored endpoing:\n

    \n cloudsearch:delete-document(\"movies\",\n {\n   \"id\" : \"tt0484562\",\n   \"version\" : 2\n });\n 
    \n

    \n", "summary" : "

    Deletes a document from the specified Amazon CloudSearch domain.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint", "type" : "atomic", "occurrence" : null, "description" : "
    The endpoint URI or the name of a stored CloudSearch credentials
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying the request options
    " } ], "returns" : { "type" : "object()", "description" : "The request response" }, "errors" : [ "cloudsearch:ENDPOINT if the specified endpoint is invalid", "cloudsearch:AUTHORIZATION if the request was unauthorized", "cloudsearch:HTTP if an HTTP error has occurred", "cloudsearch:REQUEST if the request is malformed", "cloudsearch:RESOURCES if the server storage or bandwidth resources are insufficient to execute the request", "cloudsearch:INTERNAL if an internal server error occurred", "cloudsearch:RESPONSE if the CloudSearch response cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "search-nondeterministic", "qname" : "cloudsearch:search-nondeterministic", "signature" : "($options as object()) as object()", "description" : "

    Searches the documents in the default Amazon CloudSearch domain.

    \n

    This function has the same semantics as search#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Searches the documents in the default Amazon CloudSearch domain.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    The search options object
    " } ], "returns" : { "type" : "object()", "description" : "The search results object" }, "errors" : [ "cloudsearch:ENDPOINT if the default credentials endpoint is invalid or not present", "cloudsearch:AUTHORIZATION if the request was unauthorized", "cloudsearch:HTTP if an HTTP error has occurred", "cloudsearch:REQUEST if the request is malformed", "cloudsearch:INTERNAL if an internal server error occurred", "cloudsearch:RESPONSE if the CloudSearch response cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "search-nondeterministic", "qname" : "cloudsearch:search-nondeterministic", "signature" : "($endpoint as atomic, $options as object()) as object()", "description" : "

    Searches the documents in the specified Amazon CloudSearch domain.

    \n

    This function has the same semantics as search#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Searches the documents in the specified Amazon CloudSearch domain.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "endpoint", "type" : "atomic", "occurrence" : null, "description" : "
    The endpoint URI or the name of a stored CloudSearch credentials
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    The search options object
    " } ], "returns" : { "type" : "object()", "description" : "The search results object" }, "errors" : [ "cloudsearch:ENDPOINT if the specified endpoint is invalid", "cloudsearch:AUTHORIZATION if the request was unauthorized", "cloudsearch:HTTP if an HTTP error has occurred", "cloudsearch:REQUEST if the request is malformed", "cloudsearch:INTERNAL if an internal server error occurred", "cloudsearch:RESPONSE if the CloudSearch response cannot be parsed" ] }, { "isDocumented" : true, "arity" : 1, "name" : "search", "qname" : "cloudsearch:search", "signature" : "($options as object()) as object()", "description" : "

    Searches the documents in the default Amazon CloudSearch domain.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The format of the search options object and\n of the search results object is documented in\n the module introduction.

    \n

    Example:\n

    \n cloudsearch:search({\"q\" : \"star+wars\", \"return-fields\" : \"title\"})\n 
    \n

    \n

    Example returned object:\n

    \n {\n   \"rank\" : \"-text_relevance\",\n   \"match-expr\" : \"(label 'star wars')\",\n   \"hits\" :\n   {\n     \"found\" : 2,\n     \"start\" : 0,\n     \"hit\" :\n     [\n       {\n         \"id\" : \"tt1185834\",\n         \"data\" :\n         {\n           \"actor\" : [\"Abercrombie, Ian\",\"Baker, Dee\",\"Burton, Corey\"],\n           \"title\" : [\"Star Wars: The Clone Wars\"]\n         }\n       },\n       {\n         \"id\" :\"tt0121766\",\n         \"data\" :\n         {\n           \"actor\" : [\"Bai, Ling\",\"Bryant, Gene\",\"Castle-Hughes, Keisha\"],\n           \"title\" : [\"Star Wars: Episode III - Revenge of the Sith\"]\n         }\n       }\n     ]\n   },\n   \"info\" :\n   {\n     \"rid\" : \"b7c167f6c2da6d93531b9a7b314ad030b3a74803b4b7797edb905ba5a6a08\",\n     \"time-ms\" : 2,\n     \"cpu-time-ms\" : 0\n   }\n }\n 
    \n

    \n", "summary" : "

    Searches the documents in the default Amazon CloudSearch domain.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    The search options object
    " } ], "returns" : { "type" : "object()", "description" : "The search results object" }, "errors" : [ "cloudsearch:ENDPOINT if the default credentials endpoint is invalid or not present", "cloudsearch:AUTHORIZATION if the request was unauthorized", "cloudsearch:HTTP if an HTTP error has occurred", "cloudsearch:REQUEST if the request is malformed", "cloudsearch:INTERNAL if an internal server error occurred", "cloudsearch:RESPONSE if the CloudSearch response cannot be parsed" ] }, { "isDocumented" : true, "arity" : 2, "name" : "search", "qname" : "cloudsearch:search", "signature" : "($endpoint as atomic, $options as object()) as object()", "description" : "

    Searches the documents in the specified Amazon CloudSearch domain.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The format of the search options object and\n of the search results object is documented in\n the module introduction.

    \n

    The following examples performs a simple text search for all documents\n containing both the word \"star\" and \"trek\" and returns the matching document\n title field.

    \n

    Example, using specified endpoint URI:\n

    \n cloudsearch:search(\n anyURI(\"http://doc-movies-h2pc7ftfnsdlqh6pqqawbftrhu.us-east-1.cloudsearch.amazonaws.com\"),\n {\"q\" : \"star+wars\", \"return-fields\" : \"title\"})\n 
    \n

    \n

    Example, using a stored endpoint:\n

    \n cloudsearch:search(\"movies\",\n {\"q\" : \"star+wars\", \"return-fields\" : \"title\"})\n 
    \n

    \n", "summary" : "

    Searches the documents in the specified Amazon CloudSearch domain.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "endpoint", "type" : "atomic", "occurrence" : null, "description" : "
    The endpoint URI or the name of a stored CloudSearch credentials
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    The search options object
    " } ], "returns" : { "type" : "object()", "description" : "The search results object" }, "errors" : [ "cloudsearch:ENDPOINT if the specified endpoint is invalid", "cloudsearch:AUTHORIZATION if the request was unauthorized", "cloudsearch:HTTP if an HTTP error has occurred", "cloudsearch:REQUEST if the request is malformed", "cloudsearch:INTERNAL if an internal server error occurred", "cloudsearch:RESPONSE if the CloudSearch response cannot be parsed" ] } ], "variables" : [ ] }, "http://zorba.io/modules/store/static/indexes/ddl" : { "ns" : "http://zorba.io/modules/store/static/indexes/ddl", "description" : " This modules defines a set of functions for managing indexes that are\n declared in the prolog of a module.\n

    \n This module is part of\n Zorba's XQuery Data Definition Facility.\n All the indexes managed by this module have to be pre-declared in the prolog\n of a module.\n Please refer to the\n general documentation\n for more information and examples.\n", "sees" : [ "Data Lifecycle", "XQuery Data Definition Facility", "http://zorba.io/modules/store/static/indexes/dml", "http://zorba.io/modules/store/static/collections/dml", "http://zorba.io/modules/store/static/collections/ddl", "http://zorba.io/modules/store/static/integrity-constraints/ddl", "http://zorba.io/modules/store/static/integrity-constraints/dml", "http://zorba.io/errors" ], "authors" : [ "Nicolae Brinza, Matthias Brantner, David Graf, Till Westmann, Markos Zaharioudakis" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/store/static/indexes/ddl", "prefix" : "iddl" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "available-indexes", "qname" : "iddl:available-indexes", "signature" : "() as xs:QName* external", "description" : " Gets the available indexes.\n", "summary" : "

    Gets the available indexes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName*", "description" : "A sequence of QNames, one for each available index, or an empty sequence if none are." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "create", "qname" : "iddl:create", "signature" : "($name as xs:QName) external", "description" : " Creates an index.\n", "summary" : "

    Creates an index.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the index to create.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, creates the index with the given name." }, "errors" : [ "zerr:ZDDY0021 if $name is not equal to the name of any resource in the statically known indexes.", "zerr:ZDDY0022 if an index with $name already exists." ] }, { "isDocumented" : true, "arity" : 0, "name" : "declared-indexes", "qname" : "iddl:declared-indexes", "signature" : "() as xs:QName* external", "description" : " Gets a sequence of QNames representing the indexes that have been declared\n in the prolog of the static context.\n", "summary" : "

    Gets a sequence of QNames representing the indexes that have been declared\n in the prolog of the static context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName*", "description" : "A sequence of QNames, one for each created collection, or an emtpy sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "delete", "qname" : "iddl:delete", "signature" : "($name as xs:QName) external", "description" : " Deletes an index.\n", "summary" : "

    Deletes an index.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the index to delete.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, deletes the index with the given name." }, "errors" : [ "zerr:ZDDY0009 if the index does not exist." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-available-index", "qname" : "iddl:is-available-index", "signature" : "($name as xs:QName) as xs:boolean external", "description" : " Gets whether an index exists.\n", "summary" : "

    Gets whether an index exists.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the index that is being checked.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the index is available; false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-declared-index", "qname" : "iddl:is-declared-index", "signature" : "($name as xs:QName) as xs:boolean external", "description" : " Gets whether an index has been declared in the prolog of the static context.\n", "summary" : "

    Gets whether an index has been declared in the prolog of the static context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the index that is being checked.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the index was declared; false otherwise." }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/excel/datetime" : { "ns" : "http://zorba.io/modules/excel/datetime", "description" : " This is a library module offering the same set of functions\n defined by Microsoft Excel.\n", "sees" : [ "Excel Documentation: Datetime Functions" ], "authors" : [ "Sorin Nasoi" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/excel/datetime", "prefix" : "excel-datetime" }, { "uri" : "http://zorba.io/modules/excel/errors", "prefix" : "excel-err" }, { "uri" : "http://zorba.io/modules/excel/text", "prefix" : "excel-text" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 3, "name" : "date", "qname" : "excel-datetime:date", "signature" : "($year as xs:integer, $month as xs:integer, $day as xs:integer) as xs:date?", "description" : " Constructs a date given the hours, months and days.\n", "summary" : "

    Constructs a date given the hours, months and days.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "year", "type" : "xs:integer", "occurrence" : null, "description" : "
    the year
    " }, { "name" : "month", "type" : "xs:integer", "occurrence" : null, "description" : "
    the month
    " }, { "name" : "day", "type" : "xs:integer", "occurrence" : null, "description" : "
    the day
    " } ], "returns" : { "type" : "xs:date?", "description" : "A date given the hours, months and days" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "day", "qname" : "excel-datetime:day", "signature" : "($date as xs:date) as xs:integer?", "description" : " Returns the day of a $date, represented by a serial number.\n", "summary" : "

    Returns the day of a $date, represented by a serial number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:date", "occurrence" : null, "description" : "
    the date.
    " } ], "returns" : { "type" : "xs:integer?", "description" : "The day of a $date, represented by a serial number. The day is given as an integer ranging from 1 to 31." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "days360", "qname" : "excel-datetime:days360", "signature" : "($start_date as xs:date, $end_date as xs:date) as xs:integer", "description" : " Returns the number of days between two dates based on a 360-day year.\n", "summary" : "

    Returns the number of days between two dates based on a 360-day year.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "start_date", "type" : "xs:date", "occurrence" : null, "description" : "
    the start date.
    " }, { "name" : "end_date", "type" : "xs:date", "occurrence" : null, "description" : "
    the end date.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The number of days between two dates based on a 360-day year (twelve 30-day months), which is used in some accounting calculations.

    Use this function to help compute payments if your accounting system is based on twelve 30-day months.

    The metod used is U.S. (NASD). If the starting date is the last day of a month, it becomes equal to the 30th of the same month.

    If the ending date is the last day of a month and the starting date is earlier than the 30th of a month, the ending date becomes equal to the 1st of the next month; otherwise the ending date becomes equal to the 30th of the same month." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "days360", "qname" : "excel-datetime:days360", "signature" : "($start_date as xs:date, $end_date as xs:date, $method as xs:boolean) as xs:integer", "description" : " Returns the number of days between two dates based on a 360-day year.\n", "summary" : "

    Returns the number of days between two dates based on a 360-day year.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "start_date", "type" : "xs:date", "occurrence" : null, "description" : "
    the start date.
    " }, { "name" : "end_date", "type" : "xs:date", "occurrence" : null, "description" : "
    the end date.
    " }, { "name" : "method", "type" : "xs:boolean", "occurrence" : null, "description" : "
    if false then US/NASD Method is used, otherwise the European Method is used.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The number of days between two dates based on a 360-day year (twelve 30-day months), which is used in some accounting calculations. Use this function to help compute payments if your accounting system is based on twelve 30-day months.

    The European Method (30E/360)

    - If either date A or B falls on the 31st of the month, that date will be changed to the 30th;

    - Where date B falls on the last day of February, the actual date B will be used.

    The US/NASD Method (30US/360)

    - If both date A and B fall on the last day of February, then date B will be changed to the 30th.

    - If date A falls on the 31st of a month or last day of February, then date A will be changed to the 30th.

    - If date A falls on the 30th of a month after applying (2) above and date B falls on the 31st of a month, then date B will be changed to the 30th." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "hour", "qname" : "excel-datetime:hour", "signature" : "($time as xs:time) as xs:integer?", "description" : " Returns the hour of a time value.\n", "summary" : "

    Returns the hour of a time value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "time", "type" : "xs:time", "occurrence" : null, "description" : "
    the time.
    " } ], "returns" : { "type" : "xs:integer?", "description" : "The hour of a time value. The hour is as an integer, ranging from 0 (12:00 A.M.) to 23 (11:00 P.M.)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "minute", "qname" : "excel-datetime:minute", "signature" : "($time as xs:time) as xs:integer?", "description" : " Returns the minutes of a time value.\n", "summary" : "

    Returns the minutes of a time value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "time", "type" : "xs:time", "occurrence" : null, "description" : "
    the time.
    " } ], "returns" : { "type" : "xs:integer?", "description" : "The minutes of a time value. The minute is given as an integer, ranging from 0 to 59." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "month", "qname" : "excel-datetime:month", "signature" : "($date as xs:date) as xs:integer?", "description" : " Returns the month of a $date.\n", "summary" : "

    Returns the month of a $date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:date", "occurrence" : null, "description" : "
    the date.
    " } ], "returns" : { "type" : "xs:integer?", "description" : "the month of a $date. The month is given as an integer, ranging from 1 (January) to 12 (December)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "networkdays", "qname" : "excel-datetime:networkdays", "signature" : "($start_date as xs:date, $end_date as xs:date) as xs:integer*", "description" : " Returns the number of whole working days between $start_date and $end_date.\n", "summary" : "

    Returns the number of whole working days between $start_date and $end_date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "start_date", "type" : "xs:date", "occurrence" : null, "description" : "
    the start date.
    " }, { "name" : "end_date", "type" : "xs:date", "occurrence" : null, "description" : "
    the end date.
    " } ], "returns" : { "type" : "xs:integer*", "description" : "The number of whole working days between start_date and end_date.

    Working days exclude weekends and any dates identified in holidays.

    Use NETWORKDAYS to calculate employee benefits that accrue based on the number of days worked during a specific term." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "networkdays", "qname" : "excel-datetime:networkdays", "signature" : "($start_date as xs:date, $end_date as xs:date, $holidays as xs:date*) as xs:integer*", "description" : " Returns the number of whole working days between $start_date and $end_date.\n", "summary" : "

    Returns the number of whole working days between $start_date and $end_date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "start_date", "type" : "xs:date", "occurrence" : null, "description" : "
    the start date.
    " }, { "name" : "end_date", "type" : "xs:date", "occurrence" : null, "description" : "
    the end date.
    " }, { "name" : "holidays", "type" : "xs:date", "occurrence" : "*", "description" : "
    one or more dates to exclude from the working calendar, such as state and federal holidays and floating holidays.
    " } ], "returns" : { "type" : "xs:integer*", "description" : "The number of whole working days between start_date and end_date.

    Working days exclude weekends and any dates identified in holidays.

    Use NETWORKDAYS to calculate employee benefits that accrue based on the number of days worked during a specific term." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "now", "qname" : "excel-datetime:now", "signature" : "() as xs:dateTime?", "description" : " Returns the current date and time.\n", "summary" : "

    Returns the current date and time.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:dateTime?", "description" : "The current date and time." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "second", "qname" : "excel-datetime:second", "signature" : "($time as xs:time) as xs:decimal?", "description" : " Returns the seconds of a $time value.\n", "summary" : "

    Returns the seconds of a $time value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "time", "type" : "xs:time", "occurrence" : null, "description" : "
    the time.
    " } ], "returns" : { "type" : "xs:decimal?", "description" : "The seconds of a $time value. The second is given as an integer in the range 0 (zero) to 59." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "time", "qname" : "excel-datetime:time", "signature" : "($hour as xs:integer, $minute as xs:integer, $second as xs:integer) as xs:time?", "description" : " Constructs a time given the hours, minutes and seconds.\n", "summary" : "

    Constructs a time given the hours, minutes and seconds.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "hour", "type" : "xs:integer", "occurrence" : null, "description" : "
    the hour.
    " }, { "name" : "minute", "type" : "xs:integer", "occurrence" : null, "description" : "
    the minute.
    " }, { "name" : "second", "type" : "xs:integer", "occurrence" : null, "description" : "
    the second.
    " } ], "returns" : { "type" : "xs:time?", "description" : "A time given the hours, minutes and seconds." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "today", "qname" : "excel-datetime:today", "signature" : "() as xs:date?", "description" : " Returns the current date.\n", "summary" : "

    Returns the current date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:date?", "description" : "The current date." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "weekday", "qname" : "excel-datetime:weekday", "signature" : "($date as xs:date) as xs:integer?", "description" : " Returns the day of the week corresponding to a $date.\n", "summary" : "

    Returns the day of the week corresponding to a $date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:date", "occurrence" : null, "description" : "
    the date.
    " } ], "returns" : { "type" : "xs:integer?", "description" : "The day of the week corresponding to a $date. The day is given as an integer, ranging from 1 (Sunday) to 7 (Saturday)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "weekday", "qname" : "excel-datetime:weekday", "signature" : "($date as xs:date, $return_type as xs:integer) as xs:integer?", "description" : " Returns the day of the week corresponding to a $date depending on $return_type.\n", "summary" : "

    Returns the day of the week corresponding to a $date depending on $return_type.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:date", "occurrence" : null, "description" : "
    the date.
    " }, { "name" : "return_type", "type" : "xs:integer", "occurrence" : null, "description" : "
    1 for Numbers 1 (Sunday) through 7 (Saturday). 2 for Numbers 1 (Monday) through 7 (Sunday). 3 for Numbers 0 (Monday) through 6 (Sunday).
    " } ], "returns" : { "type" : "xs:integer?", "description" : "The day of the week corresponding to a $date depending on $return_type." }, "errors" : [ "excel-err:Value if $return_type is outside the range [1,3]." ] }, { "isDocumented" : true, "arity" : 1, "name" : "year", "qname" : "excel-datetime:year", "signature" : "($date as xs:date) as xs:integer?", "description" : " Returns the year corresponding to a date.\n", "summary" : "

    Returns the year corresponding to a date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:date", "occurrence" : null, "description" : "
    the date.
    " } ], "returns" : { "type" : "xs:integer?", "description" : "The year corresponding to a date." }, "errors" : [ ] } ], "variables" : [ ] }, "http://xbrl.io/modules/bizql/profiles/sec/filings" : { "ns" : "http://xbrl.io/modules/bizql/profiles/sec/filings", "description" : "

    This module provides functionality for querying financial reports (filings)\n submitted to the SEC.

    \n

    SEC Filings are nothing else than XBRL archives. For XBRL-generic requests on archives,\n use the generic archives module.

    \n

    With this module, you can access a number of properties of an SEC filing, such as\n its document type. You can also retrieve an SEC filing given an SEC company (or its CIK).

    \n

    You can also access SEC filings statistics (the number of SEC Networks, of SEC Axes, etc).

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/archives", "prefix" : "archives" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/companies", "prefix" : "companies" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://zorba.io/modules/datetime", "prefix" : "datetime" }, { "uri" : "http://xbrl.io/modules/bizql/facts", "prefix" : "facts" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/filings", "prefix" : "filings" }, { "uri" : "http://www.28msec.com/modules/mongodb", "prefix" : "mongo" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/core", "prefix" : "sec" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "acceptance-dateTimes", "qname" : "filings:acceptance-dateTimes", "signature" : "($filings-or-ids as item()*) as dateTime*", "description" : "

    Retrieves the acceptance date of filings.

    \n", "summary" : "

    Retrieves the acceptance date of filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of filings or their IDs.
    " } ], "returns" : { "type" : "dateTime*", "description" : "the acceptance dateTimes." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "document-types", "qname" : "filings:document-types", "signature" : "($filings-or-ids as item()*) as string?", "description" : "

    Retrieves the document type of the filings.

    \n", "summary" : "

    Retrieves the document type of the filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of filings or their ids.
    " } ], "returns" : { "type" : "string?", "description" : "the document types (10-K, 10-Q)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "filing-dates", "qname" : "filings:filing-dates", "signature" : "($filings-or-ids as item()*) as date*", "description" : "

    Retrieves the submission date of filings.

    \n", "summary" : "

    Retrieves the submission date of filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of filings or their IDs.
    " } ], "returns" : { "type" : "date*", "description" : "the submission dates." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "filings-for-companies", "qname" : "filings:filings-for-companies", "signature" : "($companies-or-ciks as item()*) as object()*", "description" : "

    Return all filings submitted by the supplied companies.

    \n", "summary" : "

    Return all filings submitted by the supplied companies.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "companies-or-ciks", "type" : "item()", "occurrence" : "*", "description" : "
    arbitrary number of company objects or CIKs.
    " } ], "returns" : { "type" : "object()*", "description" : "all filings submitted by these companies." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "generators", "qname" : "filings:generators", "signature" : "($filings-or-ids as item()*) as string*", "description" : "

    Retrieves the generators of filings.

    \n", "summary" : "

    Retrieves the generators of filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of filings or their IDs.
    " } ], "returns" : { "type" : "string*", "description" : "the generators used." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-abstracts", "qname" : "filings:num-abstracts", "signature" : "($filings-or-ids) as integer*", "description" : " Return the number of (distinct) abstracts in each of the given filings.\n", "summary" : "

    Return the number of (distinct) abstracts in each of the given filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of filings or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of abstracts" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-axes", "qname" : "filings:num-axes", "signature" : "($filings-or-ids) as integer*", "description" : " Return the number of (distinct) axes in each of the given filings.\n", "summary" : "

    Return the number of (distinct) axes in each of the given filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of filings or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of axes" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-concepts", "qname" : "filings:num-concepts", "signature" : "($filings-or-ids) as integer*", "description" : " Return the number of (distinct) concepts in each of the given filings.\n", "summary" : "

    Return the number of (distinct) concepts in each of the given filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of filings or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of concepts" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-extension-abstracts", "qname" : "filings:num-extension-abstracts", "signature" : "($filings-or-ids) as integer*", "description" : " Return the number of extension abstracts in each of the given filings.\n", "summary" : "

    Return the number of extension abstracts in each of the given filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of filings or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of abstracts" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-extension-concepts", "qname" : "filings:num-extension-concepts", "signature" : "($filings-or-ids) as integer*", "description" : " Return the number of extension concepts in each of the given filings.\n", "summary" : "

    Return the number of extension concepts in each of the given filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of filings or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of concepts" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-extension-facts", "qname" : "filings:num-extension-facts", "signature" : "($filings-or-ids) as integer*", "description" : " Return the number of extension facts in each of the given filings.\n", "summary" : "

    Return the number of extension facts in each of the given filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of filings or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of facts" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-facts", "qname" : "filings:num-facts", "signature" : "($filings-or-ids) as integer*", "description" : " Return the number of facts in each of the given filings.\n", "summary" : "

    Return the number of facts in each of the given filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of filings or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of facts" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-footnotes", "qname" : "filings:num-footnotes", "signature" : "($filings-or-ids) as integer*", "description" : " Return the number of footnotes in each of the given filings.\n", "summary" : "

    Return the number of footnotes in each of the given filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of filings or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of facts" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-line-items", "qname" : "filings:num-line-items", "signature" : "($filings-or-ids) as integer*", "description" : " Return the number of (distinct) line items in each of the given filings.\n", "summary" : "

    Return the number of (distinct) line items in each of the given filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of filings or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of line items" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-members", "qname" : "filings:num-members", "signature" : "($filings-or-ids) as integer*", "description" : " Return the number of (distinct) members in each of the given filings.\n", "summary" : "

    Return the number of (distinct) members in each of the given filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of filings or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of members" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-networks", "qname" : "filings:num-networks", "signature" : "($filings-or-ids) as integer*", "description" : " Return the number of networks in each of the given filings.\n", "summary" : "

    Return the number of networks in each of the given filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of filings or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of networks" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-report-elements", "qname" : "filings:num-report-elements", "signature" : "($filings-or-ids) as integer*", "description" : " Return the number of (distinct) report elements in each of the given filings.\n", "summary" : "

    Return the number of (distinct) report elements in each of the given filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of filings or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of report elements" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "num-tables", "qname" : "filings:num-tables", "signature" : "($filings-or-ids) as integer*", "description" : " Return the number of tables in each of the given filings.\n", "summary" : "

    Return the number of tables in each of the given filings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filings-or-ids", "type" : null, "occurrence" : null, "description" : "
    list of filings or IDs
    " } ], "returns" : { "type" : "integer*", "description" : "the said number of tables" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/string" : { "ns" : "http://zorba.io/modules/string", "description" : "

    This module provides string related functions.

    \n

    Mostly, the functions in this module provide primitives\n to work with streamable strings. For example, it allows to\n check whether a given string is streamable or seekable.

    \n", "sees" : [ ], "authors" : [ "Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/string", "prefix" : "string" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "analyze-string", "qname" : "string:analyze-string", "signature" : "($input as xs:string?, $pattern as xs:string) as array()", "description" : " Analyzes a string using a regular expression, returning sequence of JSON\n objects that identify which parts of the input string matched or failed to\n match the regular expression; and in the case of matched substrings, which\n substrings matched each capturing group in the regular expression.\n

    \n This function behaves like\n fn:analyze-string\n but returns a JSON array rather than an XML element.\n", "summary" : "

    Analyzes a string using a regular expression, returning sequence of JSON\n objects that identify which parts of the input string matched or failed to\n match the regular expression; and in the case of matched substrings, which\n substrings matched each capturing group in the regular expression.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : "?", "description" : "
    The string to analyze. If the empty sequence, the function behaves as if $input were a zero-length string.
    " }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "
    The regular expression.
    " } ], "returns" : { "type" : "array()", "description" : "a JSON array of objects where each object contains a single key/value pair. Each key is either match or non-match. For non-match, the value is a string that is the part of $input that did not match; for match, the value is either a string that is the part of $input that matched (when $pattern contains no capturing groups) or an array containing values for both capturing groups and other matches.

    Capturing group matches are themselves arrays where the first element is the group number (1-based) and subsequent elements are either a string that is the part of $input that matched or sub-arrays for nested capturing groups." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "analyze-string", "qname" : "string:analyze-string", "signature" : "($input as xs:string?, $pattern as xs:string, $flags as xs:string) as array() external", "description" : " Analyzes a string using a regular expression, returning sequence of JSON\n objects that identify which parts of the input string matched or failed to\n match the regular expression; and in the case of matched substrings, which\n substrings matched each capturing group in the regular expression.\n

    \n This function behaves like\n fn:analyze-string\n but returns a JSON array rather than an XML element.\n", "summary" : "

    Analyzes a string using a regular expression, returning sequence of JSON\n objects that identify which parts of the input string matched or failed to\n match the regular expression; and in the case of matched substrings, which\n substrings matched each capturing group in the regular expression.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "xs:string", "occurrence" : "?", "description" : "
    The string to analyze. If the empty sequence, the function behaves as if $input were a zero-length string.
    " }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "
    The regular expression.
    " }, { "name" : "flags", "type" : "xs:string", "occurrence" : null, "description" : "
    The argument is interpreted in the same way as for the fn:matches function.
    " } ], "returns" : { "type" : "array()", "description" : "a JSON array of objects where each object contains a single key/value pair. Each key is either match or non-match. For non-match, the value is a string that is the part of $input that did not match; for match, the value is either a string that is the part of $input that matched (when $pattern contains no capturing groups) or an array containing values for both capturing groups and other matches.

    Capturing group matches are themselves arrays where the first element is the group number (1-based) and subsequent elements are either a string that is the part of $input that matched or sub-arrays for nested capturing groups." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-seekable", "qname" : "string:is-seekable", "signature" : "($s as string) as boolean external", "description" : "

    This function checks whether a given string item is a\n seekable stream string.

    \n

    For example, a seekable streamable string is returned by the\n file module.

    \n", "summary" : "

    This function checks whether a given string item is a\n seekable stream string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "string", "occurrence" : null, "description" : "
    the string to check
    " } ], "returns" : { "type" : "boolean", "description" : "true if the given item is a seekable stream string or false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-streamable", "qname" : "string:is-streamable", "signature" : "($s as string) as boolean external", "description" : "

    This function checks whether a given string item is implemented by a\n streamable string.

    \n

    A streamable string is produced by some functions of a module.\n It's an optimized implementation of an string to handle arbitrary\n sized data. The drawback is that its value can only be consumed once.\n That is, only one function can access the value of a streamable string\n item.

    \n", "summary" : "

    This function checks whether a given string item is implemented by a\n streamable string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "string", "occurrence" : null, "description" : "
    the string to check
    " } ], "returns" : { "type" : "boolean", "description" : "true if the given item is implemented using a streamable string or false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "materialize", "qname" : "string:materialize", "signature" : "($s as string) as string external", "description" : "

    This function materializes a streamable string.

    \n

    The drawback of a streamable (non-seekable) string is that\n its value can only be consumed once. That is, only one function\n can access the value of a streamable string item.

    \n

    In order to remedy this situation, this function can be used to\n convert a streamable string into its non-streamable counterpart. As a\n result, the string returned by this function has the same value as its\n input but is materialized and, hence, can be consumed multiple times.

    \n", "summary" : "

    This function materializes a streamable string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "string", "occurrence" : null, "description" : "
    the streamable string item to materialize
    " } ], "returns" : { "type" : "string", "description" : "a materialized string of its input or the input if the input item was not a streamable string." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "split", "qname" : "string:split", "signature" : "($s as string, $separator as string) as string* external", "description" : "

    Returns a sequence of strings constructed by splitting the input wherever\n the given separator is found.

    \n

    The function is different from tokenize. It doesn't allow\n the separator to be a regular expression. This restriction allows for more\n performant implementation. Specifically, the function processes\n streamable strings as input in a streamable way which is particularly useful\n to tokenize huge strings.

    \n", "summary" : "

    Returns a sequence of strings constructed by splitting the input wherever\n the given separator is found.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "string", "occurrence" : null, "description" : "
    the input string to split
    " }, { "name" : "separator", "type" : "string", "occurrence" : null, "description" : "
    the separator used for splitting the input string $s
    " } ], "returns" : { "type" : "string*", "description" : "a sequence of strings constructed by splitting the input" }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/store" : { "ns" : "http://www.28msec.com/modules/store", "description" : " This module provides functions to perform MongoDB query operations\n (i.e. find and aggregate) on the database associated with the\n project.\n

    The module is always imported so you don't need to import it explicitly.\n Also, you don't need to fully qualify the function if you want to invoke it.

    \n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/mongodb/types", "prefix" : "mongo" }, { "uri" : "http://www.28msec.com/modules/store", "prefix" : "store" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "aggregate", "qname" : "store:aggregate", "signature" : "($collection as string, $pipeline as array()) as object() external", "description" : " Performs a MongoDB aggregation framework job on the given collection.\n The $pipeline parameter needs to specify a valid aggregation\n framework pipeline. For example,\n
    \n  [\n    { $project : {\n       author : 1,\n       tags : 1,\n    } },\n    { $unwind : \"$tags\" },\n    { $group : {\n       _id : { tags : \"$tags\" },\n       authors : { $addToSet : \"$author\" }\n    } }\n ]\n 
    \n The function returns the result as one object. The object contains\n the field named \"ok\" with value 0 if the execution failed or 1 if\n it succeeded. If it succeeded, the result is contained as an array\n in the result field. Otherwise, the errmsg field contains the description\n of the error. For exampl,e\n
    \n {\n   \"result\" : [ ... ],\n   \"ok\" : 1\n }\n 
    \n", "summary" : "

    Performs a MongoDB aggregation framework job on the given collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "collection", "type" : "string", "occurrence" : null, "description" : "
    the name of the collection to execute the job on
    " }, { "name" : "pipeline", "type" : "array()", "occurrence" : null, "description" : "
    the specification of the pipeline to execute
    " } ], "returns" : { "type" : "object()", "description" : "an object with the result or the error message." }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "clear-if", "qname" : "store:clear-if", "signature" : "($cond as boolean) as integer", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "cond", "type" : "boolean", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "clear", "qname" : "store:clear", "signature" : "() as integer external", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "collection-chunk-specs", "qname" : "store:collection-chunk-specs", "signature" : "($name as string) as object()*", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "object()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "collection-chunk-specs", "qname" : "store:collection-chunk-specs", "signature" : "($name as string, $chunk-size as integer) as object()* external", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "" }, { "name" : "chunk-size", "type" : "integer", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "object()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "collection-chunk", "qname" : "store:collection-chunk", "signature" : "($name as string, $chunk as object()) as item()* external", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "string", "occurrence" : null, "description" : "" }, { "name" : "chunk", "type" : "object()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "find", "qname" : "store:find", "signature" : "($coll as string, $query as object()) as object()*", "description" : " Performs a MongoDB query operation on the given collection and\n returns all matches.\n", "summary" : "

    Performs a MongoDB query operation on the given collection and\n returns all matches.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "coll", "type" : "string", "occurrence" : null, "description" : "" }, { "name" : "query", "type" : "object()", "occurrence" : null, "description" : "
    the query operation to perform
    " } ], "returns" : { "type" : "object()*", "description" : "all matches returned by the given query operation" }, "errors" : [ "zerr:ZSTR0009 if the given collection does not exist" ] }, { "isDocumented" : true, "arity" : 3, "name" : "find", "qname" : "store:find", "signature" : "($coll as string, $query as object(), $options as object()) as object()* external", "description" : " Performs a MongoDB query operation on the given collection and\n returns all matches.\n Available options:\n
      \n
    • to-return: the maximum number of objects to return (0 = unlimited)
    • \n
    • to-skip: start with the n-th object
    • \n
    • batch-size: the number of objects to return in one batch
    • \n
    • slave-ok: allow this query to be run against a replica secondary
    • \n
    • await-data: the server will block for some extra time before returning,\n waiting for more data to return
    • \n
    • partial-results: return partial results if some shards are down instead\n of returning an error
    • \n
    \n", "summary" : "

    Performs a MongoDB query operation on the given collection and\n returns all matches.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "coll", "type" : "string", "occurrence" : null, "description" : "
    the name of the collection
    " }, { "name" : "query", "type" : "object()", "occurrence" : null, "description" : "
    the query operation to perform
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    the options for this operation
    " } ], "returns" : { "type" : "object()*", "description" : "all matches returned by the given query operation" }, "errors" : [ "zerr:ZSTR0009 if the given collection does not exist" ] }, { "isDocumented" : false, "arity" : 1, "name" : "flush-if", "qname" : "store:flush-if", "signature" : "($cond as boolean) as empty-sequence()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "cond", "type" : "boolean", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "flush", "qname" : "store:flush", "signature" : "() as empty-sequence() external", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "empty-sequence()", "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/hash" : { "ns" : "http://zorba.io/modules/hash", "description" : " This module provides functions that perform different hash operations.\n For example, they compute MD5 and various SHA functions on either\n strings or binary. The result is the base64 encoded value of the hash.\n", "sees" : [ ], "authors" : [ "Gabriel Petrovay, Markus Pilman, Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/hash", "prefix" : "hash" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "hash-binary", "qname" : "hash:hash-binary", "signature" : "($value as xs:base64Binary, $alg as xs:string) as xs:base64Binary external", "description" : " This function computes a hash value of the binary form of the given\n base64Binary item, i.e. the item is base64-decoded before hashing.\n", "summary" : "

    This function computes a hash value of the binary form of the given\n base64Binary item, i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    The binary item to be hashed.
    " }, { "name" : "alg", "type" : "xs:string", "occurrence" : null, "description" : "
    The algorithm to use for this hashing operation. Supported algorithms are \"md5\", \"sha1\", and \"sha256\".
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "The hash as xs:base64Binary of the provided binary" }, "errors" : [ "hash:UNSUPPORTED-ALGORITHM if the given hash algorithm is not supported" ] }, { "isDocumented" : true, "arity" : 2, "name" : "hash", "qname" : "hash:hash", "signature" : "($value as xs:string, $alg as xs:string) as xs:base64Binary external", "description" : " This function computes a hash value of the string provided as parameter.\n The function expects the hash algorithm to be used as parameter.\n", "summary" : "

    This function computes a hash value of the string provided as parameter.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to be hashed.
    " }, { "name" : "alg", "type" : "xs:string", "occurrence" : null, "description" : "
    The algorithm to use for this hashing operation. Supported algorithms are \"md5\", \"sha1\", and \"sha256\".
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "The hash as xs:base64binary of the provided string" }, "errors" : [ "hash:UNSUPPORTED-ALGORITHM if the given hash algorithm is not supported" ] }, { "isDocumented" : true, "arity" : 1, "name" : "md5-binary", "qname" : "hash:md5-binary", "signature" : "($value as xs:base64Binary) as xs:base64Binary", "description" : " This function computes the MD5 hash value of the binary form of the given\n base64Binary item, i.e. the item is base64-decoded before hashing.\n", "summary" : "

    This function computes the MD5 hash value of the binary form of the given\n base64Binary item, i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    The binary item to hash.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "The MD5 hash of the provided binary." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "md5", "qname" : "hash:md5", "signature" : "($value as xs:string) as xs:base64Binary", "description" : " Computes the MD5 hash of the string provided as parameter.\n", "summary" : "

    Computes the MD5 hash of the string provided as parameter.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to hash
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "The MD5 hash as xs:base64Binary" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sha1-binary", "qname" : "hash:sha1-binary", "signature" : "($value as xs:base64Binary) as xs:base64Binary", "description" : " This function computes the SHA1 hash value of the binary form of the given\n base64Binary item, i.e. the item is base64-decoded before hashing.\n", "summary" : "

    This function computes the SHA1 hash value of the binary form of the given\n base64Binary item, i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    The binary item to hash.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "The base64 encoded SHA1 hash of the provided binary." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sha1", "qname" : "hash:sha1", "signature" : "($value as xs:string) as xs:base64Binary", "description" : " Computes the SHA1 hash of the string provided as parameter.\n", "summary" : "

    Computes the SHA1 hash of the string provided as parameter.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to hash.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "The SHA1 hash as xs:base64Binary" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/xsl-fo" : { "ns" : "http://zorba.io/modules/xsl-fo", "description" : " This module converts XSL-FO documents\n to various formats such as PDF, EPS, PCL, AFP, Text, PNG, Postscript, RTF, and TIFF.\n For instance, the following example converts a simple XSL-FO document to PDF:\n

    \n

    import module namespace fop = \"http://zorba.io/modules/xsl-fo\";\n import module namespace file = \"http://expath.org/ns/file\";\n declare namespace fo = \"http://www.w3.org/1999/XSL/Format\";\n let $xsl-fo := <fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">\n   <fo:layout-master-set>\n     <fo:simple-page-master master-name=\"my-page\">\n       <fo:region-body margin=\"1in\"/>\n     </fo:simple-page-master>\n   </fo:layout-master-set>\n   <fo:page-sequence master-reference=\"my-page\">\n     <fo:flow flow-name=\"xsl-region-body\">\n       <fo:block>Hello, world!</fo:block>\n     </fo:flow>\n   </fo:page-sequence>\n  </fo:root>\n let $pdf := fop:generator($fop:PDF, $xsl-fo)\n return file:write-binary(\"simple.pdf\", $pdf)
    \n

    \n This module uses Apache-FOP to generate content from an XSL-FO document.\n See the Apache FOP documentation for further information.\n

    \n Note for Windows users: On Windows, this module won't work out of the box, since\n this module uses Java. But the Java VM dll is not in the system path by default. To make\n this module work, you need to add the directory where the jvm.dll is located to the\n system path. This dll is located at JRE_DIR\\bin\\client. On a standard installation, this would\n be something a path like \"C:\\Program Files\\Java\\jre6\\bin\\client\".\n", "sees" : [ "http://xmlgraphics.apache.org/fop/" ], "authors" : [ "Markus Pilman" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://www.zorba-xquery.com/modules/util-jvm", "prefix" : "util-jvm" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/modules/xsl-fo", "prefix" : "xsl-fo" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "generator", "qname" : "xsl-fo:generator", "signature" : "($output-format as xs:string, $xsl-fo-document as node()) as xs:base64Binary", "description" : " The generator function takes an XSL-FO document as input and generates output\n in the format given as input.\n The output format can be given as a MIME type - for example \"application/pdf\"\n - or one of the predefined variables can be used - like $xsl-fo:PDF. Please\n refer to the Apache FOP documentation for\n supported output formats.\n Apache FOP does not support 100% of the XSL-FO standard.\n Please consult the official\n documentation for further information.\n This function tries to find the needed Java libraries itself.

    \n On a Mac OS X computer, it should be sufficient to install Apache FOP via Mac\n Ports.

    \n On Ubuntu it should be sufficient to install the fop packages via apt-get.

    \n On Windows, the classpath needs to be set manually using\n generator#3.

    \n This function tries to find the jar files via environment variables. The user can set the\n variable FOP_HOME to the root directory of an Apache FOP distribution. If you have all\n JAR files in the same directory, you can set the environment variable FOP_LIB_DIR to this\n directory.\n", "summary" : "

    The generator function takes an XSL-FO document as input and generates output\n in the format given as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "output-format", "type" : "xs:string", "occurrence" : null, "description" : "
    The mime of the output format, to tell Apache FOP which kind of document it should create.
    " }, { "name" : "xsl-fo-document", "type" : "node()", "occurrence" : null, "description" : "
    The XSL-FO document from which the output should be generated.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "The generated output document." }, "errors" : [ "xsl-fo:JVM-NOT-STARTED If zorba was unable to start the JVM.", "xsl-fo:JAVA-EXCEPTION If Apache FOP throws an exception - i.e. if the input format is not correct/supported.", "xsl-fo:JAR-NOT-FOUND If a needed Java library could not be found." ] } ], "variables" : [ { "name" : "xsl-fo:AFP", "type" : "xs:string", "description" : " The mime type of IBMs AFP format (application/x-afp).\n" }, { "name" : "xsl-fo:EPS", "type" : "xs:string", "description" : " The mime type of the EPS format (application/postscript).\n" }, { "name" : "xsl-fo:PCL", "type" : "xs:string", "description" : " The mime type of the PCL format (application/x-pcl).\n" }, { "name" : "xsl-fo:PDF", "type" : "xs:string", "description" : " The mime type of the PDF format (application/pdf).\n" }, { "name" : "xsl-fo:PLAIN_TEXT", "type" : "xs:string", "description" : " The mime type for plain text files (text/plain).\n" }, { "name" : "xsl-fo:PNG", "type" : "xs:string", "description" : " The mime type of the PNG format (image/png).\n" }, { "name" : "xsl-fo:POSTSCRIPT", "type" : "xs:string", "description" : " The mime type of the postscript format (application/postscript).\n" }, { "name" : "xsl-fo:RTF", "type" : "xs:string", "description" : " The mime type of the RTF format (application/rtf).\n" }, { "name" : "xsl-fo:TIFF", "type" : "xs:string", "description" : " The mime type of TIFF format (application/tiff).\n" } ] }, "http://zorba.io/warnings" : { "ns" : "http://zorba.io/warnings", "description" : " This module contains one variable declaration for each diagnostic of the\n http://zorba.io/warnings namespace.\n The variables serves as documentation for the errors but can also\n be used in the code. For example, one useful scenario is to compare\n an error caught in the catch clause of a try-catch expression with one of\n the variables.\n", "sees" : [ ], "authors" : [ "Carlos Lopez" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/warnings", "prefix" : "zwarn" } ], "functions" : [ ], "variables" : [ { "name" : "zwarn:NS", "type" : "item()*", "description" : "" }, { "name" : "zwarn:ZWST0002", "type" : "xs:QName", "description" : " This warning is reported if the declaration of a function, variable,\n collection, or index contains an annotation that is not in the\n http://zorba.io/annotations namespace and Zorba doesn't know how to\n handle.\n" }, { "name" : "zwarn:ZWST0003", "type" : "item()*", "description" : "" }, { "name" : "zwarn:ZWST0004", "type" : "item()*", "description" : "" }, { "name" : "zwarn:ZWST0005", "type" : "xs:QName", "description" : " This warning is raised if the user explicitly enables caching\n of function results (using the %an:cache or %an:strictlydeterministic\n annotation) but the function cannot be cached.\n For %an:cache this happens if the function is updating or variadic.\n For %an:strictlydeterministic this happens if the function is updating,\n variadic or sequential.\n" }, { "name" : "zwarn:ZWST0006", "type" : "xs:QName", "description" : " This warning is raised if the user explicitly enables caching\n of function results (using the %an:cache annotation) and the function\n is annotated as sequential or nondeterministic.\n" }, { "name" : "zwarn:ZWST0007", "type" : "item()*", "description" : "" }, { "name" : "zwarn:ZWST0008", "type" : "item()*", "description" : "" }, { "name" : "zwarn:ZWST0009", "type" : "xs:QName", "description" : " This warning is enabled when the \"common-language\" option is employed. It will raise warnings\n for language features that are not supported by both XQuery and JSONiq grammars.\n" } ] }, "http://www.28msec.com/modules/sparql" : { "ns" : "http://www.28msec.com/modules/sparql", "description" : " This module contains functions to interact with a SPARQL endpoint.\n Requests to an endpoint are made using HTTP.\n Specifically, this module allows SELECT, ASK, CONSTRUCT and DESCRIBE queries. Additionally, it also allows for UPDATE statements.\n Various result formats are supported (e.g. XML, JSON, CSV)\n

    Configuration

    \n For this module you may use a preconfigured default or named datasource of the SPARQL category.\n You can also provide a configuration object directly.\n

    As config parameter you can either pass a string that will be interpreted as a SPARQL endpoint datasource name or\n an object with the following properties:\n

      \n
    • href: The URL of the SPARQL endpoint to use. Required.
    • \n
    • auth_method: The HTTP authentication method to use.
    • \n
    • username: The username to use for HTTP authentication.
    • \n
    • password: The password to use for HTTP authentication.
    • \n
    \n

    \n

    Options

    \n

    The options object that can be passed to plenty of the functions in this module. It may have the following properties:\n

      \n
    • default-graph-uri: A string or an array of strings with the graph URIs to be used by the query.
    • \n
    • named-graph-uri: A string or an array of strings with the named graph URIs to be used by the query.
    • \n
    • using-graph-uri: A string or an array of strings with the graph URIs to be used by an update statement.
    • \n
    • using-named-graph-uri: A string or an array of strings with the named graph URIs to be used by an update statement.
    • \n
    • method: The request method to be used. Available method values are $sparql:METHOD-GET, $sparql:METHOD-POST-URLENCODED or $sparql:METHOD-POST-SPARQL.
    • \n
    • format : The result format to request. Possible format values are $sparql:FORMAT-XML, $sparql:FORMAT-JSON, $sparql:FORMAT-CSV, $sparql:FORMAT-TSV, $sparql:FORMAT-ANY. For CONSTRUCT or DESCRIBE queries $sparql:FORMAT-RDF is available.
    • \n
    • parameters: Many SPARQL endpoints support additional parameters which are not part of the SPARQL endpoint specification. They can be provided here.
    • \n
    • http-headers: object that will be used as the headers property for the requests made by the http-client.
    • \n
    • http-options: object that will be used as the options property for the requests made by the http-client.
    • \n
    \n

    All those properties are optional.

    \n

    \n", "sees" : [ ], "authors" : [ "Alexander.Kreutz@28msec.com" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://zorba.io/modules/http-client", "prefix" : "http-client" }, { "uri" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "prefix" : "rdf" }, { "uri" : "http://www.w3.org/2005/sparql-results#", "prefix" : "s" }, { "uri" : "http://www.28msec.com/modules/sparql", "prefix" : "sparql" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "ask", "qname" : "sparql:ask", "signature" : "($query as string) as xs:boolean", "description" : "

    \n This function sends a SPARQL ASK query to an endpoint and returns the result as boolean value.\n The default datasource for SPARQL will be used.\n

    \n", "summary" : "

    \n This function sends a SPARQL ASK query to an endpoint and returns the result as boolean value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL ASK query as string.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "The boolean ASK query result." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "ask", "qname" : "sparql:ask", "signature" : "($query as string, $options as object()?) as xs:boolean", "description" : "

    \n This function sends a SPARQL ASK query to an endpoint and returns the result as boolean value.\n The default datasource for SPARQL will be used.\n

    \n

    \n

      \n
    • The default-graph-uri and named-graph-uri properties of the options object may be used to pass default graph URIs or named graph URIs to the endpoint.
    • \n
    • The method property of the options object may be used to set the request method to be used. GET will be used as default.
    • \n
    • The format property of the options object may be used to request a specific result format. However this function will try to extract only the boolean answer from the result.
    • \n
    \n

    \n", "summary" : "

    \n This function sends a SPARQL ASK query to an endpoint and returns the result as boolean value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL ASK query as string.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An optional options object as described in the module description.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "The boolean ASK query result." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "ask", "qname" : "sparql:ask", "signature" : "($config as item()?, $query as string, $options as object()?) as xs:boolean", "description" : "

    \n This function sends a SPARQL ASK query to an endpoint and returns the result as boolean value.\n

    \n

    \n

      \n
    • The default-graph-uri and named-graph-uri properties of the options object may be used to pass default graph URIs or named graph URIs to the endpoint.
    • \n
    • The method property of the options object may be used to set the request method to be used. GET will be used as default.
    • \n
    • The format property of the options object may be used to request a specific result format. However this function will try to extract only the boolean answer from the result.
    • \n
    \n

    \n", "summary" : "

    \n This function sends a SPARQL ASK query to an endpoint and returns the result as boolean value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "config", "type" : "item()", "occurrence" : "?", "description" : "
    The name of the credentials to use as string or a config object as described in the module description.
    " }, { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL ASK query as string.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An optional options object as described in the module description.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "The boolean ASK query result." }, "errors" : [ "sparql:INVALID-RESPONSE-TYPE if the response format cannot be handled by this function", "sparql:ERROR if any http or endpoint error occurs", "sparql:INVALID-PARAMETER invalid option specification", "sparql:CREDENTIALS-NOT-FOUND credential information not found", "sparql:CREDENTIALS-INVALID credential information not valid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "query-json", "qname" : "sparql:query-json", "signature" : "($query as string) as object()", "description" : "

    \n This function sends a SPARQL SELECT or ASK query to an endpoint and returns the query response as SPARQL JSON format object.\n If the endpoint fails to deliver SPARQL JSON result format this function will try to convert the results to JSON if possible.\n The default datasource for SPARQL will be used.\n

    \n

    Link to the specification of the result format at W3C: SPARQL 1.1 Query Results JSON Format

    \n", "summary" : "

    \n This function sends a SPARQL SELECT or ASK query to an endpoint and returns the query response as SPARQL JSON format object.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL SELECT or ASK query as string.
    " } ], "returns" : { "type" : "object()", "description" : "The query result in SPARQL JSON format." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "query-json", "qname" : "sparql:query-json", "signature" : "($query as string, $options as object()?) as object()", "description" : "

    \n This function sends a SPARQL SELECT or ASK query to an endpoint and returns the query response as SPARQL JSON format object.\n If the endpoint fails to deliver SPARQL JSON result format this function will try to convert the results to JSON if possible.\n The default datasource for SPARQL will be used.\n

    \n

    Link to the specification of the result format at W3C: SPARQL 1.1 Query Results JSON Format

    \n

    \n

      \n
    • The default-graph-uri and named-graph-uri properties of the options object may be used to pass default graph URIs or named graph URIs to the endpoint.
    • \n
    • The method property of the options object may be used to set the request method to be used. GET will be used as default.
    • \n
    • The format property of the options object will be ignored. \"application/sparql-results+json\" will be requested as result format.
    • \n
    \n

    \n", "summary" : "

    \n This function sends a SPARQL SELECT or ASK query to an endpoint and returns the query response as SPARQL JSON format object.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL SELECT or ASK query as string.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An optional options object as described in the module description.
    " } ], "returns" : { "type" : "object()", "description" : "The query result in SPARQL JSON format." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "query-json", "qname" : "sparql:query-json", "signature" : "($config as item()?, $query as string, $options as object()?) as object()", "description" : "

    \n This function sends a SPARQL SELECT or ASK query to an endpoint and returns the query response as SPARQL JSON format object.\n If the endpoint fails to deliver SPARQL JSON result format this function will try to convert the results to JSON if possible.\n

    \n

    Link to the specification of the result format at W3C: SPARQL 1.1 Query Results JSON Format

    \n

    \n

      \n
    • The default-graph-uri and named-graph-uri properties of the options object may be used to pass default graph URIs or named graph URIs to the endpoint.
    • \n
    • The method property of the options object may be used to set the request method to be used. GET will be used as default.
    • \n
    • The format property of the options object will be ignored. \"application/sparql-results+json\" will be requested as result format.
    • \n
    \n

    \n", "summary" : "

    \n This function sends a SPARQL SELECT or ASK query to an endpoint and returns the query response as SPARQL JSON format object.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "config", "type" : "item()", "occurrence" : "?", "description" : "
    The name of the credentials to use as string or a config object as described in the module description.
    " }, { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL SELECT or ASK query as string.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An optional options object as described in the module description.
    " } ], "returns" : { "type" : "object()", "description" : "The query result in SPARQL JSON format." }, "errors" : [ "sparql:INVALID-RESPONSE-TYPE if the response format cannot be handled by this function", "sparql:ERROR if any http or endpoint error occurs", "sparql:INVALID-PARAMETER invalid option specification", "sparql:CREDENTIALS-NOT-FOUND credential information not found", "sparql:CREDENTIALS-INVALID credential information not valid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "query-rdf", "qname" : "sparql:query-rdf", "signature" : "($query as string) as element(rdf:RDF)", "description" : "

    \n This function sends a SPARQL CONSTRUCT or DESCRIBE query to an endpoint and returns the query response as RDF.\n The default datasource for SPARQL will be used.\n

    \n

    Link to the specification of the result format at W3C: RDF/XML Syntax Specification

    \n", "summary" : "

    \n This function sends a SPARQL CONSTRUCT or DESCRIBE query to an endpoint and returns the query response as RDF.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL CONSTRUCT or DESCRIBE query as string.
    " } ], "returns" : { "type" : "element(rdf:RDF)", "description" : "The query result as RDF XML element." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "query-rdf", "qname" : "sparql:query-rdf", "signature" : "($query as string, $options as object()?) as element(rdf:RDF)", "description" : "

    \n This function sends a SPARQL CONSTRUCT or DESCRIBE query to an endpoint and returns the query response as RDF.\n The default datasource for SPARQL will be used.\n

    \n

    Link to the specification of the result format at W3C: RDF/XML Syntax Specification

    \n

    \n

      \n
    • The default-graph-uri and named-graph-uri properties of the options object may be used to pass default graph URIs or named graph URIs to the endpoint.
    • \n
    • The method property of the options object may be used to set the request method to be used. GET will be used as default.
    • \n
    • The format property of the options object will be ignored. \"application/rdf+xml\" will be requested as result format.
    • \n
    \n

    \n", "summary" : "

    \n This function sends a SPARQL CONSTRUCT or DESCRIBE query to an endpoint and returns the query response as RDF.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL CONSTRUCT or DESCRIBE query as string.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An optional options object as described in the module description.
    " } ], "returns" : { "type" : "element(rdf:RDF)", "description" : "The query result as RDF XML element." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "query-rdf", "qname" : "sparql:query-rdf", "signature" : "($config as item()?, $query as string, $options as object()?) as element(rdf:RDF)", "description" : "

    \n This function sends a SPARQL CONSTRUCT or DESCRIBE query to an endpoint and returns the query response as RDF.\n

    \n

    Link to the specification of the result format at W3C: RDF/XML Syntax Specification

    \n

    \n

      \n
    • The default-graph-uri and named-graph-uri properties of the options object may be used to pass default graph URIs or named graph URIs to the endpoint.
    • \n
    • The method property of the options object may be used to set the request method to be used. GET will be used as default.
    • \n
    • The format property of the options object will be ignored. \"application/rdf+xml\" will be requested as result format.
    • \n
    \n

    \n", "summary" : "

    \n This function sends a SPARQL CONSTRUCT or DESCRIBE query to an endpoint and returns the query response as RDF.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "config", "type" : "item()", "occurrence" : "?", "description" : "
    The name of the credentials to use as string or a config object as described in the module description.
    " }, { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL CONSTRUCT or DESCRIBE query as string.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An optional options object as described in the module description.
    " } ], "returns" : { "type" : "element(rdf:RDF)", "description" : "The query result as RDF XML element." }, "errors" : [ "sparql:INVALID-RESPONSE-TYPE if the response format cannot be handled by this function", "sparql:ERROR if any http or endpoint error occurs", "sparql:INVALID-PARAMETER invalid option specification", "sparql:CREDENTIALS-NOT-FOUND credential information not found", "sparql:CREDENTIALS-INVALID credential information not valid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "query-xml", "qname" : "sparql:query-xml", "signature" : "($query as string) as element(s:sparql)", "description" : "

    \n This function sends a SPARQL SELECT or ASK query to an endpoint and returns the query response as SPARQL XML format element.\n If the endpoint fails to deliver SPARQL XML result format this function will try to convert the results to XML if possible.\n The default datasource for SPARQL will be used.\n

    \n

    Link to the specification of the result format at W3C: SPARQL Query Results XML Format

    \n", "summary" : "

    \n This function sends a SPARQL SELECT or ASK query to an endpoint and returns the query response as SPARQL XML format element.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL SELECT or ASK query as string.
    " } ], "returns" : { "type" : "element(s:sparql)", "description" : "The query result in SPARQL XML format." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "query-xml", "qname" : "sparql:query-xml", "signature" : "($query as string, $options as object()?) as element(s:sparql)", "description" : "

    \n This function sends a SPARQL SELECT or ASK query to an endpoint and returns the query response as SPARQL XML format element.\n If the endpoint fails to deliver SPARQL XML result format this function will try to convert the results to XML if possible.\n The default datasource for SPARQL will be used.\n

    \n

    Link to the specification of the result format at W3C: SPARQL Query Results XML Format

    \n

    \n

      \n
    • The default-graph-uri and named-graph-uri properties of the options object may be used to pass default graph URIs or named graph URIs to the endpoint.
    • \n
    • The method property of the options object may be used to set the request method to be used. GET will be used as default.
    • \n
    • The format property of the options object will be ignored. \"application/sparql-results+xml\" will be requested as result format.
    • \n
    \n

    \n", "summary" : "

    \n This function sends a SPARQL SELECT or ASK query to an endpoint and returns the query response as SPARQL XML format element.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL SELECT or ASK query as string.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An optional options object as described in the module description.
    " } ], "returns" : { "type" : "element(s:sparql)", "description" : "The query result in SPARQL XML format." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "query-xml", "qname" : "sparql:query-xml", "signature" : "($config as item()?, $query as string, $options as object()?) as element(s:sparql)", "description" : "

    \n This function sends a SPARQL SELECT or ASK query to an endpoint and returns the query response as SPARQL XML format element.\n If the endpoint fails to deliver SPARQL XML result format this function will try to convert the results to XML if possible.\n

    \n

    Link to the specification of the result format at W3C: SPARQL Query Results XML Format

    \n

    \n

      \n
    • The default-graph-uri and named-graph-uri properties of the options object may be used to pass default graph URIs or named graph URIs to the endpoint.
    • \n
    • The method property of the options object may be used to set the request method to be used. GET will be used as default.
    • \n
    • The format property of the options object will be ignored. \"application/sparql-results+xml\" will be requested as result format.
    • \n
    \n

    \n", "summary" : "

    \n This function sends a SPARQL SELECT or ASK query to an endpoint and returns the query response as SPARQL XML format element.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "config", "type" : "item()", "occurrence" : "?", "description" : "
    The name of the credentials to use as string or a config object as described in the module description.
    " }, { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL SELECT or ASK query as string.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An optional options object as described in the module description.
    " } ], "returns" : { "type" : "element(s:sparql)", "description" : "The query result in SPARQL XML format." }, "errors" : [ "sparql:INVALID-RESPONSE-TYPE if the response format cannot be handled by this function", "sparql:ERROR if any http or endpoint error occurs", "sparql:INVALID-PARAMETER invalid option specification", "sparql:CREDENTIALS-NOT-FOUND credential information not found", "sparql:CREDENTIALS-INVALID credential information not valid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "query", "qname" : "sparql:query", "signature" : "($query as string) as object()", "description" : "

    \n This function sends a SPARQL query to an endpoint and directly returns the corresponding HTTP response.\n The default datasource for SPARQL will be used.\n

    \n", "summary" : "

    \n This function sends a SPARQL query to an endpoint and directly returns the corresponding HTTP response.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL query as string. May be any kind of query but not an update.
    " } ], "returns" : { "type" : "object()", "description" : "The endpoints response. This function returns the plain response object from the http-client." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "query", "qname" : "sparql:query", "signature" : "($query as string, $options as object()?) as object()", "description" : "

    \n This function sends a SPARQL query to an endpoint and directly returns the corresponding HTTP response.\n The default datasource for SPARQL will be used.\n

    \n

    \n

      \n
    • The default-graph-uri and named-graph-uri properties of the options object may be used to pass default graph URIs or named graph URIs to the endpoint.
    • \n
    • The method property of the options object may be used to set the request method to be used. GET will be used as default.
    • \n
    • The format property of the options object may be used to request a specific result format. XML will be used as default. However, note that this function does not interpret the result.
    • \n
    \n

    \n", "summary" : "

    \n This function sends a SPARQL query to an endpoint and directly returns the corresponding HTTP response.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL query as string. May be any kind of query but not an update.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An optional options object as described in the module description.
    " } ], "returns" : { "type" : "object()", "description" : "The endpoints response. This function returns the plain response object from the http-client." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "query", "qname" : "sparql:query", "signature" : "($config as item()?, $query as string, $options as object()?) as object()", "description" : "

    \n This function sends a SPARQL query to an endpoint and directly returns the corresponding HTTP response.\n

    \n

    \n

      \n
    • The default-graph-uri and named-graph-uri properties of the options object may be used to pass default graph URIs or named graph URIs to the endpoint.
    • \n
    • The method property of the options object may be used to set the request method to be used. GET will be used as default.
    • \n
    • The format property of the options object may be used to request a specific result format. XML will be used as default. However, note that this function does not interpret the result.
    • \n
    \n

    \n", "summary" : "

    \n This function sends a SPARQL query to an endpoint and directly returns the corresponding HTTP response.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "config", "type" : "item()", "occurrence" : "?", "description" : "
    The name of the credentials to use as string or a config object as described in the module description.
    " }, { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A SPARQL query as string. May be any kind of query but not an update.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An optional options object as described in the module description.
    " } ], "returns" : { "type" : "object()", "description" : "The endpoints response. This function returns the plain response object from the http-client." }, "errors" : [ "sparql:INVALID-PARAMETER invalid option specification", "sparql:CREDENTIALS-NOT-FOUND credential information not found", "sparql:CREDENTIALS-INVALID credential information not valid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "update", "qname" : "sparql:update", "signature" : "($update-statement as string) as object()", "description" : "

    \n This function sends a SPARQL update statement to an endpoint and directly returns the corresponding HTTP response.\n The default datasource for SPARQL will be used.\n

    \n", "summary" : "

    \n This function sends a SPARQL update statement to an endpoint and directly returns the corresponding HTTP response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "update-statement", "type" : "string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "object()", "description" : "The endpoints response. This function returns the plain response object from the http-client." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "update", "qname" : "sparql:update", "signature" : "($update-statement as string, $options as object()?) as object()", "description" : "

    \n This function sends a SPARQL update statement to an endpoint and directly returns the corresponding HTTP response.\n The default datasource for SPARQL will be used.\n

    \n

    \n

      \n
    • The using-graph-uri and using-named-graph-uri properties of the options object may be used to pass graph URIs or named graph URIs to the endpoint.
    • \n
    • The method property of the options object may be used to set the request method to be used. POST-URLENCODED will be used as default.
    • \n
    • The format property of the options object may be used to request a specific result format. XML will be used as default. However, note that this function does not interpret the result.
    • \n
    \n

    \n", "summary" : "

    \n This function sends a SPARQL update statement to an endpoint and directly returns the corresponding HTTP response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "update-statement", "type" : "string", "occurrence" : null, "description" : "" }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An optional options object as described in the module description.
    " } ], "returns" : { "type" : "object()", "description" : "The endpoints response. This function returns the plain response object from the http-client." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "update", "qname" : "sparql:update", "signature" : "($config as item()?, $update-statement as string, $options as object()?) as object()", "description" : "

    \n This function sends a SPARQL update statement to an endpoint and directly returns the corresponding HTTP response.\n

    \n

    \n

      \n
    • The using-graph-uri and using-named-graph-uri properties of the options object may be used to pass graph URIs or named graph URIs to the endpoint.
    • \n
    • The method property of the options object may be used to set the request method to be used. POST-URLENCODED will be used as default.
    • \n
    • The format property of the options object may be used to request a specific result format. XML will be used as default. However, note that this function does not interpret the result.
    • \n
    \n

    \n", "summary" : "

    \n This function sends a SPARQL update statement to an endpoint and directly returns the corresponding HTTP response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "config", "type" : "item()", "occurrence" : "?", "description" : "
    The name of the credentials to use as string or a config object as described in the module description.
    " }, { "name" : "update-statement", "type" : "string", "occurrence" : null, "description" : "" }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An optional options object as described in the module description.
    " } ], "returns" : { "type" : "object()", "description" : "The endpoints response. This function returns the plain response object from the http-client." }, "errors" : [ "sparql:INVALID-PARAMETER invalid option specification", "sparql:CREDENTIALS-NOT-FOUND credential information not found", "sparql:CREDENTIALS-INVALID credential information not valid" ] } ], "variables" : [ { "name" : "sparql:CREDENTIALS-CATEGORY", "type" : "string", "description" : " This variable represents the category of the datasource.\n" }, { "name" : "sparql:METHOD-GET", "type" : "string", "description" : " This variable represents the request method using HTTP GET requests. May be used for the method property of the options object.\n" }, { "name" : "sparql:METHOD-POST-URLENCODED", "type" : "string", "description" : " This variable represents the request method using HTTP POST with URL-encoded parameters. May be used for the method property of the options object.\n" }, { "name" : "sparql:METHOD-POST-SPARQL", "type" : "string", "description" : " This variable represents the request method using HTTP POST with the application/sparql-query content type. May be used for the method property of the options object.\n" }, { "name" : "sparql:FORMAT-XML", "type" : "string", "description" : " This variable represents the SPARQL XML result format.May be used for the format property of the options object.\n" }, { "name" : "sparql:FORMAT-JSON", "type" : "string", "description" : " This variable represents the SPARQL JSON result format.May be used for the format property of the options object.\n" }, { "name" : "sparql:FORMAT-RDF", "type" : "string", "description" : " This variable represents the RDF+XML result format.May be used for the format property of the options object.\n" }, { "name" : "sparql:FORMAT-CSV", "type" : "string", "description" : " This variable represents the CSV result format.May be used for the format property of the options object.\n" }, { "name" : "sparql:FORMAT-TSV", "type" : "string", "description" : " This variable represents the TSV result format.May be used for the format property of the options object.\n" }, { "name" : "sparql:FORMAT-ANY", "type" : "string", "description" : " This variable represents any result format. May be used for the format property of the options object to not specify a requested format.\n" } ] }, "http://api.28.io/dispatcher" : { "ns" : "http://api.28.io/dispatcher", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://api.28.io/browserview", "prefix" : "browserview" }, { "uri" : "http://api.28.io/csvview", "prefix" : "csvview" }, { "uri" : "http://api.28.io/dispatcher", "prefix" : "dispatcher" }, { "uri" : "http://api.28.io/functions", "prefix" : "functions" }, { "uri" : "http://api.28.io/model", "prefix" : "model" }, { "uri" : "http://zorba.io/modules/xml", "prefix" : "parse-xml" }, { "uri" : "http://www.zorba-xquery.com/schemas/pul", "prefix" : "pul" }, { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "req" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "response" }, { "uri" : "http://www.zorba-xquery.com/schemas/xdm", "prefix" : "xdm" }, { "uri" : "http://api.28.io/xdmview", "prefix" : "xdmview" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "restapi", "qname" : "dispatcher:restapi", "signature" : "()", "description" : " Main function for the collection browser. May be called from a handler function.\n Uses the call URL to determine which page needs to be returned.\n The URL for the initial page needs to end with /index\n", "summary" : "

    Main function for the collection browser.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "the requested page of the collection browser" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/store/static/collections/ddl" : { "ns" : "http://zorba.io/modules/store/static/collections/ddl", "description" : " This modules defines a set of functions for managing collections that are\n declared in the prolog of a module.\n For example, it provides functions to create, delete, or introspect\n collections.\n

    \n This module is part of Zorba's XQuery Data\n Definition Facility. All the collections managed by this module\n have to be pre-declared in the prolog of a module. Please refer to the\n general documentation\n for more information and examples.\n", "sees" : [ "Data Lifecycle", "XQuery Data Definition Facility", "http://zorba.io/modules/store/static/collections/dml", "http://zorba.io/modules/store/static/indexes/ddl", "http://zorba.io/modules/store/static/indexes/dml", "http://zorba.io/modules/store/static/integrity-constraints/ddl", "http://zorba.io/modules/store/static/integrity-constraints/dml", "http://zorba.io/errors" ], "authors" : [ "Nicolae Brinza, Matthias Brantner, David Graf, Till Westmann, Markos Zaharioudakis" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/store/static/collections/ddl", "prefix" : "cddl" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "available-collections", "qname" : "cddl:available-collections", "signature" : "() as xs:QName* external", "description" : " Gets the QNames of the collections that have been statically declared and\n are available, if any.\n", "summary" : "

    Gets the QNames of the collections that have been statically declared and\n are available, if any.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName*", "description" : "A sequence comprising one QName for each statically declared and available collection or an emtpy sequence if no such collections are available." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "create", "qname" : "cddl:create", "signature" : "($name as xs:QName) external", "description" : " Creates a collection.\n", "summary" : "

    Creates a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The of the collection to create.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, creates a collection with the given name." }, "errors" : [ "zerr:ZDDY0001 if $name is not equal to any of the declared collections in the static context.", "zerr:ZDDY0002 if a collection with $name already exists." ] }, { "isDocumented" : true, "arity" : 2, "name" : "create", "qname" : "cddl:create", "signature" : "($name as xs:QName, $content as item()*) external", "description" : " Creates a collection and adds the given sequence as content to the new\n collection.\n", "summary" : "

    Creates a collection and adds the given sequence as content to the new\n collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to create.
    " }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequences of items (nodes or JSON items) to be added to the new collection.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, creates a collection with the given name and inserts the given items into it." }, "errors" : [ "zerr:ZDDY0001 if $name is not equal to any of the declared collections in the static context.", "zerr:ZDDY0002 if a collection with $name already exists.", "zerr:ZDTY0001 if $content does not match the expected type declared by the collection according to the rules for SequenceType Matching." ] }, { "isDocumented" : true, "arity" : 0, "name" : "declared-collections", "qname" : "cddl:declared-collections", "signature" : "() as xs:QName* external", "description" : " Gets the collections that have been declared in the prolog of the static\n context.\n", "summary" : "

    Gets the collections that have been declared in the prolog of the static\n context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName*", "description" : "A sequence of QNames, one for each collection created in the static context, or an emtpy sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "delete", "qname" : "cddl:delete", "signature" : "($name as xs:QName) external", "description" : " Deletes a collection.\n", "summary" : "

    Deletes a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The collection to delete.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, deletes the collection with the given name." }, "errors" : [ "zerr:ZDDY0001 if $name is not equal to any of the declared collections in the static context.", "zerr:ZDDY0003 if the collection identified by $name is not available.", "zerr:ZDDY0013 if the domain or key expression of any of the available indexes access the collection having $name.", "zerr:ZDDY0015 if any of the in-scope variables references an item that belongs to the collection having $name" ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-available-collection", "qname" : "cddl:is-available-collection", "signature" : "($name as xs:QName) as xs:boolean external", "description" : " Gets whether a collection is statically declared and available.\n", "summary" : "

    Gets whether a collection is statically declared and available.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to check.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the collection was statically declared and is available; false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-declared-collection", "qname" : "cddl:is-declared-collection", "signature" : "($name as xs:QName) as xs:boolean external", "description" : " Gers whether a collection was declared in the prolog of the static context.\n", "summary" : "

    Gers whether a collection was declared in the prolog of the static context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to check.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the collection was declared; false otherwise." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/math" : { "ns" : "http://www.28msec.com/modules/math", "description" : " The functions in this module perform trigonometric and other mathematical\n calculations on double values.\n For a more detailed description of the semantics of each function, please\n refer to \n Trigonometric and exponential functions.\n", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xpath-functions/math", "prefix" : "fnmath" }, { "uri" : "http://www.28msec.com/modules/math", "prefix" : "math" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "acos", "qname" : "math:acos", "signature" : "($arg as double?) as double?", "description" : " Returns the arc cosine of the argument, the result being in the range zero to +π radians.\n", "summary" : "

    Returns the arc cosine of the argument, the result being in the range zero to +π radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "asin", "qname" : "math:asin", "signature" : "($arg as double?) as double?", "description" : " Returns the arc sine of the argument, the result being in the range -π/2 to +π/2 radians.\n", "summary" : "

    Returns the arc sine of the argument, the result being in the range -π/2 to +π/2 radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "atan", "qname" : "math:atan", "signature" : "($arg as double?) as double?", "description" : " Returns the arc tangent of the argument, the result being in the range -π/2 to +π/2 radians.\n", "summary" : "

    Returns the arc tangent of the argument, the result being in the range -π/2 to +π/2 radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "atan2", "qname" : "math:atan2", "signature" : "($y as double, $x as double) as double", "description" : " Returns the angle in radians subtended at the origin by the point on a plane with\n coordinates (x, y) and the positive x-axis, the result being in the range -π to +π.\n", "summary" : "

    Returns the angle in radians subtended at the origin by the point on a plane with\n coordinates (x, y) and the positive x-axis, the result being in the range -π to +π.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "y", "type" : "double", "occurrence" : null, "description" : "" }, { "name" : "x", "type" : "double", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "double", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "cos", "qname" : "math:cos", "signature" : "($theta as double?) as double?", "description" : " Returns the cosine of the argument, expressed in radians.\n", "summary" : "

    Returns the cosine of the argument, expressed in radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "theta", "type" : "double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "exp", "qname" : "math:exp", "signature" : "($arg as double?) as double?", "description" : " Returns the value of ex.\n", "summary" : "

    Returns the value of ex.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "exp10", "qname" : "math:exp10", "signature" : "($arg as double?) as double?", "description" : " Returns the value of 10x.\n", "summary" : "

    Returns the value of 10x.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "log", "qname" : "math:log", "signature" : "($arg as double?) as double?", "description" : " Returns the natural logarithm of the argument.\n", "summary" : "

    Returns the natural logarithm of the argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "log10", "qname" : "math:log10", "signature" : "($arg as double?) as double?", "description" : " Returns the base-ten logarithm of the argument.\n", "summary" : "

    Returns the base-ten logarithm of the argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "pi", "qname" : "math:pi", "signature" : "() as double", "description" : " Returns an approximation to the mathematical constant π.\n", "summary" : "

    Returns an approximation to the mathematical constant π.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "double", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "pow", "qname" : "math:pow", "signature" : "($x as double?, $y) as double?", "description" : " Returns the result of raising the first argument to the power of the second.\n", "summary" : "

    Returns the result of raising the first argument to the power of the second.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "x", "type" : "double", "occurrence" : "?", "description" : "" }, { "name" : "y", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sin", "qname" : "math:sin", "signature" : "($theta as double?) as double?", "description" : " Returns the sine of the argument, expressed in radians.\n", "summary" : "

    Returns the sine of the argument, expressed in radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "theta", "type" : "double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sqrt", "qname" : "math:sqrt", "signature" : "($arg as double?) as double?", "description" : " Returns the non-negative square root of the argument.\n", "summary" : "

    Returns the non-negative square root of the argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "double?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "tan", "qname" : "math:tan", "signature" : "($theta as double?) as double?", "description" : " Returns the tangent of the argument, expressed in radians.\n", "summary" : "

    Returns the tangent of the argument, expressed in radians.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "theta", "type" : "double", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "double?", "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/data-cleaning/normalization" : { "ns" : "http://zorba.io/modules/data-cleaning/normalization", "description" : "

    This library module provides data normalization functions for processing calendar dates,\n temporal values, currency values, units of measurement, location names and postal addresses.\n These functions are particularly useful for converting different data representations into cannonical formats.

    \n

    The logic contained in this module is not specific to any particular XQuery implementation.

    \n", "sees" : [ ], "authors" : [ "Bruno Martins and Diogo Simões" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.zorba-xquery.com/modules/http-client", "prefix" : "http" }, { "uri" : "http://zorba.io/modules/data-cleaning/normalization", "prefix" : "normalization" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "normalize-address", "qname" : "normalization:normalize-address", "signature" : "($addr as xs:string*) as xs:string*", "description" : "

    Uses an address normalization Web service to convert a postal address given as input into a\n cannonical representation format.

    \n", "summary" : "

    Uses an address normalization Web service to convert a postal address given as input into a\n cannonical representation format.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "addr", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings encoding an address, where each string in the sequence corresponds to a different component (e.g., street, city, country, etc.) of the address.
    " } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of strings with the address encoded in a cannonical format, where each string in the sequence corresponds to a different component (e.g., street, city, country, etc.) of the address." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "normalize-phone", "qname" : "normalization:normalize-phone", "signature" : "($addr as xs:string*) as xs:string*", "description" : "

    Uses an phone number normalization Web service to convert a phone number given as input into a\n cannonical representation.

    \n", "summary" : "

    Uses an phone number normalization Web service to convert a phone number given as input into a\n cannonical representation.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "addr", "type" : "xs:string", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "A strings with the phone number encoded in a cannonical format.

    Attention : This function is still not implemented.

    " }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "to-date", "qname" : "normalization:to-date", "signature" : "($sd as xs:string, $format as xs:string?) as xs:string", "description" : "

    Converts a given string representation of a date value into a date representation valid according\n to the corresponding XML Schema type.

    \n", "summary" : "

    Converts a given string representation of a date value into a date representation valid according\n to the corresponding XML Schema type.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "sd", "type" : "xs:string", "occurrence" : null, "description" : "
    The string representation for the date
    " }, { "name" : "format", "type" : "xs:string", "occurrence" : "?", "description" : "
    An optional parameter denoting the format used to represent the date in the string, according to a sequence of conversion specifications. In the format string, a conversion specification is introduced by '%', usually followed by a single letter or 'O' or 'E' and then a single letter. Any character in the format string that is not part of a conversion specification is interpreted literally, and the string '%%' gives '%'. The supported conversion specifications are as follows:
     '%b' Abbreviated month name in the current locale. '%B' Full month name in the current locale. '%d' Day of the month as decimal number (01-31). '%m' Month as decimal number (01-12). '%x' Date, locale-specific. '%y' Year without century (00-99). '%Y' Year with century. '%C' Century (00-99): the integer part of the year divided by 100. '%D' Locale-specific date format such as '%m/%d/%y'. '%e' Day of the month as decimal number (1-31), with a leading pace for a single-digit number. '%F' Equivalent to %Y-%m-%d (the ISO 8601 date format). '%h' Equivalent to '%b'. 
    " } ], "returns" : { "type" : "xs:string", "description" : "The date value resulting from the conversion." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "to-dateTime", "qname" : "normalization:to-dateTime", "signature" : "($sd as xs:string, $format as xs:string?) as xs:string", "description" : "

    Converts a given string representation of a dateTime value into a dateTime representation\n valid according to the corresponding XML Schema type.

    \n", "summary" : "

    Converts a given string representation of a dateTime value into a dateTime representation\n valid according to the corresponding XML Schema type.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "sd", "type" : "xs:string", "occurrence" : null, "description" : "
    The string representation for the dateTime.
    " }, { "name" : "format", "type" : "xs:string", "occurrence" : "?", "description" : "
    An optional parameter denoting the format used to represent the dateTime in the string, according to a sequence of conversion specifications. In the format string, a conversion specification is introduced by '%', usually followed by a single letter or 'O' or 'E' and then a single letter. Any character in the format string that is not part of a conversion specification is interpreted literally, and the string '%%' gives '%'. The supported conversion specifications are as follows:

     '%b' Abbreviated month name in the current locale. '%B' Full month name in the current locale. '%c' Date and time, locale-specific. '%C' Century (00-99): the integer part of the year divided by 100. '%d' Day of the month as decimal number (01-31). '%H' Hours as decimal number (00-23). '%I' Hours as decimal number (01-12). '%j' Day of year as decimal number (001-366). '%m' Month as decimal number (01-12). '%M' Minute as decimal number (00-59). '%p' AM/PM indicator in the locale. Used in conjunction with '%I' and *not* with '%H'. '%S' Second as decimal number (00-61), allowing for up to two leap-seconds. '%x' Date, locale-specific. '%X' Time, locale-specific. '%y' Year without century (00-99). '%Y' Year with century. '%z' Offset from Greenwich, so '-0900' is 9 hours west of Greenwich. '%Z' Time zone as a character string. '%D' Locale-specific date format such as '%m/%d/%y': ISO C99 says it should be that exact format. '%e' Day of the month as decimal number (1-31), with a leading pace for a single-digit number. '%F' Equivalent to %Y-%m-%d (the ISO 8601 date format). '%g' The last two digits of the week-based year (see '%V'). '%G' The week-based year (see '%V') as a decimal number. '%h' Equivalent to '%b'. '%k' The 24-hour clock time with single digits preceded by a blank. '%l' The 12-hour clock time with single digits preceded by a blank. '%r' The 12-hour clock time (using the locale's AM or PM). '%R' Equivalent to '%H:%M'. '%T' Equivalent to '%H:%M:%S'. 
    " } ], "returns" : { "type" : "xs:string", "description" : "The dateTime value resulting from the conversion." }, "errors" : [ "normalization:NOTSUPPORTED if the dateTime type is not known to the service." ] }, { "isDocumented" : true, "arity" : 2, "name" : "to-time", "qname" : "normalization:to-time", "signature" : "($sd as xs:string, $format as xs:string?) as xs:string?", "description" : "

    Converts a given string representation of a time value into a time representation valid according to\n the corresponding XML Schema type.

    \n", "summary" : "

    Converts a given string representation of a time value into a time representation valid according to\n the corresponding XML Schema type.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "sd", "type" : "xs:string", "occurrence" : null, "description" : "
    The string representation for the time.
    " }, { "name" : "format", "type" : "xs:string", "occurrence" : "?", "description" : "
    An optional parameter denoting the format used to represent the time in the string, according to a sequence of conversion specifications. In the format string, a conversion specification is introduced by '%', usually followed by a single letter or 'O' or 'E' and then a single letter. Any character in the format string that is not part of a conversion specification is interpreted literally, and the string '%%' gives '%'. The supported conversion specifications are as follows:

     '%H' Hours as decimal number (00-23). '%I' Hours as decimal number (01-12). '%M' Minute as decimal number (00-59). '%p' AM/PM indicator in the locale. Used in conjunction with '%I' and *not* with '%H'. '%S' Second as decimal number (00-61), allowing for up to two leap-seconds. '%X' Time, locale-specific. '%z' Offset from Greenwich, so '-0900' is 9 hours west of Greenwich. '%Z' Time zone as a character string. '%k' The 24-hour clock time with single digits preceded by a blank. '%l' The 12-hour clock time with single digits preceded by a blank. '%r' The 12-hour clock time (using the locale's AM or PM). '%R' Equivalent to '%H:%M'. '%T' Equivalent to '%H:%M:%S'. 
    " } ], "returns" : { "type" : "xs:string?", "description" : "The time value resulting from the conversion." }, "errors" : [ "normalization:NOTSUPPORTED if the date type is not known to the service." ] } ], "variables" : [ ] }, "http://zorba.io/modules/excel/engineering" : { "ns" : "http://zorba.io/modules/excel/engineering", "description" : " This is a library module offering the same set of functions\n defined by Microsoft Excel, under Engineering Functions.\n", "sees" : [ "Excel Documentation: Engineering Functions" ], "authors" : [ "Sorin Nasoi" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/excel/engineering", "prefix" : "excel-engineering" }, { "uri" : "http://zorba.io/modules/excel/errors", "prefix" : "excel-err" }, { "uri" : "http://zorba.io/modules/excel/math", "prefix" : "excel-math" }, { "uri" : "http://zorba.io/modules/excel/text", "prefix" : "excel-text" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "bin2dec", "qname" : "excel-engineering:bin2dec", "signature" : "($arg as xs:anyAtomicType) as xs:integer", "description" : " Converts a binary number to decimal.\n", "summary" : "

    Converts a binary number to decimal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " } ], "returns" : { "type" : "xs:integer", "description" : "A decimal representation of a number given it's binary representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not a binary representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters." ] }, { "isDocumented" : true, "arity" : 1, "name" : "bin2hex", "qname" : "excel-engineering:bin2hex", "signature" : "($arg as xs:anyAtomicType) as xs:string", "description" : " Converts a binary number to hexadecimal.\n", "summary" : "

    Converts a binary number to hexadecimal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " } ], "returns" : { "type" : "xs:string", "description" : "A hexadecimal representation of a number given it's binary representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not a binary representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters." ] }, { "isDocumented" : true, "arity" : 2, "name" : "bin2hex", "qname" : "excel-engineering:bin2hex", "signature" : "($arg as xs:anyAtomicType, $places as xs:anyAtomicType) as xs:string", "description" : " Converts a binary number to hexadecimal.\n", "summary" : "

    Converts a binary number to hexadecimal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " }, { "name" : "places", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the number of characters to use. Places is useful for padding the return value with leading 0s (zeros).
    " } ], "returns" : { "type" : "xs:string", "description" : "A hexadecimal representation of a number given it's binary representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not a binary representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters.", "excel-err:Value if provided value for $places is not numeric.", "excel-err:Num if provided value for $places is zero or negative.", "excel-err:Num if provided value for $places is too small." ] }, { "isDocumented" : true, "arity" : 1, "name" : "bin2oct", "qname" : "excel-engineering:bin2oct", "signature" : "($arg as xs:anyAtomicType) as xs:string", "description" : " Converts a binary number to octal.\n", "summary" : "

    Converts a binary number to octal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " } ], "returns" : { "type" : "xs:string", "description" : "A octal representation of a number given it's binary representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not a binary representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters." ] }, { "isDocumented" : true, "arity" : 2, "name" : "bin2oct", "qname" : "excel-engineering:bin2oct", "signature" : "($arg as xs:anyAtomicType, $places as xs:anyAtomicType) as xs:string", "description" : " Converts a binary number to octal.\n", "summary" : "

    Converts a binary number to octal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " }, { "name" : "places", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the number of characters to use. Places is useful for padding the return value with leading 0s (zeros).
    " } ], "returns" : { "type" : "xs:string", "description" : "A octal representation of a number given it's binary representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not a binary representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters.", "excel-err:Value if provided value for $places is not numeric.", "excel-err:Num if provided value for $places is zero or negative.", "excel-err:Num if provided value for $places is too small." ] }, { "isDocumented" : true, "arity" : 1, "name" : "dec2bin", "qname" : "excel-engineering:dec2bin", "signature" : "($arg as xs:anyAtomicType) as xs:string", "description" : " Converts a decimal number to binary.\n", "summary" : "

    Converts a decimal number to binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " } ], "returns" : { "type" : "xs:string", "description" : "A binary representation of a number given it's decimal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not numeric.", "excel-err:Num if provided value for $arg is smaller than -512 or bigger than 511." ] }, { "isDocumented" : true, "arity" : 2, "name" : "dec2bin", "qname" : "excel-engineering:dec2bin", "signature" : "($arg as xs:anyAtomicType, $places as xs:anyAtomicType) as xs:string", "description" : " Converts a decimal number to binary.\n", "summary" : "

    Converts a decimal number to binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " }, { "name" : "places", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the number of characters to use. Places is useful for padding the return value with leading 0s (zeros).
    " } ], "returns" : { "type" : "xs:string", "description" : "A binary representation of a number given it's decimal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not numeric.", "excel-err:Value if provided value for $places is not numeric.", "excel-err:Num if provided value for $places is zero or negative.", "excel-err:Num if provided value for $places is too small.", "excel-err:Num if provided value for $arg is smaller than -512 or bigger than 511." ] }, { "isDocumented" : true, "arity" : 1, "name" : "dec2hex", "qname" : "excel-engineering:dec2hex", "signature" : "($arg as xs:anyAtomicType) as xs:string", "description" : " Converts a decimal number to hexadecimal.\n", "summary" : "

    Converts a decimal number to hexadecimal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " } ], "returns" : { "type" : "xs:string", "description" : "A hexadecimal representation of a number given it's decimal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not numeric.", "excel-err:Num if provided value for $arg is smaller than -549755813888 or bigger than 549755813887" ] }, { "isDocumented" : true, "arity" : 2, "name" : "dec2hex", "qname" : "excel-engineering:dec2hex", "signature" : "($arg as xs:anyAtomicType, $places as xs:anyAtomicType) as xs:string", "description" : " Converts a decimal number to hexadecimal.\n", "summary" : "

    Converts a decimal number to hexadecimal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " }, { "name" : "places", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the number of characters to use. Places is useful for padding the return value with leading 0s (zeros).
    " } ], "returns" : { "type" : "xs:string", "description" : "A hexadecimal representation of a number given it's decimal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not numeric.", "excel-err:Value if provided value for $places is not numeric.", "excel-err:Num if provided value for $places is zero or negative.", "excel-err:Num if provided value for $places is too small.", "excel-err:Num if provided value for $arg is smaller than -549755813888 or bigger than 549755813887." ] }, { "isDocumented" : true, "arity" : 1, "name" : "dec2oct", "qname" : "excel-engineering:dec2oct", "signature" : "($arg as xs:anyAtomicType) as xs:string", "description" : " Converts a decimal number to octal.\n", "summary" : "

    Converts a decimal number to octal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " } ], "returns" : { "type" : "xs:string", "description" : "An octal representation of a number given it's decimal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not numeric.", "excel-err:Num if provided value for $arg is smaller than -536870912 or bigger than 536870911." ] }, { "isDocumented" : true, "arity" : 2, "name" : "dec2oct", "qname" : "excel-engineering:dec2oct", "signature" : "($arg as xs:anyAtomicType, $places as xs:anyAtomicType) as xs:string", "description" : " Converts a decimal number to octal.\n", "summary" : "

    Converts a decimal number to octal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number
    " }, { "name" : "places", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the number of characters to use. Places is useful for padding the return value with leading 0s (zeros).
    " } ], "returns" : { "type" : "xs:string", "description" : "An octal representation of a number given it's decimal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not numeric", "excel-err:Value if provided value for $places is not numeric", "excel-err:Num if provided value for $places is zero or negative", "excel-err:Num if provided value for $places is too small", "excel-err:Num if provided value for $arg is smaller than -536870912 or bigger than 536870911" ] }, { "isDocumented" : true, "arity" : 1, "name" : "hex2bin", "qname" : "excel-engineering:hex2bin", "signature" : "($arg as xs:anyAtomicType) as xs:string", "description" : " Converts a hexadecimal number to binary.\n", "summary" : "

    Converts a hexadecimal number to binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " } ], "returns" : { "type" : "xs:string", "description" : "A binary representation of a number given it's hexadecimal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not a hexadecimal representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters." ] }, { "isDocumented" : true, "arity" : 2, "name" : "hex2bin", "qname" : "excel-engineering:hex2bin", "signature" : "($arg as xs:anyAtomicType, $places as xs:anyAtomicType) as xs:string", "description" : " Converts a hexadecimal number to binary.\n", "summary" : "

    Converts a hexadecimal number to binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " }, { "name" : "places", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the number of characters to use. Places is useful for padding the return value with leading 0s (zeros).
    " } ], "returns" : { "type" : "xs:string", "description" : "A binary representation of a number given it's hexadecimal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not a hexadecimal representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters.", "excel-err:Value if provided value for $places is not numeric.", "excel-err:Num if provided value for $places is zero or negative.", "excel-err:Num if provided value for $places is too small." ] }, { "isDocumented" : true, "arity" : 1, "name" : "hex2dec", "qname" : "excel-engineering:hex2dec", "signature" : "($arg as xs:string) as xs:integer", "description" : " Converts a hexadecimal number to decimal.\n", "summary" : "

    Converts a hexadecimal number to decimal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : null, "description" : "
    the number.
    " } ], "returns" : { "type" : "xs:integer", "description" : "A decimal representation of a number given it's hexadecimal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not a hexadecimal representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters." ] }, { "isDocumented" : true, "arity" : 1, "name" : "hex2oct", "qname" : "excel-engineering:hex2oct", "signature" : "($arg as xs:anyAtomicType) as xs:string", "description" : " Converts a hexadecimal number to octal.\n", "summary" : "

    Converts a hexadecimal number to octal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " } ], "returns" : { "type" : "xs:string", "description" : "A octal representation of a number given it's hexadecimal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not a hexadecimal representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters." ] }, { "isDocumented" : true, "arity" : 2, "name" : "hex2oct", "qname" : "excel-engineering:hex2oct", "signature" : "($arg as xs:anyAtomicType, $places as xs:anyAtomicType) as xs:string", "description" : " Converts a hexadecimal number to octal.\n", "summary" : "

    Converts a hexadecimal number to octal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " }, { "name" : "places", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the number of characters to use. Places is useful for padding the return value with leading 0s (zeros).
    " } ], "returns" : { "type" : "xs:string", "description" : "A octal representation of a number given it's hexadecimal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not a hexadecimal representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters.", "excel-err:Value if provided value for $places is not numeric.", "excel-err:Num if provided value for $places is zero or negative.", "excel-err:Num if provided value for $places is too small." ] }, { "isDocumented" : true, "arity" : 1, "name" : "oct2bin", "qname" : "excel-engineering:oct2bin", "signature" : "($arg as xs:anyAtomicType) as xs:string", "description" : " Converts an octal number to binary.\n", "summary" : "

    Converts an octal number to binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " } ], "returns" : { "type" : "xs:string", "description" : "A binary representation of a number given it's octal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not an octal representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters." ] }, { "isDocumented" : true, "arity" : 2, "name" : "oct2bin", "qname" : "excel-engineering:oct2bin", "signature" : "($arg as xs:anyAtomicType, $places as xs:anyAtomicType) as xs:string", "description" : " Converts an octal number to binary.\n", "summary" : "

    Converts an octal number to binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " }, { "name" : "places", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the number of characters to use. Places is useful for padding the return value with leading 0s (zeros).
    " } ], "returns" : { "type" : "xs:string", "description" : "A binary representation of a number given it's octal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not an octal representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters.", "excel-err:Value if provided value for $places is not numeric.", "excel-err:Num if provided value for $places is zero or negative.", "excel-err:Num if provided value for $places is too small." ] }, { "isDocumented" : true, "arity" : 1, "name" : "oct2dec", "qname" : "excel-engineering:oct2dec", "signature" : "($arg as xs:anyAtomicType) as xs:integer", "description" : " Converts an octal number to decimal.\n", "summary" : "

    Converts an octal number to decimal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " } ], "returns" : { "type" : "xs:integer", "description" : "A decimal representation of a number given it's octal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not an octal representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters." ] }, { "isDocumented" : true, "arity" : 1, "name" : "oct2hex", "qname" : "excel-engineering:oct2hex", "signature" : "($arg as xs:anyAtomicType) as xs:string", "description" : " Converts an octal number to hexadecimal.\n", "summary" : "

    Converts an octal number to hexadecimal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " } ], "returns" : { "type" : "xs:string", "description" : "A hexadecimal representation of a number given it's octal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not an octal representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters." ] }, { "isDocumented" : true, "arity" : 2, "name" : "oct2hex", "qname" : "excel-engineering:oct2hex", "signature" : "($arg as xs:anyAtomicType, $places as xs:anyAtomicType) as xs:string", "description" : " Converts an octal number to hexadecimal.\n", "summary" : "

    Converts an octal number to hexadecimal.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the number.
    " }, { "name" : "places", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    is the number of characters to use. Places is useful for padding the return value with leading 0s (zeros).
    " } ], "returns" : { "type" : "xs:string", "description" : "A hexadecimal representation of a number given it's octal representation." }, "errors" : [ "excel-err:Value if provided value for $arg is not an octal representation of a number.", "excel-err:Value if provided value for $arg contains more than 10 characters.", "excel-err:Value if provided value for $places is not numeric.", "excel-err:Num if provided value for $places is zero or negative.", "excel-err:Num if provided value for $places is too small." ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/util-jvm" : { "ns" : "http://www.zorba-xquery.com/modules/util-jvm", "description" : " This module provides common functionality for modules that use java\n implementations.\n
    \n
    \n Modules using java implementations must import this module\n to specify the dependency.\n
    \n
    \n Note: Since this module has a Java library dependency a JVM is required\n to be installed on the system. For Windows: jvm.dll is required on the system\n path (usually located in \"C:\\Program Files\\Java\\jre\\bin\\client\").\n", "sees" : [ ], "authors" : [ "Cezar Andrei" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.zorba-xquery.com/modules/util-jvm", "prefix" : "util-jvm" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ ], "variables" : [ ] }, "http://www.28msec.com/modules/asynchronous-jobs" : { "ns" : "http://www.28msec.com/modules/asynchronous-jobs", "description" : "

    This module provides functionality for executing asynchronous jobs.\n There are three kinds of jobs: (1) a job for executing a (public or private)\n query of your project, (2) a job for mapping an input\n collection into an output collection, and (3) a job for shuffling the items\n of an input collection to several output collections.\n Map and Shuffle jobs are mostly used within\n the parallelism framework and are not meant to be created directly.

    \n

    Jobs that have been scheduled for execution can be referred to by\n an opaque identifier being returned by the corresponding scheduling\n function (e.g. job:execute or job:map). Specifically,\n the job's identifier can be used to retrieve the status of a job\n (e.g. job:status) or the names of its input and output collections.

    \n", "sees" : [ ], "authors" : [ "Ghislain Fourny", "Julien Ribon", "Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://zorba.io/modules/base64", "prefix" : "base64" }, { "uri" : "http://zorba.io/modules/fetch", "prefix" : "fetch" }, { "uri" : "http://www.zorba-xquery.com/modules/http-client", "prefix" : "http-client" }, { "uri" : "http://www.28msec.com/modules/asynchronous-jobs", "prefix" : "job" }, { "uri" : "http://www.28msec.com/modules/project", "prefix" : "project" }, { "uri" : "http://zorba.io/modules/random", "prefix" : "rand" }, { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "request" }, { "uri" : "http://www.28msec.com/modules/store", "prefix" : "store" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "build-map-shuffle", "qname" : "job:build-map-shuffle", "signature" : "($input-collection as xs:string, $options as object()?) as object()", "description" : "

    Builds an object describing an asynchronous job (map or shuffle).

    \n

    This object can then be sent to the scheduler.

    \n

    The $options parameter allows for the specification of properties for\n the shuffle job. Allowed options are:\n

      \n
    • kind: the kind of job (\"map\" or \"shuffle\").
    • \n
    • map-function (map jobs only): a function with any signature\n (item()* to item()*),\n and that is used to map the input collection to the output collection.
    • \n
    • shuffle-function (shuffle jobs only): a function taking an item\n and returning an integer.\n It is used to select the output collection to which each item is sent.
    • \n
    • output-collection as string (map jobs only): the name of the collection in\n which the output of the executed query is stored. If not specified,\n the result of the query will be stored in a collection withing the\n MongoDB database associated with the project. The name of the\n collection is randomly generated and starts with _28.temporary\n
    • \n
    • output-collections as array (shuffle jobs only): an array with the names of the collections in\n which the items of the input collections are shuffled. Compulsory.\n
    • \n
    • chunk-info as object: an object containing the specification of a chunk\n of the input collection. The shuffling will only occur on this chunk.\n If not specified, the entire input collection will be mapped.\n
    • \n
    • allow-streaming as boolean (map jobs only): a boolean indicating if calling the map function can\n be distributed over partitions of the input collection. If false, the map function will\n be called only once on the entire input collection. This might result\n in a cache overflow if the number of items is too big. If true,\n the input will be arbitrarily partitioned and the map function will be called for each\n partition. The size of a partition is chosen in order to be smaller than the cache size.\n The default is false.\n
    • \n
    • dependencies as array: an array containing the ids of all asynchronous jobs that must\n be completed before this job starts. This job will be hold pending until all these dependencies\n are completed.\n
    • \n
    \n

    \n", "summary" : "

    Builds an object describing an asynchronous job (map or shuffle).

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "input-collection", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the collection that the job processes.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An object specifying above options for the asynchronous job.
    " } ], "returns" : { "type" : "object()", "description" : "the id of the scheduled job, which can be used to pull for the status and results." }, "errors" : [ "err:XPTY0004 if the type of a supplied option is incorrect.", "job:JBDY0005 if the supplied function does not have a name.", "job:JBDY0006 if the supplied function is in the local namespace.", "job:JBDY0008 if the supplied input collection is not available." ] }, { "isDocumented" : true, "arity" : 1, "name" : "error", "qname" : "job:error", "signature" : "($id as xs:string) as object()?", "description" : "

    Returns the error object output by an asynchronous job, in case of a failed job.

    \n", "summary" : "

    Returns the error object output by an asynchronous job, in case of a failed job.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the asynchronous job to query.
    " } ], "returns" : { "type" : "object()?", "description" : "the error object output by the corresponding asynchronous job." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "execute", "qname" : "job:execute", "signature" : "($query as xs:string) as xs:string", "description" : "

    Schedules an asynchronous job executing the given (public or private)\n query from your project.

    \n

    The result of the query will be stored in a collection withing the\n MongoDB database associated with the project. The name of the collection\n is randomly generated and starts with _28.temporary.

    \n", "summary" : "

    Schedules an asynchronous job executing the given (public or private)\n query from your project.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "xs:string", "occurrence" : null, "description" : "
    The path of the query to execute, which must begin with /public or /private. (examples: /public/query.xq, /private/query.jq).
    " } ], "returns" : { "type" : "xs:string", "description" : "The id of the scheduled job." }, "errors" : [ "job:JBDY0003 if the supplied query path does not begin with /public or /private.", "job:JBDY0004 if the supplied query path cannot be resolved." ] }, { "isDocumented" : true, "arity" : 2, "name" : "execute", "qname" : "job:execute", "signature" : "($query as xs:string, $options as object()?) as xs:string", "description" : "

    Schedules an asynchronous job executing the given (public or private)\n query from your project.

    \n

    The $options parameter allows for the specification of properties for\n the asynchronously executed job. Allowed options are:\n

      \n
    • output-collection as string: the name of the collection in\n which the output of the executed query is stored. If not specified,\n the result of the query will be stored in a collection withing the\n MongoDB database associated with the project. The name of the\n collection is randomly generated and starts with _28.temporary\n
    • \n
    \n

    \n", "summary" : "

    Schedules an asynchronous job executing the given (public or private)\n query from your project.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "xs:string", "occurrence" : null, "description" : "
    The path of the query to execute, which must begin with /public or /private. (examples: /public/query.xq, /private/query.jq).
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An object specifying above options for the asynchronous job.
    " } ], "returns" : { "type" : "xs:string", "description" : "The id of the scheduled job." }, "errors" : [ "err:XPTY0004 if the type of a supplied option is incorrect.", "job:JBDY0003 if the supplied query path does not begin with /public or /private.", "job:JBDY0004 if the supplied query path cannot be resolved." ] }, { "isDocumented" : true, "arity" : 1, "name" : "function", "qname" : "job:function", "signature" : "($id as xs:string) as xs:string?", "description" : "

    Returns the name of the map or shuffle function used by an asynchronous job.

    \n", "summary" : "

    Returns the name of the map or shuffle function used by an asynchronous job.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the asynchronous job to query.
    " } ], "returns" : { "type" : "xs:string?", "description" : "the name of the map or shuffle function of the corresponding asynchronous job." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "get", "qname" : "job:get", "signature" : "($id as xs:string) as object()*", "description" : "

    Returns the asynchronous job associated with the supplied asynchronous job id,\n or the asynchronous jobs associated with the supplied parallel job id.

    \n

    This function is internal and should only be used by the parallelism module.

    \n", "summary" : "

    Returns the asynchronous job associated with the supplied asynchronous job id,\n or the asynchronous jobs associated with the supplied parallel job id.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the asynchronous or parallel job to query.
    " } ], "returns" : { "type" : "object()*", "description" : "the objects describing the asynchronous jobs." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "input-collection", "qname" : "job:input-collection", "signature" : "($id as xs:string) as xs:string?", "description" : "

    Returns the name of the input collection of a mapping asynchronous job.

    \n", "summary" : "

    Returns the name of the input collection of a mapping asynchronous job.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the asynchronous job to query.
    " } ], "returns" : { "type" : "xs:string?", "description" : "the name of the input collection of the corresponding asynchronous job." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "jobs", "qname" : "job:jobs", "signature" : "() as object()*", "description" : "

    Returns the ids of all jobs created by this project.

    \n", "summary" : "

    Returns the ids of all jobs created by this project.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()*", "description" : "the sequence of the ids of all jobs created so far." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "kind", "qname" : "job:kind", "signature" : "($id as xs:string) as xs:string?", "description" : "

    Returns the kind of the asynchronous job.

    \n", "summary" : "

    Returns the kind of the asynchronous job.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the asynchronous job to query.
    " } ], "returns" : { "type" : "xs:string?", "description" : "the kind of the asynchronous job." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "map", "qname" : "job:map", "signature" : "($input-collection as xs:string, $map-function as function (item()*) as item()*) as xs:string", "description" : "

    Schedules an asynchronous job mapping the input collection\n to an output collection with the specified function.

    \n

    The name of the output collection is randomly generated and\n starts with _28.temporary.

    \n", "summary" : "

    Schedules an asynchronous job mapping the input collection\n to an output collection with the specified function.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "input-collection", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the collection that the job processes.
    " }, { "name" : "map-function", "type" : "function (item()*) as item()*", "occurrence" : null, "description" : "
    The function which is run on the input collection's contents.
    " } ], "returns" : { "type" : "xs:string", "description" : "The id of the scheduled job, which can be used to pull for the status and results." }, "errors" : [ "job:JBDY0005 if the supplied function does not have a name.", "job:JBDY0006 if the supplied function is in the local namespace.", "job:JBDY0008 if the supplied input collection does not exist." ] }, { "isDocumented" : true, "arity" : 3, "name" : "map", "qname" : "job:map", "signature" : "($input-collection as xs:string, $map-function as function (item()*) as item()*, $options as object()?) as xs:string", "description" : "

    Schedules an asynchronous job mapping the input collection\n to an output collection with the specified function.

    \n

    The $options parameter allows for the specification of properties for\n the map job. Allowed options are:\n

      \n
    • output-collection as string: the name of the collection in\n which the output of the executed query is stored. If not specified,\n the result of the query will be stored in a collection withing the\n MongoDB database associated with the project. The name of the\n collection is randomly generated and starts with _28.temporary\n
    • \n
    • chunk-info as object: an object containing the specification of a chunk\n of the input collection. The mapping will only occur on this chunk.\n If not specified, the entire input collection will be mapped.\n
    • \n
    • allow-streaming as boolean: a boolean indicating if calling the map function can\n be distributed over partitions of the input collection. If false, the map function will\n be called only once on the entire input collection. This might result\n in a cache overflow if the number of items is too big. If true,\n the input will be arbitrarily partitioned and the map function will be called for each\n partition. The size of a partition is chosen in order to be smaller than the cache size.\n The default is false.\n
    • \n
    • dependencies as array: an array containing the ids of all asynchronous jobs that must\n be completed before this job starts. This job will be hold pending until all these dependencies\n are completed.\n
    • \n
    \n

    \n", "summary" : "

    Schedules an asynchronous job mapping the input collection\n to an output collection with the specified function.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "input-collection", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the collection that the job processes.
    " }, { "name" : "map-function", "type" : "function (item()*) as item()*", "occurrence" : null, "description" : "
    The function which is run on the collection's contents.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An object specifying above options for the asynchronous job.
    " } ], "returns" : { "type" : "xs:string", "description" : "the id of the scheduled job, which can be used to pull for the status and results." }, "errors" : [ "err:XPTY0004 if the type of a supplied option is incorrect.", "job:JBDY0005 if the supplied function does not have a name.", "job:JBDY0006 if the supplied function is in the local namespace.", "job:JBDY0008 if the supplied input collection does not exist." ] }, { "isDocumented" : true, "arity" : 1, "name" : "output-collection", "qname" : "job:output-collection", "signature" : "($id as xs:string) as xs:string?", "description" : "

    Returns the name of the output collection of a mapping or executing asynchronous job.

    \n", "summary" : "

    Returns the name of the output collection of a mapping or executing asynchronous job.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the asynchronous job to query.
    " } ], "returns" : { "type" : "xs:string?", "description" : "the name of the output collection of the corresponding asynchronous job." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "output-collections", "qname" : "job:output-collections", "signature" : "($id as xs:string) as xs:string*", "description" : " Returns the name of the output collections of a shuffle asynchronous job.\n", "summary" : "

    Returns the name of the output collections of a shuffle asynchronous job.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "the name of the output collections of the corresponding asynchronous job." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "properties", "qname" : "job:properties", "signature" : "($id as xs:string) as object()", "description" : "

    Returns the properties of an asynchronous job as an object with the following\n fields:

    \n
      \n
    • accessed: the time at which the job was last accessed.
    • \n
    • completed: the time at which the job was completed.
    • \n
    • created: the time at which the job was created.
    • \n
    • lock-acquired: the time at which a processing lock was taken on the job.
    • \n
    • status: the status of the job. One of pending, in progress,\n completed, failed, timed out.
    • \n
    • error: An object containing error information in case of failure.
    • \n
    \n", "summary" : "

    Returns the properties of an asynchronous job as an object with the following\n fields: \n \n accessed : the time at which the job was last accessed.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the asynchronous job to query.
    " } ], "returns" : { "type" : "object()", "description" : "the time at which the corresponding asynchronous job was last accessed." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "query-name", "qname" : "job:query-name", "signature" : "($id as xs:string) as xs:string?", "description" : "

    Returns the name of the query executed by an executing asynchronous job.

    \n", "summary" : "

    Returns the name of the query executed by an executing asynchronous job.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "id", "type" : "xs:string", "occurrence" : null, "description" : "
    the id of the asynchronous job to query.
    " } ], "returns" : { "type" : "xs:string?", "description" : "the name of the query executed by the corresponding asynchronous job." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "schedule", "qname" : "job:schedule", "signature" : "($jobs as object()*) as object()*", "description" : "

    Sends jobs to the job queue.

    \n

    This function is internal and should only be used by this and the parallelism module.

    \n", "summary" : "

    Sends jobs to the job queue.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "jobs", "type" : "object()", "occurrence" : "*", "description" : "
    The job to send, as generated by job:build-map-shuffle().
    " } ], "returns" : { "type" : "object()*", "description" : "Objects containing the new ids." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "shuffle", "qname" : "job:shuffle", "signature" : "($input-collection as xs:string, $shuffle-function as function (item()) as xs:integer, $options as object()?) as xs:string", "description" : "

    Schedules an asynchronous job shuffling the items of the input collections to output collections\n using the specified shuffle function.

    \n

    The $options parameter allows for the specification of properties for\n the shuffle job. Allowed options are:\n

      \n
    • output-collections as array: an array with the names of the collections in\n which the items of the input collections are shuffled. Compulsory.\n
    • \n
    • chunk-info as object: an object containing the specification of a chunk\n of the input collection. The shuffling will only occur on this chunk.\n If not specified, the entire input collection will be mapped.\n
    • \n
    • dependencies as array: an array containing the ids of all asynchronous jobs that must\n be completed before this job starts. This job will be hold pending until all these dependencies\n are completed.\n
    • \n
    \n

    \n", "summary" : "

    Schedules an asynchronous job shuffling the items of the input collections to output collections\n using the specified shuffle function.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "input-collection", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the collection that the job processes.
    " }, { "name" : "shuffle-function", "type" : "function (item()) as xs:integer", "occurrence" : null, "description" : "" }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    An object specifying above options for the asynchronous job.
    " } ], "returns" : { "type" : "xs:string", "description" : "the id of the scheduled job, which can be used to pull for the status and results." }, "errors" : [ "err:XPTY0004 if the type of a supplied option is incorrect.", "job:JBDY0005 if the supplied function does not have a name.", "job:JBDY0006 if the supplied function is in the local namespace.", "job:JBDY0008 if the supplied input collection does not exist." ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/datetime" : { "ns" : "http://www.28msec.com/modules/datetime", "description" : " This modules contains function that operate on items of type date, time,\n dateTime, and duration.\n

    The module is always imported so you don't need to import it explicitly.\n Also, you don't need to fully qualify a function to invoke it.

    \n", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.28msec.com/modules/datetime", "prefix" : "datetime" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "adjust-date-to-timezone", "qname" : "datetime:adjust-date-to-timezone", "signature" : "($arg as date?) as date?", "description" : " Adjusts a date value to the implicit timezone.\n", "summary" : "

    Adjusts a date value to the implicit timezone.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "date", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "date?", "description" : "the date in the implicit timezone that contains the starting instant of the supplied date. For a detailed description of the semantics of this function, please see adjust-date-to-timezone." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "adjust-date-to-timezone", "qname" : "datetime:adjust-date-to-timezone", "signature" : "($arg as date?, $timezone as dayTimeDuration?) as date?", "description" : " Adjusts a date value to a specific timezone, or to no timezone at all.\n", "summary" : "

    Adjusts a date value to a specific timezone, or to no timezone at all.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "date", "occurrence" : "?", "description" : "" }, { "name" : "timezone", "type" : "dayTimeDuration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "date?", "description" : "the date in the target timezone that contains the starting instant of the supplied date.
    • adjust-date-to-timezone(date(\"2002-03-07\"), dayTimeDuration(\"-PT10H\")) returns date(\"2002-03-06-10:00\").
    • adjust-date-to-timezone(date(\"2002-03-07-07:00\"), ()) returns date(\"2002-03-07\").
    For a detailed description of the semantics of this function, please see adjust-date-to-timezone" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "adjust-dateTime-to-timezone", "qname" : "datetime:adjust-dateTime-to-timezone", "signature" : "($arg as dateTime?) as dateTime", "description" : " Adjusts a dateTime value to the implicit timezone.\n", "summary" : "

    Adjusts a dateTime value to the implicit timezone.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "dateTime", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "dateTime", "description" : "the dateTime in the implicit timezone. For a detailed description of the semantics of this function, please see adjust-dateTime-to-timezone" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "adjust-dateTime-to-timezone", "qname" : "datetime:adjust-dateTime-to-timezone", "signature" : "($arg as dateTime?, $timezone as dayTimeDuration?) as dateTime", "description" : " Adjusts a dateTime value to the specified timezone, or to no timezone at all.\n", "summary" : "

    Adjusts a dateTime value to the specified timezone, or to no timezone at all.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "dateTime", "occurrence" : "?", "description" : "" }, { "name" : "timezone", "type" : "dayTimeDuration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "dateTime", "description" : "the dateTime in the specified timezone.
    • adjust-dateTime-to-timezone(dateTime('2002-03-07T10:00:00-07:00'), dayTimeDuration(\"-PT10H\")) returns dateTime('2002-03-07T07:00:00-10:00').
    • adjust-dateTime-to-timezone(dateTime('2002-03-07T10:00:00'), ()) returns dateTime('2002-03-07T10:00:00').
    For a detailed description of the semantics of this function, please see adjust-dateTime-to-timezone" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "adjust-time-to-timezone", "qname" : "datetime:adjust-time-to-timezone", "signature" : "($arg as time?) as time?", "description" : " Adjusts a time value to an implicit timezone.\n", "summary" : "

    Adjusts a time value to an implicit timezone.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "time", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "time?", "description" : "the time in the implicit timezone. For a detailed description of the semantics of this function, please see adjust-time-to-timezone" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "adjust-time-to-timezone", "qname" : "datetime:adjust-time-to-timezone", "signature" : "($arg as time?, $timezone as dayTimeDuration?) as time?", "description" : " Adjusts a time value to a specific timezone, or to no timezone at all.\n", "summary" : "

    Adjusts a time value to a specific timezone, or to no timezone at all.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "time", "occurrence" : "?", "description" : "" }, { "name" : "timezone", "type" : "dayTimeDuration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "time?", "description" : "the time in the specified timezone.
    • adjust-time-to-timezone(time(\"10:00:00\"), dayTimeDuration(\"-PT10H\")) returns time(\"07:00:00-10:00\").
    • adjust-time-to-timezone(time(\"10:00:00-07:00\"), ()) returns time(\"10:00:00\").
    For a detailed description of the semantics of this function, please see adjust-time-to-timezone" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "current-date", "qname" : "datetime:current-date", "signature" : "() as date external", "description" : " Returns the current date.\n For a detailed description of the semantics of this function, please see\n current-date\n", "summary" : "

    Returns the current date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "date", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "current-dateTime", "qname" : "datetime:current-dateTime", "signature" : "() as dateTimeStamp external", "description" : " Returns the current dateTime.\n For a detailed description of the semantics of this function, please see\n current-dateTime\n", "summary" : "

    Returns the current dateTime.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "dateTimeStamp", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "current-time", "qname" : "datetime:current-time", "signature" : "() as time external", "description" : " Returns the current time.\n For a detailed description of the semantics of this function, please see\n current-time\n", "summary" : "

    Returns the current time.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "time", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "dateTime", "qname" : "datetime:dateTime", "signature" : "($arg1 as date?, $arg2 as time?) as dateTime?", "description" : " Returns a dateTime value created by combining a date and a time.\n", "summary" : "

    Returns a dateTime value created by combining a date and a time.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "date", "occurrence" : "?", "description" : "" }, { "name" : "arg2", "type" : "time", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "dateTime?", "description" : "the dateTime value created by combinding the given date and time.
    • dateTime(date(\"1999-12-31\"), time(\"12:00:00\")) returns dateTime(\"1999-12-31T12:00:00\").
    For a detailed description of the semantics of this function, please see dateTime" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "day-from-date", "qname" : "datetime:day-from-date", "signature" : "($arg as date?) as integer?", "description" : " Returns the day component of a date.\n", "summary" : "

    Returns the day component of a date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "date", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the day component of the given date.
    • day-from-date(date(\"1999-05-31-05:00\")) returns 31.
    For a detailed description of the semantics of this function, please see day-from-date" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "day-from-dateTime", "qname" : "datetime:day-from-dateTime", "signature" : "($arg as dateTime?) as integer?", "description" : " Returns the day component of a dateTime.\n", "summary" : "

    Returns the day component of a dateTime.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "dateTime", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the day component of the given dateTime.
    • day-from-dateTime(dateTime(\"1999-12-31T20:00:00-05:00\")) returns 31.
    For a detailed description of the semantics of this function, please see day-from-dateTime" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "days-from-duration", "qname" : "datetime:days-from-duration", "signature" : "($arg as duration?) as integer?", "description" : " Returns the number of days in a duration.\n", "summary" : "

    Returns the number of days in a duration.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "duration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the number of days in the given duration.
    • days-from-duration(dayTimeDuration(\"P3DT55H\")) returns 5.
    For a detailed description of the semantics of this function, please see days-from-duration" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "format-date", "qname" : "datetime:format-date", "signature" : "($value as date?, $picture as string) as string?", "description" : " Returns a string containing a date value formatted for display.\n", "summary" : "

    Returns a string containing a date value formatted for display.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "date", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "string?", "description" : "the string formatted according to the given picture. The following examples assume let $d := date(\"2002-12-31\") and the Gregorian calendar as the default calendar.
    • format-date($d, \"[Y0001]-[M01]-[D01]\") returns 2002-12-31.
    • format-date($d, \"[D1] [MI] [Y]\") returns 31 XII 2002.
    For a detailed description of the semantics of this function, please see format-date" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "format-date", "qname" : "datetime:format-date", "signature" : "($value as date?, $picture as string, $language as string?, $calendar as string?, $place as string?) as string?", "description" : " Returns a string containing a date value formatted for display.\n", "summary" : "

    Returns a string containing a date value formatted for display.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "date", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "string", "occurrence" : null, "description" : "" }, { "name" : "language", "type" : "string", "occurrence" : "?", "description" : "" }, { "name" : "calendar", "type" : "string", "occurrence" : "?", "description" : "" }, { "name" : "place", "type" : "string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "string?", "description" : "the string formatted according to the given picture. The following examples assume let $d := date(\"2002-12-31\") and the Gregorian calendar as the default calendar.
    • format-date($d, \"[YWw]\", \"en\", (), ()) returns Two Thousand and Three.
    • format-date($d, \"[D] [MNn], [Y]\", \"de\", (), ()) returns 31 Dezember, 2002.
    • format-date($d, \"[D\\u0E51] [Mn] [Y\\u0E51]\", \"th\", \"BE\", ()) returns ๓๑ ธันวาคม ๒๐๐๒.
    For a detailed description of the semantics of this function, please see format-date" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "format-dateTime", "qname" : "datetime:format-dateTime", "signature" : "($value as dateTime?, $picture as string) as string?", "description" : " Returns a string containing a dateTime value formatted for display.\n", "summary" : "

    Returns a string containing a dateTime value formatted for display.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "dateTime", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "string?", "description" : "the string formatted according to the given picture. The following examples assume let $dt := dateTime(\"2002-12-31T15:58:45\") and the Gregorian calendar as the default calendar.
    • format-dateTime($dt, \"[h].[m01][Pn] on [FNn], [D1o] [MNn]\") returns 3.58pm on Tuesday, 31st December.
    • format-dateTime($dt, \"[M01]/[D01]/[Y0001] at [H01]:[m01]:[s01]\") returns 12/31/2002 at 15:58:45.
    For a detailed description of the semantics of this function, please see format-dateTime" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 5, "name" : "format-dateTime", "qname" : "datetime:format-dateTime", "signature" : "($value as dateTime?, $picture as string, $language as string?, $calendar as string?, $place as string?) as string?", "description" : " Returns a string containing a dateTime value formatted for display.\n", "summary" : "

    Returns a string containing a dateTime value formatted for display.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "dateTime", "occurrence" : "?", "description" : "" }, { "name" : "picture", "type" : "string", "occurrence" : null, "description" : "" }, { "name" : "language", "type" : "string", "occurrence" : "?", "description" : "" }, { "name" : "calendar", "type" : "string", "occurrence" : "?", "description" : "" }, { "name" : "place", "type" : "string", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "string?", "description" : "the string formatted according to the given picture. For a detailed description of the semantics of this function, please see format-dateTime" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "hours-from-dateTime", "qname" : "datetime:hours-from-dateTime", "signature" : "($arg as dateTime?) as integer?", "description" : " Returns the hours component of a dateTime.\n", "summary" : "

    Returns the hours component of a dateTime.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "dateTime", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the hours component of the given dateTime.
    • hours-from-dateTime(dateTime(\"1999-12-31T21:20:00-05:00\")) returns 21.
    • hours-from-dateTime(adjust-dateTime-to-timezone(dateTime(\"1999-12-31T21:20:00-05:00\"), dayTimeDuration(\"PT0S\"))) returns 2.
    For a detailed description of the semantics of this function, please see hours-from-dateTime" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "hours-from-duration", "qname" : "datetime:hours-from-duration", "signature" : "($arg as duration?) as integer?", "description" : " Returns the number of hours in a duration.\n", "summary" : "

    Returns the number of hours in a duration.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "duration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the number of hours in the given duration.
    • hours-from-duration(dayTimeDuration(\"P3DT10H\")) returns 10.
    • hours-from-duration(dayTimeDuration(\"-P3DT10H\")) returns -10.
    For a detailed description of the semantics of this function, please see hours-from-duration" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "hours-from-time", "qname" : "datetime:hours-from-time", "signature" : "($arg as time?) as integer?", "description" : " Returns the hours component of a time.\n", "summary" : "

    Returns the hours component of a time.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "time", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the hours component of the given time.
    • hours-from-time(time(\"11:23:00\")) returns 11.
    • hours-from-time(time(\"24:00:00\")) returns 0.
    • hours-from-time(adjust-time-to-timezone(time(\"01:23:00+05:00\"), dayTimeDuration(\"PT0S\"))) returns 20.
    For a detailed description of the semantics of this function, please see hours-from-time" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "implicit-timezone", "qname" : "datetime:implicit-timezone", "signature" : "() as dayTimeDuration", "description" : " Returns the value of the implicit timezone property set in the platform.\n", "summary" : "

    Returns the value of the implicit timezone property set in the platform.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "dayTimeDuration", "description" : "the implicit timezone property. For a detailed description of the semantics of this function, please see implicit-timezone" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "minutes-from-dateTime", "qname" : "datetime:minutes-from-dateTime", "signature" : "($arg as dateTime?) as integer?", "description" : " Returns the minute component of a dateTime.\n", "summary" : "

    Returns the minute component of a dateTime.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "dateTime", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the minute component of the given dateTime.
    • minutes-from-dateTime(dateTime(\"1999-05-31T13:20:00-05:00\")) returns 20.
    For a detailed description of the semantics of this function, please see minutes-from-dateTime" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "minutes-from-duration", "qname" : "datetime:minutes-from-duration", "signature" : "($arg as duration?) as integer?", "description" : " Returns the number of minutes in a duration.\n", "summary" : "

    Returns the number of minutes in a duration.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "duration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the number of minutes of the given duration.
    • minutes-from-duration(dayTimeDuration(\"P3DT10H\")) returns 0.
    • minutes-from-duration(dayTimeDuration(\"-P5DT12H30M\")) returns -30.
    For a detailed description of the semantics of this function, please see minutes-from-duration" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "minutes-from-time", "qname" : "datetime:minutes-from-time", "signature" : "($arg as time?) as integer?", "description" : " Returns the minutes component of a time.\n", "summary" : "

    Returns the minutes component of a time.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "time", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the minutes component of the given time.
    • minutes-from-time(time(\"13:00:00Z\")) returns 0.
    For a detailed description of the semantics of this function, please see minutes-from-time" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "month-from-date", "qname" : "datetime:month-from-date", "signature" : "($arg as date?) as integer?", "description" : " Returns the month component of a date.\n", "summary" : "

    Returns the month component of a date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "date", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the month component of the given date.
    • month-from-date(date(\"1999-05-31-05:00\")) returns 5.
    • month-from-date(date(\"2000-01-01+05:00\")) returns 1.
    For a detailed description of the semantics of this function, please see month-from-date" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "month-from-dateTime", "qname" : "datetime:month-from-dateTime", "signature" : "($arg as dateTime?) as integer?", "description" : " Returns the month component of a dateTime.\n", "summary" : "

    Returns the month component of a dateTime.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "dateTime", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the month component of the given dateTime.
    • month-from-dateTime(dateTime(\"1999-05-31T21:20:00-05:00\")) returns 5.
    • month-from-dateTime(dateTime(\"2000-01-01T11:05:00+05:00\")) returns 1.
    For a detailed description of the semantics of this function, please see month-from-dateTime" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "months-from-duration", "qname" : "datetime:months-from-duration", "signature" : "($arg as duration?) as integer?", "description" : " Returns the number of months in a duration.\n", "summary" : "

    Returns the number of months in a duration.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "duration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the number of months in the given duration.
    • months-from-duration(yearMonthDuration(\"P20Y15M\")) returns 3.
    • months-from-duration(yearMonthDuration(\"-P20Y18M\")) returns 6.
    For a detailed description of the semantics of this function, please see months-from-duration" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "seconds-from-dateTime", "qname" : "datetime:seconds-from-dateTime", "signature" : "($arg as dateTime?) as decimal?", "description" : " Returns the seconds component of a dateTime.\n", "summary" : "

    Returns the seconds component of a dateTime.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "dateTime", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "decimal?", "description" : "the seconds component of the given dateTime.
    • seconds-from-dateTime(dateTime(\"1999-05-31T13:20:00-05:00\")) returns 0.
    For a detailed description of the semantics of this function, please see seconds-from-dateTime" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "seconds-from-duration", "qname" : "datetime:seconds-from-duration", "signature" : "($arg as duration?) as decimal?", "description" : " Returns the number of seconds in a duration.\n", "summary" : "

    Returns the number of seconds in a duration.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "duration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "decimal?", "description" : "the number of seconds in the given duration.
    • seconds-from-duration(dayTimeDuration(\"P3DT10H12.5S\")) returns 12.5.
    • seconds-from-duration(dayTimeDuration(\"-PT256S\")) returns -16.0.
    For a detailed description of the semantics of this function, please see seconds-from-duration" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "seconds-from-time", "qname" : "datetime:seconds-from-time", "signature" : "($arg as time?) as decimal?", "description" : " Returns the seconds component of a time.\n", "summary" : "

    Returns the seconds component of a time.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "time", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "decimal?", "description" : "the seconds component of the given time.
    • seconds-from-time(time(\"13:20:10.5\")) returns 10.5.
    For a detailed description of the semantics of this function, please see seconds-from-time" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "timezone-from-date", "qname" : "datetime:timezone-from-date", "signature" : "($arg as date?) as dayTimeDuration?", "description" : " Returns the timezone component of a date.\n", "summary" : "

    Returns the timezone component of a date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "date", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "dayTimeDuration?", "description" : "the timezone component of the given date.
    • timezone-from-date(date(\"1999-05-31-05:00\")) returns dayTimeDuration(\"-PT5H\").
    • timezone-from-date(date(\"2000-06-12Z\")) returns dayTimeDuration(\"PT0S\").
    For a detailed description of the semantics of this function, please see timezone-from-date" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "timezone-from-dateTime", "qname" : "datetime:timezone-from-dateTime", "signature" : "($arg as dateTime?) as dayTimeDuration?", "description" : " Returns the timezone component of a dateTime.\n", "summary" : "

    Returns the timezone component of a dateTime.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "dateTime", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "dayTimeDuration?", "description" : "the timezone component of the given dateTime.
    • timezone-from-dateTime(dateTime(\"1999-05-31T13:20:00-05:00\")) returns dayTimeDuration(\"-PT5H\").
    • timezone-from-dateTime(dateTime(\"2000-06-12T13:20:00Z\")) returns dayTimeDuration(\"PT0S\").
    For a detailed description of the semantics of this function, please see timezone-from-dateTime" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "timezone-from-time", "qname" : "datetime:timezone-from-time", "signature" : "($arg as time?) as dayTimeDuration?", "description" : " Returns the timezone component of a time.\n", "summary" : "

    Returns the timezone component of a time.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "time", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "dayTimeDuration?", "description" : "the timezone component of the given time.
    • timezone-from-time(time(\"13:20:00-05:00\")) returns dayTimeDuration(\"-PT5H\").
    • timezone-from-time(time(\"13:20:00\")) returns ().
    For a detailed description of the semantics of this function, please see timezone-from-time" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "year-from-date", "qname" : "datetime:year-from-date", "signature" : "($arg as date?) as integer?", "description" : " Returns the year component of a date.\n", "summary" : "

    Returns the year component of a date.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "date", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the year component of the given date.
    • year-from-date(date(\"2000-01-01+05:00\")) returns 2000.
    For a detailed description of the semantics of this function, please see year-from-date" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "year-from-dateTime", "qname" : "datetime:year-from-dateTime", "signature" : "($arg as dateTime?) as integer?", "description" : " Returns the year component of a dateTime.\n", "summary" : "

    Returns the year component of a dateTime.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "dateTime", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the year component of the given dateTime.
    • year-from-dateTime(dateTime(\"1999-05-31T13:20:00-05:00\")) returns 1999.
    • year-from-dateTime(dateTime(\"1999-12-31T24:00:00\")) returns 2000.
    For a detailed description of the semantics of this function, please see year-from-dateTime" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "years-from-duration", "qname" : "datetime:years-from-duration", "signature" : "($arg as duration?) as integer?", "description" : " Returns the number of years in a duration.\n", "summary" : "

    Returns the number of years in a duration.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "duration", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "integer?", "description" : "the number of years in the given duration.
    • years-from-duration(yearMonthDuration(\"P20Y15M\")) returns 21.
    • years-from-duration(yearMonthDuration(\"-P15M\")) returns -1.
    For a detailed description of the semantics of this function, please see years-from-duration" }, "errors" : [ ] } ], "variables" : [ ] }, "http://api.28.io/jdbc" : { "ns" : "http://api.28.io/jdbc", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://api.28.io/jdbc", "prefix" : "api" }, { "uri" : "http://www.28msec.com/modules/jdbc", "prefix" : "jdbc" }, { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "req" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "res" }, { "uri" : "http://www.28msec.com/modules/store", "prefix" : "store" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : false, "arity" : 0, "name" : "dispatch", "qname" : "api:dispatch", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "import", "qname" : "api:import", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "tables", "qname" : "api:tables", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/excel/information" : { "ns" : "http://zorba.io/modules/excel/information", "description" : " This is a library module offering the same set of functions\n defined by Microsoft Excel, under Information Functions.\n", "sees" : [ "Excel Documentation: Information Functions" ], "authors" : [ "Sorin Nasoi" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/excel/errors", "prefix" : "excel-err" }, { "uri" : "http://zorba.io/modules/excel/information", "prefix" : "excel-information" }, { "uri" : "http://zorba.io/modules/excel/math", "prefix" : "excel-math" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "is-blank", "qname" : "excel-information:is-blank", "signature" : "($value as xs:anyAtomicType?) as xs:boolean", "description" : " Test if the passed argument is empty of not.\n", "summary" : "

    Test if the passed argument is empty of not.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the value.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "If the value of $arg is the empty sequence, the function returns true, otherwise the function returns false." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-even", "qname" : "excel-information:is-even", "signature" : "($value as xs:anyAtomicType?) as xs:boolean", "description" : " Test is a number is even.\n", "summary" : "

    Test is a number is even.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the value.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "TRUE if number is even, FALSE if number is odd." }, "errors" : [ "excel-err:Value if provided value is not a number." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-odd", "qname" : "excel-information:is-odd", "signature" : "($value as xs:anyAtomicType?) as xs:boolean", "description" : " Test is a number is odd.\n", "summary" : "

    Test is a number is odd.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the value.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "TRUE if number is odd, FALSE if number is even." }, "errors" : [ "excel-err:Value if provided value is not a number." ] }, { "isDocumented" : true, "arity" : 1, "name" : "islogical", "qname" : "excel-information:islogical", "signature" : "($value as xs:anyAtomicType?) as xs:boolean", "description" : " Tests if the passed $value is a logical value.\n", "summary" : "

    Tests if the passed $value is a logical value.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the value.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "TRUE if $value refers to a logical value." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "isnumber", "qname" : "excel-information:isnumber", "signature" : "($value as xs:anyAtomicType?) as xs:boolean", "description" : " Tests if the passed $value is a number.\n", "summary" : "

    Tests if the passed $value is a number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the value.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "TRUE if $value refers to a number." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "istext", "qname" : "excel-information:istext", "signature" : "($value as xs:anyAtomicType?) as xs:boolean", "description" : " Tests if the passed $value is a string.\n", "summary" : "

    Tests if the passed $value is a string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the value.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "TRUE if $value refers to text." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "n", "qname" : "excel-information:n", "signature" : "($value as xs:anyAtomicType?) as xs:anyAtomicType", "description" : " Converts a $value to a number.\n", "summary" : "

    Converts a $value to a number.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the value.
    " } ], "returns" : { "type" : "xs:anyAtomicType", "description" : "A $value converted to a number." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "na", "qname" : "excel-information:na", "signature" : "() as xs:anyAtomicType", "description" : " Raises the error value #N/A.\n", "summary" : "

    Raises the error value #N/A.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:anyAtomicType", "description" : "The error value #N/A. #N/A is the error value that means \"no value is available.\"" }, "errors" : [ "excel-err:NA the purpose of this function is to raise this error" ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/image/animation" : { "ns" : "http://www.zorba-xquery.com/modules/image/animation", "description" : " This module provides functions to create animated GIF images.\n", "sees" : [ ], "authors" : [ "Daniel Thomas" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.zorba-xquery.com/modules/image/animation", "prefix" : "anim" }, { "uri" : "http://www.zorba-xquery.com/modules/image/error", "prefix" : "ierr" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 3, "name" : "create-animated-gif", "qname" : "anim:create-animated-gif", "signature" : "($images as xs:base64Binary+, $delay as xs:unsignedInt, $iterations as xs:unsignedInt) as xs:base64Binary external", "description" : " Creates an animated GIF image.\n The resulting animated GIF shows the passed images consecutively.\n It has the same width and height as the first passed image.\n", "summary" : "

    Creates an animated GIF image.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "images", "type" : "xs:base64Binary", "occurrence" : "+", "description" : "
    the image sequence
    " }, { "name" : "delay", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    the hundredths of seconds an image is shown
    " }, { "name" : "iterations", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    the amount of times all images are shown. 0 for infinite.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the animated GIF" }, "errors" : [ "ierr:IM001 one of the passed images is invalid." ] }, { "isDocumented" : true, "arity" : 4, "name" : "create-morphed-gif", "qname" : "anim:create-morphed-gif", "signature" : "($images as xs:base64Binary+, $delay as xs:unsignedInt, $iterations as xs:unsignedInt, $nr-of-morph-images as xs:unsignedInt) as xs:base64Binary external", "description" : " Creates an animated GIF image with morph effect.\n The resulting animated GIF shows the passed images consecutively with morph effect between the changes.\n It has the same width and height as the first passed image.\n", "summary" : "

    Creates an animated GIF image with morph effect.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "images", "type" : "xs:base64Binary", "occurrence" : "+", "description" : "
    the image sequence
    " }, { "name" : "delay", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    the hundredths of seconds an image is shown
    " }, { "name" : "iterations", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    the amount of times all images are shown. 0 for infinite.
    " }, { "name" : "nr-of-morph-images", "type" : "xs:unsignedInt", "occurrence" : null, "description" : "
    the number of additionally added images to create the morph effect between two passed images.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the animated GIF" }, "errors" : [ "ierr:IM001 one of the passed images is invalid." ] } ], "variables" : [ ] }, "http://28.io/modules/error" : { "ns" : "http://28.io/modules/error", "description" : "

    Applications written with Sausalito use this default error module\n if an error happens inside a Sausalito project.

    \n

    An error can occur during the run time of a Sausalito project on one\n of the following cases:

    \n
      \n
    1. If the XQuery code raises a dynamic error that is not caught in a\n try-catch block.
    2. \n
    3. If the given XQuery program is syntactically incorrect or contains\n other static errors.
    4. \n
    5. If an explicit call to fn:error() was made and the error is not\n caught in a try-catch block.
    6. \n
    7. If a request is made to a module or a function which does\n not exist.
    8. \n
    9. If any other unexpected error happens during the processing of\n the request.
    10. \n
    \n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://28.io/modules/error", "prefix" : "err" }, { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "request" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "resp" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 4, "name" : "handle", "qname" : "err:handle", "signature" : "($code as xs:QName, $description as xs:string?, $value as item()*, $stack) as item()*", "description" : "

    This is the default function that is called if an error happens.\n The default can be overridden by adding an error.xq library module\n into the Sausalito project. This module needs to declare a function\n with the same signature as the err:handle function in this module.

    \n

    The value returned by this function is sent to the client. If the\n default is overridden, the implementation is free to define all\n parameters of the response (e.g. set the corresponding HTTP status\n code or an arbitrary header).

    \n

    If the default is used, the status code is 500 if the $code QName\n is not equal to one of the status code QNames declared in HTTP module.\n Otherwise, the corresponding status code is set.

    \n", "summary" : "

    This is the default function that is called if an error happens.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "code", "type" : "xs:QName", "occurrence" : null, "description" : "
    the error code that triggered the problem as a QName
    " }, { "name" : "description", "type" : "xs:string", "occurrence" : "?", "description" : "
    a description of the error
    " }, { "name" : "value", "type" : "item()", "occurrence" : "*", "description" : "
    a potentially empty list of items that were involved in causing the error
    " }, { "name" : "stack", "type" : null, "occurrence" : null, "description" : "
    the stacktrace leading to the error as an element. For example, <stack> <call ns=\"http://www.example.com/\" localName=\"my-function\" arity=\"3\"/> </stack>
    " } ], "returns" : { "type" : "item()*", "description" : "content of the response message" }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/internal-debug" : { "ns" : "http://www.zorba-xquery.com/modules/internal-debug", "description" : " This internal module provides functions for testing error handling and\n internal function caching.\n", "sees" : [ ], "authors" : [ "Federico Cavalieri" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.zorba-xquery.com/modules/internal-debug", "prefix" : "debug" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "cpp-error", "qname" : "debug:cpp-error", "signature" : "() as empty-sequence() external", "description" : " Raises a c++ exception.\n", "summary" : "

    Raises a c++ exception.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "empty-sequence()", "description" : "empty sequence" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "cpp-exit", "qname" : "debug:cpp-exit", "signature" : "() as empty-sequence() external", "description" : " C++ exit is invoked.\n", "summary" : "

    C++ exit is invoked.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "empty-sequence()", "description" : "empty sequence" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "user-error-no-location", "qname" : "debug:user-error-no-location", "signature" : "() as empty-sequence() external", "description" : " Raises a user error without query location.\n", "summary" : "

    Raises a user error without query location.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "empty-sequence()", "description" : "empty sequence" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "user-error", "qname" : "debug:user-error", "signature" : "() as empty-sequence() external", "description" : " Raises a user error.\n", "summary" : "

    Raises a user error.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "empty-sequence()", "description" : "empty sequence" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "zorba-error", "qname" : "debug:zorba-error", "signature" : "() as empty-sequence() external", "description" : " Raises a zorba error.\n", "summary" : "

    Raises a zorba error.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "empty-sequence()", "description" : "empty sequence" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/reflection" : { "ns" : "http://zorba.io/modules/reflection", "description" : " This module provides functions to dynamically invoke functions or main modules,\n respectively. Each of the functions (invoke or eval) come in four variants depending\n whether the expression being invoked is simple, nondeterministic, updating,\n or sequential.\n", "sees" : [ ], "authors" : [ "Nicolae Brinza" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://zorba.io/modules/reflection", "prefix" : "reflection" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "eval-n", "qname" : "reflection:eval-n", "signature" : "($query as xs:string) as item()* external", "description" : " See documentation of reflection:eval() except the main module that is to\n be executed may be nondeterministc.\n", "summary" : "

    See documentation of reflection:eval() except the main module that is to\n be executed may be nondeterministc.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "xs:string", "occurrence" : null, "description" : "
    the query string to be evaluated
    " } ], "returns" : { "type" : "item()*", "description" : "the result of evaluating the query" }, "errors" : [ "whatever error the evaluated XQuery may return", "err:XQST0031 If the XQuery version of the inner program is greater than the version of the outer program." ] }, { "isDocumented" : true, "arity" : 1, "name" : "eval-s", "qname" : "reflection:eval-s", "signature" : "($query as xs:string) as item()* external", "description" : " See documentation of reflection:eval() except the main module that is to\n be executed may be sequential, i.e. may have side-effects.\n", "summary" : "

    See documentation of reflection:eval() except the main module that is to\n be executed may be sequential, i.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "xs:string", "occurrence" : null, "description" : "
    the query string to be evaluated
    " } ], "returns" : { "type" : "item()*", "description" : "the result of evaluating the query (the result is not supposed to contain any PUL)." }, "errors" : [ "whatever error the evaluated XQuery may return", "err:XQST0031 If the XQuery version of the inner program is greater than the version of the outer program." ] }, { "isDocumented" : true, "arity" : 1, "name" : "eval-u", "qname" : "reflection:eval-u", "signature" : "($query as xs:string) external", "description" : " See documentation of reflection:eval() except the main module that is to\n be executed may be updating, i.e. return a pending update list.\n", "summary" : "

    See documentation of reflection:eval() except the main module that is to\n be executed may be updating, i.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : true, "parameters" : [ { "name" : "query", "type" : "xs:string", "occurrence" : null, "description" : "
    the query string to be evaluated
    " } ], "returns" : { "type" : null, "description" : "the PUL resulting from evaluating the query" }, "errors" : [ "whatever error the evaluated XQuery may return", "err:XQST0031 If the XQuery version of the inner program is greater than the version of the outer program." ] }, { "isDocumented" : true, "arity" : 1, "name" : "eval", "qname" : "reflection:eval", "signature" : "($query as xs:string) as item()* external", "description" : " The purpose of this function is to (dynamically) execute an XQuery program\n from inside another XQuery program.

    \n The XQuery program that invokes the\n eval function will be referred to as the \"outer\" program and the XQuery\n program that is executed by the eval invocation will be referred to as\n the \"inner\" program. The function is given as a string argument.\n Typically, the outer program constructs this string dynamically,\n e.g., based on data extracted from documents and/or the values of\n external variables. The eval function treats this string as\n an XQuery main module. That is, it parses the string, compiles the\n resulting parse tree, executes the resulting execution plan, and finally\n returns the result or error (if any) to the outer program.

    \n The given XQuery program needs to be a valid according to XQuery's\n MainModule production (see \n http://www.w3.org/TR/xquery/#doc-xquery-MainModule. Please note\n that the inner pogram must at least have the XQuery version of the\n outer program [err:XQST0031].

    \n The inner program \"inherits\" the static and dynamic context of the outer\n program. Specifically, evaluation of the inner program is done in static and\n dynamic contextes that are initialized as copies of the static and dynamic\n contextes of the outer program at the place where the eval invocation appears\n at. This means that, for example, all variables that are in-scope at the place\n where the eval function is invoked from, are also in-scope inside the inner\n program and can be referenced there without having to be re-declared. On the other\n hand, declarations that appear in the prolog of the inner main module or are\n imported by the inner main module from library modules, hide their corresponding\n inherited declarations. For example, if the inner main module declares\n a variable or function with the same name as an inherited variable or function,\n the inner variable/function hides the inherited one.

    \n If the inner program declares an external variable with the same name as an\n inherited variable, the value of the inherited variable is used to initialize\n the inner external variable. If, however, an inner external variable has no\n default initializer and no corresponding inherited variable, it will remain\n uninitialized, causing the inner program to raise an error when executed.\n", "summary" : "

    The purpose of this function is to (dynamically) execute an XQuery program\n from inside another XQuery program.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query", "type" : "xs:string", "occurrence" : null, "description" : "
    the query string to be evaluated
    " } ], "returns" : { "type" : "item()*", "description" : "the result of evaluating the query" }, "errors" : [ "whatever error the evaluated XQuery may return.", "err:XQST0031 If the XQuery version of the inner program is greater than the version of the outer program." ] }, { "isDocumented" : true, "arity" : 1, "name" : "invoke-n", "qname" : "reflection:invoke-n", "signature" : "($name as xs:QName) as item()* external", "description" : " See documentation for reflection:invoke except the function that\n is to be invoked may be nondeterministic.\n", "summary" : "

    See documentation for reflection:invoke except the function that\n is to be invoked may be nondeterministic.

    ", "annotation_str" : " %an:nondeterministic %an:variadic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" }, { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "variadic", "value" : "" } ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    the QName of the function that is to be invoked
    " } ], "returns" : { "type" : "item()*", "description" : "the result that is returned by the invoked function" }, "errors" : [ "whatever error the invoked function may return" ] }, { "isDocumented" : true, "arity" : 1, "name" : "invoke-s", "qname" : "reflection:invoke-s", "signature" : "($name as xs:QName) as item()* external", "description" : " See documentation for reflection:invoke except the function that\n is to be invoked may be sequential, i.e. may have side-effects.\n", "summary" : "

    See documentation for reflection:invoke except the function that\n is to be invoked may be sequential, i.

    ", "annotation_str" : " %an:variadic %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "variadic", "value" : "" }, { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    the QName of the function that is to be invoked
    " } ], "returns" : { "type" : "item()*", "description" : "the result that is returned by the invoked function" }, "errors" : [ "whatever error the invoked function may return" ] }, { "isDocumented" : true, "arity" : 1, "name" : "invoke-u", "qname" : "reflection:invoke-u", "signature" : "($name as xs:QName) external", "description" : " See documentation for reflection:invoke-n except the function that\n is to be invoked may be updating, i.e. return a pending update list.\n", "summary" : "

    See documentation for reflection:invoke-n except the function that\n is to be invoked may be updating, i.

    ", "annotation_str" : " %an:nondeterministic %an:variadic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" }, { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "variadic", "value" : "" } ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    the QName of the function that is to be invoked
    " } ], "returns" : { "type" : null, "description" : "the result that is returned by the invoked function" }, "errors" : [ "whatever error the invoked function may return" ] }, { "isDocumented" : true, "arity" : 1, "name" : "invoke", "qname" : "reflection:invoke", "signature" : "($name as xs:QName) as item()* external", "description" : " The invoke function allows to dynamically call a function given its QName\n and parameters.

    \n It is possible to invoke a function whose name is not known\n at compilation time -- it can be computed, passed through an external\n variable, taken from a file, etc. The first parameter must always be a\n QName identifying a known function.

    \n The function is declared with the %an:variadic annotation. Hence, it allows\n for an arbitrary number of parameters. All of these parameters (except the\n first one) will be passed to the function that is called.\n
    \n Example usage :

     reflection:invoke ( xs:QName(\"fn:max\"), (1,2,3) ) 
    \n
    \n Returns
     3 
    .\n", "summary" : "

    The invoke function allows to dynamically call a function given its QName\n and parameters.

    ", "annotation_str" : " %an:variadic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "variadic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    the QName of the function that is to be invoked
    " } ], "returns" : { "type" : "item()*", "description" : "the result that is returned by the invoked function" }, "errors" : [ "whatever error the invoked function may return" ] } ], "variables" : [ ] }, "http://zorba.io/modules/hmac" : { "ns" : "http://zorba.io/modules/hmac", "description" : " This module provides functions that perform HMAC\n (hash-based message authentication code) operations.\n For example, they calculate message codes involving hash functions such\n as MD5 and various SHA variants. The result is the base64 encoded value\n of the hash. A hash may be used to verify the data integrity and\n the authenticity of a message.\n", "sees" : [ ], "authors" : [ "William Candillon, Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/hmac", "prefix" : "hmac" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 3, "name" : "compute-binary", "qname" : "hmac:compute-binary", "signature" : "($message as xs:base64Binary, $secret-key as xs:string, $hash-algo as xs:string) as xs:base64Binary external", "description" : " Calculate the HMAC for the given message and secret-key involving\n an custom hash function. Before calculating the code, the given\n base64-encoded message is base64-decoded.\n", "summary" : "

    Calculate the HMAC for the given message and secret-key involving\n an custom hash function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "message", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the message to be authenticated
    " }, { "name" : "secret-key", "type" : "xs:string", "occurrence" : null, "description" : "
    the secret key used for calculating the authentication
    " }, { "name" : "hash-algo", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:base64Binary", "description" : "the base64 encoded message authentication code" }, "errors" : [ "hash:UNSUPPORTED-ALGORITHM if the given hash algorithm is not supported" ] }, { "isDocumented" : true, "arity" : 3, "name" : "compute", "qname" : "hmac:compute", "signature" : "($message as xs:string, $secret-key as xs:string, $alg as xs:string) as xs:base64Binary external", "description" : " Calculate the HMAC for the given message and secret-key involving\n an custom hash function.\n", "summary" : "

    Calculate the HMAC for the given message and secret-key involving\n an custom hash function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "message", "type" : "xs:string", "occurrence" : null, "description" : "
    the message to be authenticated
    " }, { "name" : "secret-key", "type" : "xs:string", "occurrence" : null, "description" : "
    the secret key used for calculating the authentication
    " }, { "name" : "alg", "type" : "xs:string", "occurrence" : null, "description" : "
    The algorithm to use for the hashing operation. Supported algorithms are \"md5\", \"sha1\", and \"sha256\".
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the base64 encoded message authentication code" }, "errors" : [ "hash:UNSUPPORTED-ALGORITHM if the given hash algorithm is not supported" ] }, { "isDocumented" : true, "arity" : 2, "name" : "md5-binary", "qname" : "hmac:md5-binary", "signature" : "($message as xs:base64Binary, $secret-key as xs:string) as xs:base64Binary", "description" : " Calculate the HMAC for the given message and secret-key involving\n the MD5 hash function. Before calculating the code, the given\n base64-encoded message is base64-decoded.\n", "summary" : "

    Calculate the HMAC for the given message and secret-key involving\n the MD5 hash function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "message", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the message to be authenticated
    " }, { "name" : "secret-key", "type" : "xs:string", "occurrence" : null, "description" : "
    the secret key used for calculating the authentication
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the base64 encoded message authentication code" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "md5", "qname" : "hmac:md5", "signature" : "($message as xs:string, $secret-key as xs:string) as xs:base64Binary", "description" : " Calculate the HMAC for the given message and secret-key involving\n the MD5 hash function.\n", "summary" : "

    Calculate the HMAC for the given message and secret-key involving\n the MD5 hash function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "message", "type" : "xs:string", "occurrence" : null, "description" : "
    the message to be authenticated
    " }, { "name" : "secret-key", "type" : "xs:string", "occurrence" : null, "description" : "
    the secret key used for calculating the authentication
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the base64 encoded message authentication code" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "sha1-binary", "qname" : "hmac:sha1-binary", "signature" : "($message as xs:base64Binary, $secret-key as xs:string) as xs:base64Binary", "description" : " Calculate the HMAC for the given message and secret-key involving\n the SHA1 hash function. Before calculating the code, the given\n base64-encoded message is base64-decoded.\n", "summary" : "

    Calculate the HMAC for the given message and secret-key involving\n the SHA1 hash function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "message", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the message to be authenticated
    " }, { "name" : "secret-key", "type" : "xs:string", "occurrence" : null, "description" : "
    the secret key used for calculating the authentication
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the base64 encoded message authentication code" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "sha1", "qname" : "hmac:sha1", "signature" : "($message as xs:string, $secret-key as xs:string) as xs:base64Binary", "description" : " Calculate the HMAC for the given message and secret-key involving\n the SHA1 hash function.\n", "summary" : "

    Calculate the HMAC for the given message and secret-key involving\n the SHA1 hash function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "message", "type" : "xs:string", "occurrence" : null, "description" : "
    the message to be authenticated
    " }, { "name" : "secret-key", "type" : "xs:string", "occurrence" : null, "description" : "
    the secret key used for calculating the authentication
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the base64 encoded message authentication code" }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/sleep" : { "ns" : "http://www.28msec.com/modules/sleep", "description" : " This module provides a function to put the currently executing request\n to sleep.\n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/sleep", "prefix" : "sleep" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "millis", "qname" : "sleep:millis", "signature" : "($millis as xs:integer) as empty-sequence() external", "description" : " Puts the currently executing request to sleep.\n This function is mainly useful in development e.g. to simulate the\n effects of long-running tasks wrt. the concurrent execution of\n requests.\n Here the function is used to simulate a request that runs for 1 second\n
    \n declare $acquired := lock:try-acquire(\"my-lock\");\n if ($acquired)\n   sleep:millis(1000);\n else\n   fn:error(xs:QName(\"...\"), \"failed to acquire lock\");\n 
    \n", "summary" : "

    Puts the currently executing request to sleep.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "millis", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of milliseconds to sleep
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and returns the empty sequence" }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/cloudant" : { "ns" : "http://www.28msec.com/modules/cloudant", "description" : "

    This module provides functionality for creating, reading, updating,\n deleting and searching data in Cloudant\n databases.

    \n

    Before issuing a request to Cloudant it is mandatory to create\n a new connection through one of the connect functions.\n These functions return a connection identifier which needs to be used\n to access data in Cloudant through the other functions.

    \n

    In these functions Cloudant databases will be identified through\n their names. By default, the functions will assume that the database is owned by\n the user for which the given connection has been created.\n To specify a different database owner, most functions accept an\n $options parameter that allows a database-owner\n option to specify a different database owner for a single request.\n Moreover, when connecting, it is possible to specify the default\n database owner using the connect#3 function.

    \n

    Additional information on the Cloudant APIs can be found\n on the Cloudant website.

    \n

    Important Notice Regarding Function Determinism

    \n

    The non side-effecting functions:\n

    \n are declared deterministic, which means that their results could be cached\n when invoked multiple times with the same arguments in the same query execution.

    \n

    To not use cached results you can use the following alternative functions:\n

    \n which have been declared as being non deterministic.

    \n", "sees" : [ ], "authors" : [ "Federico Cavalieri" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/cloudant", "prefix" : "cloudant" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://zorba.io/modules/http-client", "prefix" : "http" }, { "uri" : "http://www.28msec.com/modules/maps", "prefix" : "map" }, { "uri" : "http://zorba.io/modules/random", "prefix" : "random" }, { "uri" : "http://www.zorba-xquery.com/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "all-documents-nondeterministic", "qname" : "cloudant:all-documents-nondeterministic", "signature" : "($connection as anyURI, $database as string) as object()", "description" : "

    Lists all the documents in a given database.

    \n

    This function has the same semantics as\n all-documents#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists all the documents in a given database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " } ], "returns" : { "type" : "object()", "description" : "An object listing the documents in the specified database" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 3, "name" : "all-documents-nondeterministic", "qname" : "cloudant:all-documents-nondeterministic", "signature" : "($connection as anyURI, $database as string, $options as object()) as object()", "description" : "

    Lists all the documents in a given database.

    \n

    This function has the same semantics as\n all-documents#3,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists all the documents in a given database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object listing the documents in the specified database" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 2, "name" : "all-documents", "qname" : "cloudant:all-documents", "signature" : "($connection as anyURI, $database as string) as object()", "description" : "

    Lists all the documents in a given database.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The information is returned as a JSON structure containing meta information\n about the return structure, and the list of documents each with its ID, revision\n and key. The key is generated from the document ID.

    \n

    For example,\n

    cloudant:all-documents($connection, \"db\")
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"total_rows\":3,\n   \"offset\":0,\n   \"rows\":[\n   {\n     \"id\":\"5a049246-179f-42ad-87ac-8f080426c17c\",\n     \"key\":\"5a049246-179f-42ad-87ac-8f080426c17c\",\n     \"value\":\n     {\n       \"rev\":\"2-9d5401898196997853b5ac4163857a29\"\n     }\n   },\n   {\n     \"id\":\"96f898f0-f6ff-4a9b-aac4-503992f31b01\",\n     \"key\":\"96f898f0-f6ff-4a9b-aac4-503992f31b01\",\n     \"value\":\n     {\n       \"rev\":\"2-ff7b85665c4c297838963c80ecf481a3\"\n      }\n   },\n   {\n     \"id\":\"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n     \"key\":\"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n     \"value\":\n     {\n       \"rev\":\"2-cbdef49ef3ddc127eff86350844a6108\"\n     }\n   }]\n }\n 
    \n

    \n

    The fields have the following meaning:\n

      \n
    • offset: offset where the document list started.
    • \n
    • rows: array of document objects, each containing id, key and revision number.
    • \n
    • total_rows: number of documents in the database.
    • \n
    • update_seq: current update sequence database.
    • \n
    \n

    \n", "summary" : "

    Lists all the documents in a given database.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " } ], "returns" : { "type" : "object()", "description" : "An object listing the documents in the specified database" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 3, "name" : "all-documents", "qname" : "cloudant:all-documents", "signature" : "($connection as anyURI, $database as string, $options as object()) as object()", "description" : "

    Lists all the documents in a given database.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The information is returned as a JSON structure containing meta information\n about the return structure, and the list of documents each with its ID, revision\n and key. The key is generated from the document ID.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • descending: return the documents in descending by key order (boolean,\n default: false).
    • \n
    • endkey: stop returning records when the specified key is reached (string).
    • \n
    • endkey_docid: stop returning records when the specified document ID is\n reached (string).
    • \n
    • group: group the results using the reduce function to a group or single\n row (boolean, default: false).
    • \n
    • group_level: specify the group level to be used (numeric).
    • \n
    • include_docs: include the full content of the documents in the return\n (boolean, default: false).
    • \n
    • inclusive_end: specifies whether the specified end key should be included\n in the result (boolean, default: true).
    • \n
    • key: return only documents that match the specified key (string).
    • \n
    • limit: limit the number of the returned documents to the specified number\n (numeric).
    • \n
    • reduce: use the reduction function (boolean, default: true).
    • \n
    • skip: skip this number of records before starting to return the results\n (numeric, default: 0).
    • \n
    • stale: allow the results from a stale view to be used (string, allowed\n value: \"ok\").
    • \n
    • startkey: start returning records when the specified key is reached (string).
    • \n
    • startkey_docid: start returning records when the specified document ID\n is reached (string).
    • \n
    • database-owner: specifies the database owner (string, default: connection\n user).
    • \n
    \n

    \n

    For example,\n

    cloudant:all-documents($connection, \"db\", {\"database-owner\": \"username\"})
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"total_rows\":3,\n   \"offset\":0,\n   \"rows\":[\n   {\n     \"id\":\"5a049246-179f-42ad-87ac-8f080426c17c\",\n     \"key\":\"5a049246-179f-42ad-87ac-8f080426c17c\",\n     \"value\":\n     {\n       \"rev\":\"2-9d5401898196997853b5ac4163857a29\"\n     }\n   },\n   {\n     \"id\":\"96f898f0-f6ff-4a9b-aac4-503992f31b01\",\n     \"key\":\"96f898f0-f6ff-4a9b-aac4-503992f31b01\",\n     \"value\":\n     {\n       \"rev\":\"2-ff7b85665c4c297838963c80ecf481a3\"\n      }\n   },\n   {\n     \"id\":\"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n     \"key\":\"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n     \"value\":\n     {\n       \"rev\":\"2-cbdef49ef3ddc127eff86350844a6108\"\n     }\n   }]\n }\n 
    \n

    \n

    The fields have the following meaning:\n

      \n
    • offset: offset where the document list started.
    • \n
    • rows: array of document objects, each containing id, key and revision number.
    • \n
    • total_rows: number of documents in the database.
    • \n
    • update_seq: current update sequence database.
    • \n
    \n

    \n", "summary" : "

    Lists all the documents in a given database.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object listing the documents in the specified database" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 4, "name" : "all-view-documents-nondeterministic", "qname" : "cloudant:all-view-documents-nondeterministic", "signature" : "($connection as anyURI, $database as string, $design-document as string, $view as string) as object()", "description" : "

    Returns a JSON object describing all the documents in a given view.

    \n

    This function has the same semantics as\n all-view-documents#4,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Returns a JSON object describing all the documents in a given view.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "design-document", "type" : "string", "occurrence" : null, "description" : "
    A design document name
    " }, { "name" : "view", "type" : "string", "occurrence" : null, "description" : "
    A view name
    " } ], "returns" : { "type" : "object()", "description" : "An object listing all documents in the specified view" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 5, "name" : "all-view-documents-nondeterministic", "qname" : "cloudant:all-view-documents-nondeterministic", "signature" : "($connection as anyURI, $database as string, $design-document as string, $view as string, $options as object()) as object()", "description" : "

    Returns a JSON object describing all the documents in a given view.

    \n

    This function has the same semantics as\n all-view-documents#5,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Returns a JSON object describing all the documents in a given view.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "design-document", "type" : "string", "occurrence" : null, "description" : "
    A design document name
    " }, { "name" : "view", "type" : "string", "occurrence" : null, "description" : "
    A view name
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object listing all documents in the specified view" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 4, "name" : "all-view-documents", "qname" : "cloudant:all-view-documents", "signature" : "($connection as anyURI, $database as string, $design-document as string, $view as string) as object()", "description" : "

    Returns a JSON object describing all the documents in a given view.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The information is returned as a JSON structure containing meta information\n about the return structure, and the list of documents each with its ID, revision\n and key. The key is generated from the document ID.

    \n

    For example,\n

    cloudant:all-view-documents($connection, \"db\", \"recipes\", \"by_title\")
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"offset\" : 0,\n   \"rows\" :\n   [\n     {\n       \"id\" : \"3-tiersalmonspinachandavocadoterrine\",\n       \"key\" : \"3-tier salmon, spinach and avocado terrine\",\n       \"value\" : [\"3-tier salmon, spinach and avocado terrine\"]\n     },\n     {\n       \"id\" : \"Aberffrawcake\",\n       \"key\" : \"Aberffraw cake\",\n       \"value\" : [\"Aberffraw cake\"]\n     },\n     {\n       \"id\" : \"Adukiandorangecasserole-microwave\",\n       \"key\" : \"Aduki and orange casserole - microwave\",\n       \"value\" : [\"Aduki and orange casserole - microwave\"]\n     }\n   ],\n   \"total_rows\" : 3\n }\n 
    \n

    \n

    The fields have the following meaning:\n

      \n
    • offset: offset where the document list started.
    • \n
    • rows: array of document objects, each containing id, key and revision number.
    • \n
    • total_rows: number of documents in the database.
    • \n
    \n

    \n", "summary" : "

    Returns a JSON object describing all the documents in a given view.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "design-document", "type" : "string", "occurrence" : null, "description" : "
    A design document name
    " }, { "name" : "view", "type" : "string", "occurrence" : null, "description" : "
    A view name
    " } ], "returns" : { "type" : "object()", "description" : "An object listing all documents in the specified view" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 5, "name" : "all-view-documents", "qname" : "cloudant:all-view-documents", "signature" : "($connection as anyURI, $database as string, $design-document as string, $view as string, $options as object()) as object()", "description" : "

    Returns a JSON object describing all the documents in a given view.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The information is returned as a JSON structure containing meta information\n about the return structure, and the list of documents each with its ID, revision\n and key. The key is generated from the document ID.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • descending: return the documents in descending by key order (boolean,\n default: false)
    • \n
    • endkey: stop returning records when the specified key is reached (string)
    • \n
    • endkey_docid: stop returning records when the specified document ID is\n reached (string)
    • \n
    • group: group the results using the reduce function to a group or single\n row (boolean, default: false)
    • \n
    • group_level: specify the group level to be used (numeric)
    • \n
    • include_docs: include the full content of the documents in the return\n (boolean, default: false)
    • \n
    • inclusive_end: specifies whether the specified end key should be included\n in the result (boolean, default: true)
    • \n
    • key: return only documents that match the specified key (string)
    • \n
    • limit: limit the number of the returned documents to the specified number\n (numeric)
    • \n
    • reduce: use the reduction function (boolean, default: true)
    • \n
    • skip: skip this number of records before starting to return the results\n (numeric, default: 0)
    • \n
    • stale: allow the results from a stale view to be used (string, allowed\n value: \"ok\")
    • \n
    • startkey: start returning records when the specified key is reached\n (string)
    • \n
    • startkey_docid: start returning records when the specified document ID\n is reached (string)
    • \n
    • database-owner: specifies the database owner (string, default:\n connection user).
    • \n
    \n

    \n

    For example,\n

    cloudant:all-view-documents($connection, \"db\", \"recipes\", \"by_title\",\n   {\"database-owner\" : \"username\"})
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"offset\" : 0,\n   \"rows\" :\n   [\n     {\n       \"id\" : \"3-tiersalmonspinachandavocadoterrine\",\n       \"key\" : \"3-tier salmon, spinach and avocado terrine\",\n       \"value\" : [\"3-tier salmon, spinach and avocado terrine\"]\n     },\n     {\n       \"id\" : \"Aberffrawcake\",\n       \"key\" : \"Aberffraw cake\",\n       \"value\" : [\"Aberffraw cake\"]\n     },\n     {\n       \"id\" : \"Adukiandorangecasserole-microwave\",\n       \"key\" : \"Aduki and orange casserole - microwave\",\n       \"value\" : [\"Aduki and orange casserole - microwave\"]\n     }\n   ],\n   \"total_rows\" : 3\n }\n 
    \n

    \n

    The fields have the following meaning:\n

      \n
    • offset: offset where the document list started.
    • \n
    • rows: array of document objects, each containing id, key and revision\n number.
    • \n
    • total_rows: number of documents in the database.
    • \n
    \n

    \n", "summary" : "

    Returns a JSON object describing all the documents in a given view.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "design-document", "type" : "string", "occurrence" : null, "description" : "
    A design document name
    " }, { "name" : "view", "type" : "string", "occurrence" : null, "description" : "
    A view name
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object listing all documents in the specified view" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 4, "name" : "attachment-nondeterministic", "qname" : "cloudant:attachment-nondeterministic", "signature" : "($connection as anyURI, $database as string, $document-id as string, $attachment-name as string) as object()", "description" : "

    Retrieves the specified document attachment.

    \n

    This function has the same semantics as\n attachment#4,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves the specified document attachment.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "attachment-name", "type" : "string", "occurrence" : null, "description" : "
    An attchment name
    " } ], "returns" : { "type" : "object()", "description" : "The specified document attachment" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 5, "name" : "attachment-nondeterministic", "qname" : "cloudant:attachment-nondeterministic", "signature" : "($connection as anyURI, $database as string, $document-id as string, $attachment-name as string, $options as object()) as object()", "description" : "

    Retrieves the specified document attachment.

    \n

    This function has the same semantics as attachment#5,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves the specified document attachment.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "attachment-name", "type" : "string", "occurrence" : null, "description" : "
    An attchment name
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "The specified document attachment" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:ATTACHMENT-NOT-EXISTS Attachment does not exists", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 4, "name" : "attachment", "qname" : "cloudant:attachment", "signature" : "($connection as anyURI, $database as string, $document-id as string, $attachment-name as string) as object()", "description" : "

    Retrieves the specified document attachment.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    For example,\n

    cloudant:attachment($connection, \"db\", \"DocID\", \"Attachment\")
    .\n

    \n

    Retrieving a design document attachment.

    \n

    To retrieve a design document attachment the document id must\n start with _design/.

    \n

    For example,\n

    cloudant:attachment($connection, \"db\", \"_design/DocID\", \"Attachment\")
    .\n

    \n

    Return value

    \n

    The returned object reports the media-type of the attachment as\n it was specified when the attachment was submitted to the database and\n its raw content.\n The format of the returned object is the following:\n

    \n {\n   \"media-type\": \"text/plain\",\n   \"content\" : \"Hello World\"\n }\n 
    \n

    \n

    The type of the content field is determined by the media-type returned by the\n server. If the media-type indicates that the body content is textual,\n then the content has type string, base64Binary otherwise.\n Specifically, the body content is considered textual only if the MIME-type specified in\n the media-type is one of:\n

      \n
    • \"application/json\"
    • \n
    • \"application/x-javascript\"
    • \n
    • \"application/xml\"
    • \n
    • \"application/xml-external-parsed-entity\"
    • \n
    \n or if the MIME-type starts with \"text/\" or ends with \"+xml\".

    \n", "summary" : "

    Retrieves the specified document attachment.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "attachment-name", "type" : "string", "occurrence" : null, "description" : "
    An attchment name
    " } ], "returns" : { "type" : "object()", "description" : "The specified document attachment" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 5, "name" : "attachment", "qname" : "cloudant:attachment", "signature" : "($connection as anyURI, $database as string, $document-id as string, $attachment-name as string, $options as object()) as object()", "description" : "

    Retrieves the specified document attachment.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • database-owner: specifies the database owner (string, default: connection user).
    • \n
    \n

    \n

    For example,\n

    cloudant:attachment($connection, \"db\", \"DocID\", \"Attachment\",\n   {\"database-owner\": \"username\"})
    .\n

    \n

    Retrieving a design document attachment.

    \n

    To retrieve a design document attachment the document id must\n start with _design/.

    \n

    For example,\n

    cloudant:attachment($connection, \"db\", \"_design/DocID\", \"Attachment\",\n   {\"database-owner\": \"username\"})
    .\n

    \n

    Return value

    \n

    The returned object reports the media-type of the attachment as\n it was specified when the attachment was submitted to the database and\n its raw content.\n The format of the returned object is the following:\n

    \n {\n   \"media-type\": \"text/plain\",\n   \"content\" : \"Hello World\"\n }\n 
    \n

    \n

    The type of the content field is determined by the media-type returned by the\n server. If the media-type indicates that the body content is textual,\n then the content has type string, base64Binary otherwise.\n Specifically, the body content is considered textual only if the MIME-type specified in\n the media-type is one of:\n

      \n
    • \"application/json\"
    • \n
    • \"application/x-javascript\"
    • \n
    • \"application/xml\"
    • \n
    • \"application/xml-external-parsed-entity\"
    • \n
    \n or if the MIME-type starts with \"text/\" or ends with \"+xml\".

    \n", "summary" : "

    Retrieves the specified document attachment.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "attachment-name", "type" : "string", "occurrence" : null, "description" : "
    An attchment name
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "The specified document attachment" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:ATTACHMENT-NOT-EXISTS Attachment does not exists", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 3, "name" : "bulk-crud", "qname" : "cloudant:bulk-crud", "signature" : "($connection as anyURI, $database as string, $documents as object()*) as array()", "description" : "

    Creates, updates or deletes multiple documents with a single request.

    \n

    When creating new documents the document ID is optional. For updating\n existing documents, you must provide the document ID, revision information,\n and new document values. To delete existing documents, you must provide the\n document ID, revision information and add a field _deleted having\n value true.\n

    \n

    For example,\n

    cloudant:bulk-crud($connection, \"db\",\n (\n   {\n     \"name\":\"Nicholas\",\n     \"age\":45,\n     \"gender\":\"male\",\n   },\n   {\n     \"name\":\"Taylor\",\n     \"age\":50,\n     \"gender\":\"male\",\n     \"_id\":\"5a049246-179f-42ad-87ac-8f080426c17c\",\n   },\n   {\n     \"name\":\"Owen\",\n     \"age\":51,\n     \"gender\":\"male\",\n     \"_id\":\"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n     \"_rev\":\"2-f29c836d0bedc4b4b95cfaa6d99e95df\",\n   },\n   {\n     \"_id\":\"b675e932-9bb6-4fc9-b889-50238ac3512b\",\n     \"_rev\":\"2-abd3942fdab3515bfed224abed2451feb\",\n     \"_deleted\": true\n   }\n ))\n 
    \n requires to insert the first document with a system-generated identifier, to\n insert the second one with a user-specified identifier, to update the third\n one and, finally,to delete the last one.\n

    \n

    \n The JSON returned by the_bulk_docs operation consists of an array\n of JSON structures, one for each submitted document.\n The returned JSON structure should be examined to ensure that all of\n the documents submitted in the original request were successfully added\n to the database. When no errors are raised, the revision of the new\n document is reported for all documents.\n

    \n

    \n

    \n [{\n    \"id\":\"96f898f0-f6ff-4a9b-aac4-503992f31b01\",\n    \"rev\":\"2-ff7b85665c4c297838963c80ecf481a3\"\n  },\n  {\n    \"id\":\"5a049246-179f-42ad-87ac-8f080426c17c\",\n    \"rev\":\"2-9d5401898196997853b5ac4163857a29\"\n  },\n  {\n    \"id\":\"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n    \"rev\":\"2-cbdef49ef3ddc127eff86350844a6108\"\n  },\n  {\n    \"id\": \"b675e932-9bb6-4fc9-b889-50238ac3512b\",\n    \"rev\":\"2-12356bafb1232167befabb32127823943d\"\n  }]\n 
    \n

    \n

    Cloudant will only guarantee that some of the documents will be\n saved when you send the request. The response will contain the list of\n documents successfully inserted or updated during the process.\n In the event of a crash, some of the documents may have been successfully\n saved, and some will have been lost.\n The response structure will indicate whether the document was updated by\n supplying the rev parameter indicating a new document revision\n was created. If the update failed, then you will get an error of type\n conflict.

    \n

    For example:\n

    \n [\n   {\n     \"id\":\"FishStew\",\n     \"error\":\"conflict\",\n     \"reason\":\"Document update conflict.\"\n   },\n   {\n     \"id\":\"LambStew\",\n     \"error\":\"conflict\",\n     \"reason\":\"Document update conflict.\"\n   },\n   {\n     \"id\":\"7f7638c86173eb440b8890839ff35433\",\n     \"error\":\"conflict\",\n     \"reason\":\"Document update conflict.\"\n   }\n ]\n 
    \n In this case no new revision has been created and you will need to submit\n the document update with the correct revision tag, to update the document.\n

    \n

    The exact structure of each document in the returned array is:\n

      \n
    • id: the document ID
    • \n
    • rev: the new document revision, if a new revision was created
    • \n
    • error: the error type, if an error was raised
    • \n
    • reason: a description of the raised error, if an error was raised
    • \n
    \n

    \n

    The error type can either be conflict or forbidden. The first type means that\n the document as submitted is in conflict. The new revision has not been created\n and you will need to re-submit the document to the database. Entries with forbidden\n error type indicate that the validation routine applied to the document during submission\n has returned an error.

    \n", "summary" : "

    Creates, updates or deletes multiple documents with a single request.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "documents", "type" : "object()", "occurrence" : "*", "description" : "
    An sequence of documents
    " } ], "returns" : { "type" : "array()", "description" : "An object describing the performed operations" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 4, "name" : "bulk-crud", "qname" : "cloudant:bulk-crud", "signature" : "($connection as anyURI, $database as string, $documents as object()*, $options as object()) as array()", "description" : "

    Creates, updates or deletes multiple documents with a single request.

    \n

    When creating new documents the document ID is optional. For updating\n existing documents, you must provide the document ID, revision information,\n and new document values. To delete existing documents, you must provide the\n document ID, revision information and add a field _deleted having\n value true.\n

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • all_or_nothing: sets the database commit mode to use all-or-nothing\n semantics (boolean, default: false).
    • \n
    • database-owner: specifies the database owner (string, default: connection\n user).
    • \n
    \n

    \n

    For example,\n

    cloudant:bulk-crud($connection, \"db\",\n (\n   {\n     \"name\":\"Nicholas\",\n     \"age\":45,\n     \"gender\":\"male\",\n   },\n   {\n     \"name\":\"Taylor\",\n     \"age\":50,\n     \"gender\":\"male\",\n     \"_id\":\"5a049246-179f-42ad-87ac-8f080426c17c\",\n   },\n   {\n     \"name\":\"Owen\",\n     \"age\":51,\n     \"gender\":\"male\",\n     \"_id\":\"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n     \"_rev\":\"2-f29c836d0bedc4b4b95cfaa6d99e95df\",\n   },\n   {\n     \"_id\":\"b675e932-9bb6-4fc9-b889-50238ac3512b\",\n     \"_rev\":\"2-abd3942fdab3515bfed224abed2451feb\",\n     \"_deleted\": true\n   }\n ),{\"database-owner\": \"username\"})\n 
    \n requires to insert the first document with a system-generated identifier, to\n insert the second one with a user-specified identifier, to update the third\n one and, finally, to delete the last one.\n

    \n

    \n The JSON returned by the_bulk_docs operation consists of an array\n of JSON structures, one for each document in the original submission.\n The returned JSON structure should be examined to ensure that all of\n the documents submitted in the original request were successfully added\n to the database. When no errors are raised, the revision of the new\n document is reported for all documents.\n

    \n

    \n

    \n [{\n    \"id\":\"96f898f0-f6ff-4a9b-aac4-503992f31b01\",\n    \"rev\":\"2-ff7b85665c4c297838963c80ecf481a3\"\n  },\n  {\n    \"id\":\"5a049246-179f-42ad-87ac-8f080426c17c\",\n    \"rev\":\"2-9d5401898196997853b5ac4163857a29\"\n  },\n  {\n    \"id\":\"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n    \"rev\":\"2-cbdef49ef3ddc127eff86350844a6108\"\n  },\n  {\n    \"id\": \"b675e932-9bb6-4fc9-b889-50238ac3512b\",\n    \"rev\":\"2-12356bafb1232167befabb32127823943d\"\n  }]\n 
    \n

    \n

    Cloudant will only guarantee that some of the documents will be\n saved when you send the request. The response will contain the list of\n documents successfully inserted or updated during the process.\n In the event of a crash, some of the documents may have been successfully\n saved, and some will have been lost.\n The response structure will indicate whether the document was updated by\n supplying the rev parameter indicating a new document revision\n was created. If the update failed, then you will get an error of type\n conflict.

    \n

    For example:\n

    \n [\n   {\n     \"id\":\"FishStew\",\n     \"error\":\"conflict\",\n     \"reason\":\"Document update conflict.\"\n   },\n   {\n     \"id\":\"LambStew\",\n     \"error\":\"conflict\",\n     \"reason\":\"Document update conflict.\"\n   },\n   {\n     \"id\":\"7f7638c86173eb440b8890839ff35433\",\n     \"error\":\"conflict\",\n     \"reason\":\"Document update conflict.\"\n   }\n ]\n 
    \n In this case no new revision has been created and you will need to submit\n the document update with the correct revision tag, to update the document.\n

    \n

    The exact structure of each document in the returned array is:\n

      \n
    • id: the document ID
    • \n
    • rev: the new document revision, if a new revision was created
    • \n
    • error: the error type, if an error was raised
    • \n
    • reason: a description of the raised error, if an error was raised
    • \n
    \n

    \n

    The error type can either be conflict or forbidden. The first type means that\n the document as submitted is in conflict. The new revision has not been created\n and you will need to re-submit the document to the database. Entries with forbidden\n error type indicate that the validation routine applied to the document during submission\n has returned an error.

    \n", "summary" : "

    Creates, updates or deletes multiple documents with a single request.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "documents", "type" : "object()", "occurrence" : "*", "description" : "
    An sequence of documents
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "array()", "description" : "An object describing the performed operations" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 2, "name" : "commit-changes", "qname" : "cloudant:commit-changes", "signature" : "($connection as anyURI, $database as string) as object()", "description" : "

    Commits any recent changes to the specified database to disk.

    \n

    For example,\n

    cloudant:commit-changes($connection, \"db\")
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"ok\" : true,\n   \"instance_start_time\" : \"0\"\n }\n 
    \n

    \n", "summary" : "

    Commits any recent changes to the specified database to disk.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " } ], "returns" : { "type" : "object()", "description" : "An object reporting the instance start time" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NOT-EXISTS The specified database does not exists", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 3, "name" : "commit-changes", "qname" : "cloudant:commit-changes", "signature" : "($connection as anyURI, $database as string, $options as object()) as object()", "description" : "

    Commits any recent changes to the specified database to disk.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • database-owner: specifies the database owner (string, default: connection\n user).
    • \n
    \n

    \n

    For example,\n

    \n cloudant:commit-changes($connection, \"db\", {\"database-owner\": \"username\"})\n 
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"ok\" : true,\n   \"instance_start_time\" : \"0\"\n }\n 
    \n

    \n", "summary" : "

    Commits any recent changes to the specified database to disk.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object reporting the instance start time" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NOT-EXISTS The specified database does not exists", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 0, "name" : "connect", "qname" : "cloudant:connect", "signature" : "() as anyURI", "description" : "

    Opens a connection to Cloudant using the default credentials.

    \n

    The function returns an opaque URI that can represents the connection.\n This URI has to be passed to other functions of this module that require\n a $connection parameter as a first argument.

    \n

    This function requires to specify an options object.\n The following options are supported:\n

      \n
    • username: the username used for connecting (string, mandatory).
    • \n
    • password: the password used for connecting (string, mandatory).
    • \n
    • default-database-owner: the default database owner which will be\n used when calling the other module functions (string).
    • \n
    \n

    \n

    For example,\n

    cloudant:connect()
    .\n

    \n", "summary" : "

    Opens a connection to Cloudant using the default credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "anyURI", "description" : "An identifier that represents the connection to the server" }, "errors" : [ "cloudant:CREDENTIALS Missing or invalid credentials", "cloudant:AUTHORIZATION Authentication error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 1, "name" : "connect", "qname" : "cloudant:connect", "signature" : "($credentials as item()) as anyURI", "description" : "

    Opens a connection to Cloudant using the specified credentials.

    \n

    The function returns an opaque URI that can represents the connection.\n This URI has to be passed to other functions of this module that require\n a $connection parameter as a first argument.

    \n

    The $credentials parameter is used to specify the connection information.\n If a string is used, then the function will interpret it as the name of\n a credential in the Cloudant category.\n If an object is used, then the function will open a connection using it.\n The object structure is the following:\n

      \n
    • username: the username used for connecting (string, mandatory).
    • \n
    • password: the password used for connecting (string, mandatory).
    • \n
    • default-database-owner: the default database owner which will be\n used when calling the other module functions (string, optional).
    • \n
    \n

    \n

    For example, using stored credential:\n

    cloudant:connect(\"credentials-name\")
    \n For example, specifying the connection information:\n
    cloudant:connect(\n   {\n     \"username\": \"user\",\n     \"password: \"pass\",\n     \"owner\": \"another-user\"\n   })
    .\n

    \n", "summary" : "

    Opens a connection to Cloudant using the specified credentials.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "credentials", "type" : "item()", "occurrence" : null, "description" : "
    The connection specification
    " } ], "returns" : { "type" : "anyURI", "description" : "An identifier that represents the connection to the server" }, "errors" : [ "cloudant:AUTHORIZATION Authentication error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:INTERNAL Cloudant internal error", "cloudant:CREDENTIALS Missing or malformed credentials" ] }, { "isDocumented" : true, "arity" : 2, "name" : "create-database", "qname" : "cloudant:create-database", "signature" : "($connection as anyURI, $database as string) as empty-sequence()", "description" : "

    Creates a new database.

    \n

    The database name must be composed of one or more of the following\n characters:\n

      \n
    • Lowercase characters (a-z).
    • \n
    • Digits (0-9).
    • \n
    • Any of the characters: _,$,(,),+,- and /.
    • \n
    \n

    \n

    For example,\n

    cloudant:create-database($connection, \"db\")
    .\n

    \n", "summary" : "

    Creates a new database.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "Empty sequence" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:DATABASE-EXISTS Database already exists", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 3, "name" : "create-document", "qname" : "cloudant:create-document", "signature" : "($connection as anyURI, $database as string, $document as object()) as object()", "description" : "

    Creates a new document in the specified database.

    \n

    Creates a new document in the specified database,\n using the supplied JSON document structure. If the JSON\n structure includes the _id field, then the document will\n be created with the specified document ID. If the _id\n field is not specified, a new unique ID will be generated.

    \n

    You can include one or more attachments with a given document\n by incorporating the attachment information within the JSON of\n the document. This provides a simpler alternative to loading\n documents with attachments than making a separate call.\n To do so add you can add the _attachments object\n field to the document. It can have one ore more fields, each\n defining a different attachment.\n The name of the field is the name of the attachment.\n Its value is an object containing the following fields:\n

      \n
    • content_type: MIME Content type string
    • \n
    • data: File attachment content, Base64 encoded
    • \n
    \n

    \n

    For example,\n

    cloudant:create-document($connection, \"db\",\n   {\n     \"_id\" : \"FishStew\",\n     \"servings\" : 4,\n     \"subtitle\" : \"Delicious with fresh bread\",\n     \"title\" : \"Fish Stew\"\n     \"_attachments\" : {\n       \"styling.css\" : {\n       \"content-type\" : \"text/css\",\n       \"data\" : \"cCB7IGZvbnQtc2l6ZTogMTJwdDsgfQo=\"\n       }\n     }\n   })\n 
    \n creates a document with an attachment named styling.css.\n

    \n

    Creating a design document

    \n

    To create a design document the _id field must be present and must\n start with _design/.

    \n

    For example, the following expression creates a design document\n

    cloudant:create-document($connection, \"db\",\n   {\n     \"_id\": \"_design/DesDocID\",\n     \"views\": {\n       \"view1\": {\n       \"map\":\"function(doc){emit(doc.field, 1)}\",\n       \"reduce\": \"function(key, value, rereduce){return sum(values)}\"\n       }\n     },\n     \"indexes\": {\n       \"mysearch\" : {\n         \"analyzer\": {\"name\": \"portuguese\", \"stopwords\":[\"foo\", \"bar, \"baz\"]},\n         \"index\": \"function(doc){ ... }\"\n       },\n     }\n   }, {\"database-owner\": \"username\"})\n 
    .\n

    \n

    Return value

    \n

    The returned JSON object will report the new document revision\n and has the following form:\n

    \n {\n   \"id\":\"64575eef70ab90a2b8d55fc09e00440d\",\n   \"ok\":true,\n   \"rev\":\"1-9c65296036141e575d32ba9c034dd3ee\"\n }\n 
    \n

    \n", "summary" : "

    Creates a new document in the specified database.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document", "type" : "object()", "occurrence" : null, "description" : "
    A document
    " } ], "returns" : { "type" : "object()", "description" : "An object which contains the document id and revision" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:DOCUMENT Document creation conflict", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 4, "name" : "create-document", "qname" : "cloudant:create-document", "signature" : "($connection as anyURI, $database as string, $document as object(), $options as object()) as object()", "description" : "

    Creates a new document in the specified database

    \n

    Creates a new document in the specified database,\n using the supplied JSON document structure. If the JSON\n structure includes the _id field, then the document will\n be created with the specified document ID. If the _id\n field is not specified, a new unique ID will be generated.

    \n

    You can include one or more attachments with a given document\n by incorporating the attachment information within the JSON of\n the document. This provides a simpler alternative to loading\n documents with attachments than making a separate call.\n To do so add you can add the _attachments object\n field to the document. It can have one ore more fields, each\n defining a different attachment.\n The name of the field is the name of the attachment.\n Its value is an object containing the following fields:\n

      \n
    • content_type: MIME Content type string
    • \n
    • data: File attachment content, Base64 encoded
    • \n
    \n

    \n

    For example,\n

    cloudant:create-document($connection, \"db\",\n   {\n     \"_id\" : \"FishStew\",\n     \"servings\" : 4,\n     \"subtitle\" : \"Delicious with fresh bread\",\n     \"title\" : \"Fish Stew\"\n     \"_attachments\" : {\n       \"styling.css\" : {\n       \"content-type\" : \"text/css\",\n       \"data\" : \"cCB7IGZvbnQtc2l6ZTogMTJwdDsgfQo=\"\n       }\n     }\n   }, {\"database-owner\": \"username\"})\n 
    \n creates a document with an attachment named styling.css.\n

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • batch: requires batch mode for insertions (string, allowed value: \"ok\")
    • \n
    • database-owner: specifies the database owner (string, default: connection user).
    • \n
    \n

    \n

    You can write documents to the database at a higher rate\n by using the batch option. This collects document writes\n together in memory (on a user-by-user basis) before they are\n committed to disk. This increases the risk of the documents\n not being stored in the event of a failure, since the documents\n are not written to disk immediately.

    \n

    Creating a design document

    \n

    To create a design document the _id field must be present and must\n start with _design/.

    \n

    For example, the following expression creates a design document\n

    cloudant:create-document($connection, \"db\",\n   {\n     \"_id\": \"_design/DesDocID\",\n     \"views\": {\n       \"view1\": {\n       \"map\":\"function(doc){emit(doc.field, 1)}\",\n       \"reduce\": \"function(key, value, rereduce){return sum(values)}\"\n       }\n     },\n     \"indexes\": {\n       \"mysearch\" : {\n         \"analyzer\": {\"name\": \"portuguese\", \"stopwords\":[\"foo\", \"bar, \"baz\"]},\n         \"index\": \"function(doc){ ... }\"\n       },\n     }\n   }, {\"database-owner\": \"username\"})\n 
    .\n

    \n

    Return value

    \n

    The returned JSON object will report the new document revision\n and has the following form:\n

    \n {\n   \"id\":\"64575eef70ab90a2b8d55fc09e00440d\",\n   \"ok\":true,\n   \"rev\":\"1-9c65296036141e575d32ba9c034dd3ee\"\n }\n 
    \n

    \n", "summary" : "

    Creates a new document in the specified database \n Creates a new document in the specified database,\n using the supplied JSON document structure.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document", "type" : "object()", "occurrence" : null, "description" : "
    A document
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object which contains the document id and revision" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:DOCUMENT Document creation conflict", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 7, "name" : "create-or-update-attachment", "qname" : "cloudant:create-or-update-attachment", "signature" : "($connection as anyURI, $database as string, $document-id as string, $document-rev as string, $attachment-name as string, $media-type as string, $attachment as atomic) as object()", "description" : "

    Creates or updates a document attachment.

    \n

    The latest document revision must be specified.

    \n

    For example,\n

    cloudant:create-or-update-attachment($connection, \"db\", \"FishStew\",\n   \"8-7c4740b4dcf26683e941d6641c00c39d\", \"AttachmentName\", \"text/plain\",\n   \"AttachmentContent\")
    .\n

    \n

    Creating or updating a design document attachment.

    \n

    To create or update a design document attachment the document id must\n start with _design/.

    \n

    For example,\n

    cloudant:create-or-update-attachment($connection, \"db\", \"_design/DesDocId\",\n   \"8-7c4740b4dcf26683e941d6641c00c39d\", \"AttachmentName\", \"text/plain\",\n   \"AttachmentContent\")
    .\n

    \n

    Return value

    \n

    The returned object reports the document id and its new\n revision, as follows:\n

    \n {\n   \"id\":\"FishStew\",\n   \"ok\":true,\n   \"rev\":\"9-247bb19a41bfd9bfdaf5ee6e2e05be74\"\n }\n 
    \n

    \n", "summary" : "

    Creates or updates a document attachment.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "document-rev", "type" : "string", "occurrence" : null, "description" : "
    A document revision
    " }, { "name" : "attachment-name", "type" : "string", "occurrence" : null, "description" : "
    The name of the attachment
    " }, { "name" : "media-type", "type" : "string", "occurrence" : null, "description" : "
    The media-type of the attachment
    " }, { "name" : "attachment", "type" : "atomic", "occurrence" : null, "description" : "
    -name The name of the attachment
    " } ], "returns" : { "type" : "object()", "description" : "An object containing the document id and its new revision" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:ATTACHMENT-TYPE Attachment type must be string, base64Binary or hexBinary", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 8, "name" : "create-or-update-attachment", "qname" : "cloudant:create-or-update-attachment", "signature" : "($connection as anyURI, $database as string, $document-id as string, $document-rev as string, $attachment-name as string, $media-type as string, $attachment as atomic, $options as object()) as object()", "description" : "

    Creates or updates a document attachment.

    \n

    The latest document revision must be specified.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • database-owner: specifies the database owner (string, default: connection user).
    • \n
    \n

    \n

    For example,\n

    cloudant:create-or-update-attachment($connection, \"db\", \"FishStew\",\n   \"8-7c4740b4dcf26683e941d6641c00c39d\", \"AttachmentName\", \"text/plain\",\n   \"AttachmentContent\", {\"database-owner\": \"username\"})
    .\n

    \n

    Creating or updating a design document attachment.

    \n

    To create or update a design document attachment the document id must\n start with _design/.

    \n

    For example,\n

    cloudant:create-or-update-attachment($connection, \"db\", \"_design/DesDocId\",\n   \"8-7c4740b4dcf26683e941d6641c00c39d\", \"AttachmentName\", \"text/plain\",\n   \"AttachmentContent\", {\"database-owner\": \"username\"})
    .\n

    \n

    Return value

    \n

    The returned object reports the document id and its new\n revision, as follows:\n

    \n {\n   \"id\":\"FishStew\",\n   \"ok\":true,\n   \"rev\":\"9-247bb19a41bfd9bfdaf5ee6e2e05be74\"\n }\n 
    \n

    \n", "summary" : "

    Creates or updates a document attachment.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "document-rev", "type" : "string", "occurrence" : null, "description" : "
    A document revision
    " }, { "name" : "attachment-name", "type" : "string", "occurrence" : null, "description" : "
    The name of the attachment
    " }, { "name" : "media-type", "type" : "string", "occurrence" : null, "description" : "
    The media-type of the attachment
    " }, { "name" : "attachment", "type" : "atomic", "occurrence" : null, "description" : "
    -name The name of the attachment
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object containing the document id and its new revision" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:ATTACHMENT-TYPE Attachment type must be string, base64Binary or hexBinary", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 3, "name" : "create-or-update-document", "qname" : "cloudant:create-or-update-document", "signature" : "($connection as anyURI, $database as string, $document as object()) as object()", "description" : "

    Creates or updates a document.

    \n

    When creating a new document, the _id field must\n be specified.

    \n

    For example,\n

    cloudant:create-or-update-document($connection, \"db\",\n   {\n     \"name\":\"Hannah\",\n     \"age\":120,\n     \"gender\":\"female\",\n     \"_id\":\"DocID\"\n   })
    .\n

    \n

    When updating a document, the _id and the\n _rev field, which contains the last document revision,\n must be specified.

    \n

    For example,\n

    cloudant:create-or-update-document($connection, \"db\",\n   {\n     \"name\":\"Hannah\",\n     \"age\":40,\n     \"gender\":\"female\",\n     \"_id\":\"DocID\",\n     \"_rev\":\"1-764b9b11845fd0b73cfa0e61acc74ecf\"\n   })
    .\n

    \n

    Creating or updating a design document

    \n

    To create or update a design document the document id must\n start with _design/.

    \n

    For example, the following expression creates a design document\n

    cloudant:create-or-update-document($connection, \"db\",\n   {\n     \"_id\": \"_design/DesDocID\",\n     \"views\": {\n       \"view1\": {\n       \"map\":\"function(doc){emit(doc.field, 1)}\",\n       \"reduce\": \"function(key, value, rereduce){return sum(values)}\"\n       }\n     },\n     \"indexes\": {\n       \"mysearch\" : {\n         \"analyzer\": {\"name\": \"portuguese\", \"stopwords\":[\"foo\", \"bar, \"baz\"]},\n         \"index\": \"function(doc){ ... }\"\n       },\n     }\n   })\n 
    .\n

    \n

    For example, the following expression updates a design document\n

    cloudant:create-or-update-document($connection, \"db\",\n   {\n     \"_id\": \"_design/DesDocID\",\n     \"_rev\": \"2-f29c836d0bedc4b4b95cfaa6d99e95df\",\n     \"views\": {\n       \"view1\": {\n       \"map\":\"function(doc){emit(doc.field, 1)}\",\n       \"reduce\": \"function(key, value, rereduce){return sum(values)}\"\n       }\n     },\n     \"indexes\": {\n       \"mysearch\" : {\n         \"analyzer\": {\"name\": \"portuguese\", \"stopwords\":[\"foo\", \"bar, \"baz\"]},\n         \"index\": \"function(doc){ ... }\"\n       },\n     }\n   })\n 
    .

    \n

    \n The meaning of the fields in the design document is the following:\n

      \n
    • _id: document ID
    • \n
    • _rev: document revision
    • \n
    • views: object defining the views. Each field defines a different view.\n The field name is the name of the view and has the following content:\n
        \n
      • map: view map function
      • \n
      • reduce: view reduce function (optional)
      • \n
      \n
    • \n
    • indexes: object defining the view indexes. Each field defines a different index.\n The field name is the name of the index and has the following content:\n
        \n
      • analyzer: Name of the analyzer to be used or an object with the\n following fields:\n
          \n
        • name: Name of the analyzer
        • \n
        • stopwords: An array of stop words. Stop words are words that\n should not be indexed.
        • \n
        \n
      • \n
      • index: Function that handles the indexing
      • \n
      \n
    • \n
    \n

    \n

    Return value

    \n

    The format of the returned object is the following and contains\n the document id and revision.\n

    \n {\n   \"ok\":true,\n   \"id\":\"DocID\",\n   \"rev\":\"1-764b9b11845fd0b73cfa0e61acc74ecf\"\n }\n 
    \n

    \n", "summary" : "

    Creates or updates a document.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document", "type" : "object()", "occurrence" : null, "description" : "
    A document
    " } ], "returns" : { "type" : "object()", "description" : "An object which specifies the document id and its new revision" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:DOCUMENT-MALFORMED Malformed document object", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 4, "name" : "create-or-update-document", "qname" : "cloudant:create-or-update-document", "signature" : "($connection as anyURI, $database as string, $document as object(), $options as object()) as object()", "description" : "

    Creates or updates a document.

    \n

    When creating a new document, the _id field must\n be specified.

    \n

    For example,\n

    cloudant:create-or-update-document($connection, \"db\", \"DocID\",\n   {\n     \"name\":\"Hannah\",\n     \"age\":120,\n     \"gender\":\"female\",\n     \"_id\":\"DocID\"\n   }, {\"database-owner\": \"username\"})
    .\n

    \n

    When updating a document, the _id and the\n _rev field, which contains the last document revision,\n must be specified.

    \n

    For example,\n

    cloudant:create-or-update-document($connection, \"db\", \"DocID\",\n   {\n     \"name\":\"Hannah\",\n     \"age\":40,\n     \"gender\":\"female\",\n     \"_id\":\"DocID\",\n     \"_rev\":\"1-764b9b11845fd0b73cfa0e61acc74ecf\"\n   }, {\"database-owner\": \"username\"})
    .\n

    \n

    Creating or updating a design document

    \n

    To create or update a design document the document id must\n start with _design/.

    \n

    For example, the following expression creates a design document\n

    cloudant:create-or-update-document($connection, \"db\",\n   {\n     \"_id\": \"_design/DesDocID\",\n     \"views\": {\n       \"view1\": {\n       \"map\":\"function(doc){emit(doc.field, 1)}\",\n       \"reduce\": \"function(key, value, rereduce){return sum(values)}\"\n       }\n     },\n     \"indexes\": {\n       \"mysearch\" : {\n         \"analyzer\": {\"name\": \"portuguese\", \"stopwords\":[\"foo\", \"bar, \"baz\"]},\n         \"index\": \"function(doc){ ... }\"\n       },\n     }\n   }, {\"database-owner\": \"username\"})\n 
    .\n

    \n
    cloudant:create-or-update-document($connection, \"db\",\n   {\n     \"_id\": \"_design/DesDocID\",\n     \"_rev\": \"2-f29c836d0bedc4b4b95cfaa6d99e95df\",\n     \"views\": {\n       \"view1\": {\n       \"map\":\"function(doc){emit(doc.field, 1)}\",\n       \"reduce\": \"function(key, value, rereduce){return sum(values)}\"\n       }\n     },\n     \"indexes\": {\n       \"mysearch\" : {\n         \"analyzer\": {\"name\": \"portuguese\", \"stopwords\":[\"foo\", \"bar, \"baz\"]},\n         \"index\": \"function(doc){ ... }\"\n       },\n     }\n   }, {\"database-owner\": \"username\"})\n 
    .\n

    \n The meaning of the fields in the design document is the following:\n

      \n
    • _id: document ID
    • \n
    • _rev: document revision
    • \n
    • views: object defining the views. Each field defines a different view.\n The field name is the name of the view and has the following content:\n
        \n
      • map: view map function
      • \n
      • reduce: view reduce function (optional)
      • \n
      \n
    • \n
    • indexes: object defining the view indexes. Each field defines a different index.\n The field name is the name of the index and has the following content:\n
        \n
      • analyzer: Name of the analyzer to be used or an object with the\n following fields:\n
          \n
        • name: Name of the analyzer
        • \n
        • stopwords: An array of stop words. Stop words are words that\n should not be indexed.
        • \n
        \n
      • \n
      • index: Function that handles the indexing
      • \n
      \n
    • \n
    \n

    \n

    Return value

    \n

    The format of the returned object is the following and contains\n the document id and revision.\n

    \n {\n   \"ok\":true,\n   \"id\":\"DocID\",\n   \"rev\":\"1-764b9b11845fd0b73cfa0e61acc74ecf\"\n }\n 
    \n

    \n", "summary" : "

    Creates or updates a document.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document", "type" : "object()", "occurrence" : null, "description" : "
    A document
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object which specifies the document id and its new revision" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:DOCUMENT-MALFORMED Malformed document object", "cloudant:OPTIONS Malformed options object", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 2, "name" : "database-info-nondeterministic", "qname" : "cloudant:database-info-nondeterministic", "signature" : "($connection as anyURI, $database as string) as object()", "description" : "

    Returns information about a database.

    \n

    This function has the same semantics as database-info#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Returns information about a database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " } ], "returns" : { "type" : "object()", "description" : "An object describing the specified database" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 3, "name" : "database-info-nondeterministic", "qname" : "cloudant:database-info-nondeterministic", "signature" : "($connection as anyURI, $database as string, $options as object()) as object()", "description" : "

    Returns information about a database.

    \n

    This function has the same semantics as\n database-info#3,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Returns information about a database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    a database name
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object describing the specified database" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 2, "name" : "database-info", "qname" : "cloudant:database-info", "signature" : "($connection as anyURI, $database as string) as object()", "description" : "

    Returns information about a database.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    For example,\n

    cloudant:database-info($connection, \"db\")
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"update_seq\": \"0-g1AAAADneJzLYWBg...\",\n   \"db_name\": \"db\",\n   \"purge_seq\": 0,\n   \"other\": {\n     \"data_size\": 0\n   },\n   \"doc_del_count\": 0,\n   \"doc_count\": 0,\n   \"disk_size\": 316,\n   \"disk_format_version\": 5,\n   \"compact_running\": false,\n   \"instance_start_time\": \"0\"\n }\n 
    \n

    \n

    The fields have the following meaning:\n

      \n
    • compact_running: set to true if the database compaction routine is\n operating on this database.
    • \n
    • db_name: the name of the database.
    • \n
    • disk_format_version: the version of the physical format used for the data\n when it is stored on disk.
    • \n
    • disk_size: size in bytes of the data as stored on the disk. Views indexes\n are not included in the calculation.
    • \n
    • doc_count: a count of the documents in the specified database.
    • \n
    • doc_del_count: number of deleted documents.
    • \n
    • instance_start_time: always 0.
    • \n
    • purge_seq: the number of purge operations on the database.
    • \n
    • update_seq: the current number of updates to the database.
    • \n
    • other: JSON object containing a data_size field.
    • \n
    \n

    \n", "summary" : "

    Returns information about a database.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " } ], "returns" : { "type" : "object()", "description" : "An object describing the specified database" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 3, "name" : "database-info", "qname" : "cloudant:database-info", "signature" : "($connection as anyURI, $database as string, $options as object()) as object()", "description" : "

    Returns information about a database.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • database-owner: specifies the database owner (string, default: connection user).
    • \n
    \n

    \n

    For example,\n

    cloudant:database-info($connection, \"db\", {\"database-owner\": \"username\"})
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"update_seq\": \"0-g1AAAADneJzLYWBg...\",\n   \"db_name\": \"db\",\n   \"purge_seq\": 0,\n   \"other\": {\n     \"data_size\": 0\n   },\n   \"doc_del_count\": 0,\n   \"doc_count\": 0,\n   \"disk_size\": 316,\n   \"disk_format_version\": 5,\n   \"compact_running\": false,\n   \"instance_start_time\": \"0\"\n }\n 
    \n

    \n

    The fields have the following meaning:\n

      \n
    • compact_running: set to true if the database compaction routine is\n operating on this database.
    • \n
    • db_name: the name of the database.
    • \n
    • disk_format_version: the version of the physical format used for the data\n when it is stored on disk.
    • \n
    • disk_size: size in bytes of the data as stored on the disk. Views indexes\n are not included in the calculation.
    • \n
    • doc_count: a count of the documents in the specified database.
    • \n
    • doc_del_count: number of deleted documents.
    • \n
    • instance_start_time: always 0.
    • \n
    • purge_seq: the number of purge operations on the database.
    • \n
    • update_seq: the current number of updates to the database.
    • \n
    • other: JSON object containing a data_size field.
    • \n
    \n

    \n", "summary" : "

    Returns information about a database.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    a database name
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object describing the specified database" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 5, "name" : "delete-attachment", "qname" : "cloudant:delete-attachment", "signature" : "($connection as anyURI, $database as string, $document-id as string, $document-rev as string, $attachment-name as string) as object()", "description" : "

    Deletes the specified attachment.

    \n

    The latest document revision must be specified.

    \n

    For example,\n

    cloudant:delete-attachment($connection, \"db\", \"FishStew\",\n   \"8-7c4740b4dcf26683e941d6641c00c39d\", \"AttachmentName\")
    .\n

    \n

    Deleting a design document attachment.

    \n

    To delete a design document attachment the document id must\n start with _design/.

    \n

    For example,\n

    cloudant:delete-attachment($connection, \"db\", \"_design/DesDocId\",\n   \"8-7c4740b4dcf26683e941d6641c00c39d\",\n   \"AttachmentName\", \"text/plain\", \"AttachmentContent\")
    .\n

    \n

    Return value

    \n

    The returned object reports the document id and its new\n revision, as follows:\n

    \n {\n   \"id\":\"FishStew\",\n   \"ok\":true,\n   \"rev\":\"9-247bb19a41bfd9bfdaf5ee6e2e05be74\"\n }\n 
    \n

    \n", "summary" : "

    Deletes the specified attachment.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "document-rev", "type" : "string", "occurrence" : null, "description" : "
    A document revision
    " }, { "name" : "attachment-name", "type" : "string", "occurrence" : null, "description" : "
    The name of the attachment
    " } ], "returns" : { "type" : "object()", "description" : "An object containing the document id and its new revision" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:ATTACHMENT-NOT-EXISTS Attachment does not exists", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:ATTACHMENT-TYPE Attachment type must be string, base64Binary or hexBinary", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 6, "name" : "delete-attachment", "qname" : "cloudant:delete-attachment", "signature" : "($connection as anyURI, $database as string, $document-id as string, $document-rev as string, $attachment-name as string, $options as object()) as object()", "description" : "

    Deletes the specified attachment.

    \n

    The latest document revision must be specified.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • database-owner: specifies the database owner (string, default: connection user).
    • \n
    \n

    \n

    For example,\n

    cloudant:delete-attachment($connection, \"db\", \"FishStew\",\n \"8-7c4740b4dcf26683e941d6641c00c39d\", \"AttachmentName\",\n {\"database-owner\": \"username\"})
    .\n

    \n

    Deleting a design document attachment.

    \n

    To delete a design document attachment the document id must\n start with _design/.

    \n

    For example,\n

    cloudant:delete-attachment($connection, \"db\", \"_design/DesDocId\",\n   \"8-7c4740b4dcf26683e941d6641c00c39d\", \"AttachmentName\", \"text/plain\",\n   \"AttachmentContent\", {\"database-owner\": \"username\"})
    .\n

    \n

    Return value

    \n

    The returned object reports the document id and its new\n revision, as follows:\n

    \n {\n   \"id\":\"FishStew\",\n   \"ok\":true,\n   \"rev\":\"9-247bb19a41bfd9bfdaf5ee6e2e05be74\"\n }\n 
    \n

    \n", "summary" : "

    Deletes the specified attachment.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "document-rev", "type" : "string", "occurrence" : null, "description" : "
    A document revision
    " }, { "name" : "attachment-name", "type" : "string", "occurrence" : null, "description" : "
    The name of the attachment
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object containing the document id and its new revision" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:ATTACHMENT-NOT-EXISTS Attachment does not exists", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:ATTACHMENT-TYPE Attachment type must be string, base64Binary or hexBinary", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 2, "name" : "delete-database", "qname" : "cloudant:delete-database", "signature" : "($connection as anyURI, $database as string) as empty-sequence()", "description" : "

    Deletes a database and all the documents and attachments contained in it.

    \n

    The database name must be composed of one or more of the following characters:\n

      \n
    • Lowercase characters (a-z).
    • \n
    • Digits (0-9).
    • \n
    • Any of the characters: _,$,(,),+,- and /.
    • \n
    \n

    \n

    For example,\n

    cloudant:delete-database($connection, \"db\")
    .\n

    \n", "summary" : "

    Deletes a database and all the documents and attachments contained in it.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "Empty sequence" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:DATABASE-NOT-EXISTS Database does not exist", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 4, "name" : "delete-document", "qname" : "cloudant:delete-document", "signature" : "($connection as anyURI, $database as string, $document-id as string, $document-rev as string) as object()", "description" : "

    Deletes the specified document from a database.

    \n

    The latest document revision must be specified.

    \n

    For example,\n

    \n cloudant:delete-document($connection, \"db\", \"DocID\", \"3-7c4740b4dcf26683e941d6641c00c39d\")\n 
    .\n

    \n

    Deleting a design document

    \n

    To delete a design document the document id must\n start with _design/.

    \n

    For example,\n

    \n cloudant:delete-document($connection, \"db\", \"_design/DesDocID\", \"3-7c4740b4dcf26683e941d6641c00c39d\")\n 
    .\n

    \n

    Return value

    \n

    The returned object reports the document id and its\n new revision, as follows:\n

    \n {\n   \"id\":\"DocID\",\n   \"ok\":true,\n   \"rev\":\"4-2719fd41187c60762ff584761b714cfb\"\n }\n 
    \n

    \n", "summary" : "

    Deletes the specified document from a database.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "document-rev", "type" : "string", "occurrence" : null, "description" : "
    A document revision
    " } ], "returns" : { "type" : "object()", "description" : "An object which specifies the document id and its new revision" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:REVISION Specified revision is missing, invalid or not the latest.", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 5, "name" : "delete-document", "qname" : "cloudant:delete-document", "signature" : "($connection as anyURI, $database as string, $document-id as string, $document-rev as string, $options as object()) as object()", "description" : "

    Deletes the specified document from a database.

    \n

    The latest document revision must be specified.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • database-owner: specifies the database owner (string, default: connection user).
    • \n
    \n

    \n

    For example,\n

    \n cloudant:delete-document($connection, \"db\", \"DocID\", \"3-7c4740b4dcf26683e941d6641c00c39d\",\n   {\"database-owner\": \"username\"})\n 
    .\n

    \n

    Deleting a design document

    \n

    To delete a design document the document id must\n start with _design/.

    \n

    For example,\n

    \n cloudant:delete-document($connection, \"db\", \"_design/DesDocID\", \"3-7c4740b4dcf26683e941d6641c00c39d\",\n   {\"database-owner\": \"username\"})\n 
    .\n

    \n

    Return value

    \n

    The returned object reports the document id and its\n new revision, as follows:\n

    \n {\n   \"id\":\"DocID\",\n   \"ok\":true,\n   \"rev\":\"4-2719fd41187c60762ff584761b714cfb\"\n }\n 
    \n

    \n", "summary" : "

    Deletes the specified document from a database.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "document-rev", "type" : "string", "occurrence" : null, "description" : "
    A document revision
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object which specifies the document id and its new revision" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:REVISION Specified revision is missing, invalid or not the latest.", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 3, "name" : "document-info-nondeterministic", "qname" : "cloudant:document-info-nondeterministic", "signature" : "($connection as anyURI, $database as string, $document-id as string) as object()", "description" : "

    Returns the latest revision and size for a given document.

    \n

    This function has the same semantics as\n document-info#3,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Returns the latest revision and size for a given document.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " } ], "returns" : { "type" : "object()", "description" : "An object specifying the document id, revision and size" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DOCUMENT The specified document or revision cannot be found", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 4, "name" : "document-info-nondeterministic", "qname" : "cloudant:document-info-nondeterministic", "signature" : "($connection as anyURI, $database as string, $document-id as string, $options as object()) as object()", "description" : "

    Returns the latest revision and size for a given document.

    \n

    This function has the same semantics as\n document-info#4,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Returns the latest revision and size for a given document.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object specifying the document id, revision and size" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DOCUMENT The specified document or revision cannot be found", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 3, "name" : "document-info", "qname" : "cloudant:document-info", "signature" : "($connection as anyURI, $database as string, $document-id as string) as object()", "description" : "

    Returns the latest revision and size for a given document.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    For example,\n

    cloudant:document-info($connection, \"db\", \"DocID\")
    .\n

    \n

    The format of the returned object is the following and contains\n the document id, latest revision and size.\n

    \n {\n   \"ok\": true,\n   \"id\": \"DocID\",\n   \"rev\": \"1-764b9b11845fd0b73cfa0e61acc74ecf\",\n   \"size\": 500\n }\n 
    \n

    \n

    Returning the latest revision and size for a given design document

    \n

    To return the latest revision and size of a design document the document\n id must start with\n _design/.

    \n

    For example,\n

    cloudant:document-info($connection, \"db\", \"_design/DesDocID\")
    .\n

    \n", "summary" : "

    Returns the latest revision and size for a given document.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " } ], "returns" : { "type" : "object()", "description" : "An object specifying the document id, revision and size" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DOCUMENT The specified document or revision cannot be found", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 4, "name" : "document-info", "qname" : "cloudant:document-info", "signature" : "($connection as anyURI, $database as string, $document-id as string, $options as object()) as object()", "description" : "

    Returns the latest revision and size for a given document.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • database-owner: specifies the database owner (string, default: connection user).
    • \n
    \n

    \n

    For example,\n

    \n cloudant:document-info($connection, \"db\", \"DocID\", {\"database-owner\": \"username\"})\n 
    .\n

    \n

    The format of the returned object is the following and contains\n the document id, latest revision and size.\n

    \n {\n   \"ok\": true,\n   \"id\": \"DocID\",\n   \"rev\": \"1-764b9b11845fd0b73cfa0e61acc74ecf\",\n   \"size\": 500\n }\n 
    \n

    \n

    Returning the latest revision and size for a given design document

    \n

    To return the latest revision and size of a design document the document\n id must start with _design/.

    \n

    For example,\n

    \n cloudant:document-info($connection, \"db\", \"_design/DesDocID\", {\"database-owner\": \"username\"})\n 
    .\n

    \n", "summary" : "

    Returns the latest revision and size for a given document.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object specifying the document id, revision and size" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DOCUMENT The specified document or revision cannot be found", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 3, "name" : "document-nondeterministic", "qname" : "cloudant:document-nondeterministic", "signature" : "($connection as anyURI, $database as string, $document-id as string) as object()", "description" : "

    Retrieves a document from the specified database.

    \n

    This function has the same semantics as document#3,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves a document from the specified database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " } ], "returns" : { "type" : "object()", "description" : "The specified document" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:DOCUMENT The specified document or revision cannot be found", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 4, "name" : "document-nondeterministic", "qname" : "cloudant:document-nondeterministic", "signature" : "($connection as anyURI, $database as string, $document-id as string, $options as object()) as object()", "description" : "

    Retrieves a document from the specified database

    \n

    This function has the same semantics as document#4,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Retrieves a document from the specified database \n This function has the same semantics as document#4 ,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "The specified document" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:DOCUMENT The specified document or revision cannot be found", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 3, "name" : "document", "qname" : "cloudant:document", "signature" : "($connection as anyURI, $database as string, $document-id as string) as object()", "description" : "

    Retrieves a document from the specified database.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The latest revision of the document will be returned.

    \n

    If the document includes attachments, then the\n returned structure will contain a summary of the\n attachments associated with the document, but not the\n attachment data itself.

    \n

    For example,\n

    cloudant:document($connection, \"db\", \"DocID\")
    .\n

    \n

    The returned JSON object will contain the document\n and has the following format:\n

    \n {\n   \"_id\": \"DocID\",\n   \"_rev\": \"2-f29c836d0bedc4b4b95cfaa6d99e95df\",\n   \"name\": \"Anna\",\n   \"age\": 89,\n   \"gender\": \"female\",\n   \"_attachments\": {\n     \"my attachment\": {\n       \"content_type\": \"application/json; charset=UTF-8\",\n       \"revpos\": 2,\n       \"digest\": \"md5-37IZysiyWLRWx31J/1WQHw==\",\n       \"length\": 12,\n       \"stub\": true\n       }\n     }\n   }\n 
    \n

    \n

    \n The meaning of the fields in the returned object is the following:\n

      \n
    • _id: document ID
    • \n
    • _rev: document revision
    • \n
    • attachments: document attachments (optional), each field denotes the name\n of a different attachment\n
        \n
      • content_type: attachment MIME Content type string
      • \n
      • length: attachment length in bytes
      • \n
      • revpos: revision where this attachment exists
      • \n
      • digest: MD5 checksum of the attachment
      • \n
      • stub: indicates whether the attachment is a stub
      • \n
      \n
    • \n
    \n

    \n

    Retrieving a design document from the specified database

    \n

    To retrieve a design document the document id must start with\n _design/.

    \n

    For example,\n

    cloudant:document($connection, \"db\", \"_design/DesDocID\")
    .\n

    \n

    A JSON object with the following format is returned:\n

    \n {\n  \"_id\": \"_design/DesDocID\",\n   \"views\": {\n     \"view1\": {\n       \"map\":\"function(doc){emit(doc.field, 1)}\",\n       \"reduce\": \"function(key, value, rereduce){return sum(values)}\"\n     }\n   },\n   \"indexes\": {\n     \"mysearch\" : {\n       \"analyzer\": {\"name\": \"portuguese\", \"stopwords\":[\"foo\", \"bar, \"baz\"]},\n       \"index\": \"function(doc){ ... }\"\n     },\n   }\n }\n 
    \n

    \n

    \n The meaning of the fields in the returned object is the following:\n

      \n
    • _id: document ID
    • \n
    • _rev: document revision
    • \n
    • views: object defining the views. Each field defines a different view.\n The field name is the name of the view and has the following content:\n
        \n
      • map: view map function
      • \n
      • reduce: view reduce function (optional)
      • \n
      \n
    • \n
    • indexes: object defining the view indexes. Each field defines a different index.\n The field name is the name of the index and has the following content:\n
        \n
      • analyzer: Name of the analyzer to be used or an object with the\n following fields:\n
          \n
        • name: Name of the analyzer
        • \n
        • stopwords: An array of stop words. Stop words are words that\n should not be indexed.
        • \n
        \n
      • \n
      • index: Function that handles the indexing
      • \n
      \n
    • \n
    \n

    \n", "summary" : "

    Retrieves a document from the specified database.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " } ], "returns" : { "type" : "object()", "description" : "The specified document" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:DOCUMENT The specified document or revision cannot be found", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 4, "name" : "document", "qname" : "cloudant:document", "signature" : "($connection as anyURI, $database as string, $document-id as string, $options as object()) as object()", "description" : "

    Retrieves a document from the specified database

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Unless you request a specific revision, the latest\n revision of the document will always be returned.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • conflict: returns the conflict tree for the document (boolean)
    • \n
    • rev: specifies the revision to return (string)
    • \n
    • revs: return a list of the revisions for the document (boolean)
    • \n
    • revs_info: return a list of detailed revision information for the document\n (boolean, allowed value: true)
    • \n
    • database-owner: specifies the database owner (string, default: connection user).
    • \n
    \n

    \n

    If the document includes attachments, then the\n returned structure will contain a summary of the\n attachments associated with the document, but not the\n attachment data itself.

    \n

    For example,\n

    \n cloudant:document($connection, \"db\", \"DocID\", {\"database-owner\": \"username\"})\n 
    .\n

    \n

    The returned JSON object will contain the document\n and has the following format:\n

    \n {\n   \"_id\": \"DocID\",\n   \"_rev\": \"2-f29c836d0bedc4b4b95cfaa6d99e95df\",\n   \"name\": \"Anna\",\n   \"age\": 89,\n   \"gender\": \"female\",\n   \"_attachments\": {\n     \"my attachment\": {\n       \"content_type\": \"application/json; charset=UTF-8\",\n       \"revpos\": 2,\n       \"digest\": \"md5-37IZysiyWLRWx31J/1WQHw==\",\n       \"length\": 12,\n       \"stub\": true\n       }\n     }\n   }\n 
    \n

    \n

    \n The meaning of the fields in the returned object is the following:\n

      \n
    • _id: document ID
    • \n
    • _rev: document revision
    • \n
    • attachments: document attachments (optional), each field denotes the name\n of a different attachment:\n
        \n
      • content_type: attachment MIME Content type string
      • \n
      • length: attachment length in bytes
      • \n
      • revpos: revision where this attachment exists
      • \n
      • digest: MD5 checksum of the attachment
      • \n
      • stub: indicates whether the attachment is a stub
      • \n
      \n
    • \n
    \n

    \n

    Retrieving a design document from the specified database

    \n

    To retrieve a design document the document id must start with\n _design/.

    \n

    For example,\n

    cloudant:document($connection, \"db\", \"_design/DesDocID\", {\"database-owner\": \"username\"})
    .\n

    \n

    A JSON object with the following format is returned:\n

    \n {\n  \"_id\": \"_design/DesDocID\",\n  \"_rev\": \"2-f29c836d0bedc4b4b95cfaa6d99e95df\",\n   \"views\": {\n     \"view1\": {\n       \"map\":\"function(doc){emit(doc.field, 1)}\",\n       \"reduce\": \"function(key, value, rereduce){return sum(values)}\"\n     }\n   },\n   \"indexes\": {\n     \"mysearch\" : {\n       \"analyzer\": {\"name\": \"portuguese\", \"stopwords\":[\"foo\", \"bar, \"baz\"]},\n       \"index\": \"function(doc){ ... }\"\n     },\n   }\n }\n 
    \n

    \n

    \n The meaning of the fields in the returned object is the following:\n

      \n
    • _id: document ID
    • \n
    • _rev: document revision
    • \n
    • views: object defining the views. Each field defines a different view.\n The field name is the name of the view and has the following content:\n
        \n
      • map: view map function
      • \n
      • reduce: view reduce function (optional)
      • \n
      \n
    • \n
    • indexes: object defining the view indexes. Each field defines a different index.\n The field name is the name of the index and has the following content:\n
        \n
      • analyzer: Name of the analyzer to be used or an object with the\n following fields:\n
          \n
        • name: Name of the analyzer
        • \n
        • stopwords: An array of stop words. Stop words are words that\n should not be indexed.
        • \n
        \n
      • \n
      • index: Function that handles the indexing
      • \n
      \n
    • \n
    \n

    \n

    Getting a List of Revisions

    \n

    You can obtain a list of the revisions for a given document\n by the revs option.

    \n

    For example,\n

    cloudant:document($connection, \"db\", \"DocID\", {\"revs\": true})
    .\n

    \n

    The returned JSON object includes the original document and\n a _revisions structure that includes the revision\n information:\n

    \n {\n   \"servings\":4,\n   \"subtitle\":\"Delicious with a green salad\",\n   \"_id\":\"FishStew\",\n   \"title\":\"Irish Fish Stew\",\n   \"_revisions\":\n   {\n     \"ids\": [\n       \"a1a9b39ee3cc39181b796a69cb48521c\",\n       \"7c4740b4dcf26683e941d6641c00c39d\",\n       \"9c65296036141e575d32ba9c034dd3ee\"\n      ],\n     \"start\":3\n  },\n  \"_rev\":\"3-a1a9b39ee3cc39181b796a69cb48521c\"\n }\n 
    \n

    \n

    The meaning of the additional fields is the following:\n

      \n
    • _revisions: document revisions
    • \n
    • _ids: array of valid revision IDs, in reverse order (latest first)
    • \n
    • start: prefix number for the latest revision
    • \n
    \n

    \n

    Obtaining an Extended Revision History

    \n

    You can get additional information about the revisions for a given document\n with the revs_info option.

    \n

    For example,\n

    cloudant:document($connection, \"db\", \"DocID\", {\"revs_info\": true})
    .\n

    \n

    This returns extended revision information, including the availability and status\n of each revision:\n

    \n {\n   \"servings\":4,\n   \"subtitle\":\"Delicious with a green salad\",\n   \"_id\":\"FishStew\",\n   \"_revs_info\":[\n     {\n       \"status\":\"available\",\n       \"rev\":\"3-a1a9b39ee3cc39181b796a69cb48521c\"\n     },\n     {\n       \"status\":\"available\",\n       \"rev\":\"2-7c4740b4dcf26683e941d6641c00c39d\"\n     },\n     {\n       \"status\":\"available\",\n       \"rev\":\"1-9c65296036141e575d32ba9c034dd3ee\"\n     }\n   ],\n   \"title\":\"Irish Fish Stew\",\n   \"_rev\":\"3-a1a9b39ee3cc39181b796a69cb48521c\"\n }\n 
    \n

    \n

    The meaning of the additional fields is the following:\n

      \n
    • _revs_info: document extended revision info
    • \n
    • rev: revision ID
    • \n
    • status: revision status
    • \n
    \n

    \n", "summary" : "

    Retrieves a document from the specified database \n This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "document-id", "type" : "string", "occurrence" : null, "description" : "
    A document identifier
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "The specified document" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:DATABASE-NAME Invalid database name", "cloudant:DOCUMENT The specified document or revision cannot be found", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 1, "name" : "list-databases-nondeterministic", "qname" : "cloudant:list-databases-nondeterministic", "signature" : "($connection as anyURI) as array()", "description" : "

    Returns an array containing the names of all the user's databases.

    \n

    This function has the same semantics as\n list-databases#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Returns an array containing the names of all the user's databases.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " } ], "returns" : { "type" : "array()", "description" : "An array of all the database names" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-databases-nondeterministic", "qname" : "cloudant:list-databases-nondeterministic", "signature" : "($connection as anyURI, $options as object()) as array()", "description" : "

    Returns an array containing the names of all the user's databases.

    \n

    This function has the same semantics as\n list-databases#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Returns an array containing the names of all the user's databases.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "array()", "description" : "An array of all the databases names" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 1, "name" : "list-databases", "qname" : "cloudant:list-databases", "signature" : "($connection as anyURI) as array()", "description" : "

    Returns an array containing the names of all the user's databases.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    For example,\n

    cloudant:list-databases($connection)
    .\n

    \n", "summary" : "

    Returns an array containing the names of all the user's databases.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " } ], "returns" : { "type" : "array()", "description" : "An array of all the database names" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 2, "name" : "list-databases", "qname" : "cloudant:list-databases", "signature" : "($connection as anyURI, $options as object()) as array()", "description" : "

    Returns an array containing the names of all the user's databases.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • database-owner: specifies the database owner (string, default: connection user).
    • \n
    \n

    \n

    For example,\n

    cloudant:list-databases($connection, {\"database-owner\" : \"username\"})
    .\n

    \n", "summary" : "

    Returns an array containing the names of all the user's databases.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "array()", "description" : "An array of all the databases names" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 5, "name" : "lucene-query-nondeterministic", "qname" : "cloudant:lucene-query-nondeterministic", "signature" : "($connection as anyURI, $database as string, $design-document as string, $index as string, $query as string) as object()", "description" : "

    Executes a Lucene query against a view and returns the query result.

    \n

    This function has the same semantics as\n lucene-query#5,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Executes a Lucene query against a view and returns the query result.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "design-document", "type" : "string", "occurrence" : null, "description" : "
    A design document name
    " }, { "name" : "index", "type" : "string", "occurrence" : null, "description" : "
    An index name
    " }, { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A Lucene query
    " } ], "returns" : { "type" : "object()", "description" : "The Lucene query results" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 6, "name" : "lucene-query-nondeterministic", "qname" : "cloudant:lucene-query-nondeterministic", "signature" : "($connection as anyURI, $database as string, $design-document as string, $index as string, $query as string, $options as object()) as object()", "description" : "

    Executes a Lucene query against a view and returns the query result.

    \n

    This function has the same semantics as lucene-query#6,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Executes a Lucene query against a view and returns the query result.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "design-document", "type" : "string", "occurrence" : null, "description" : "
    A design document name
    " }, { "name" : "index", "type" : "string", "occurrence" : null, "description" : "
    An index name
    " }, { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A Lucene query
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "The Lucene query results" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 5, "name" : "lucene-query", "qname" : "cloudant:lucene-query", "signature" : "($connection as anyURI, $database as string, $design-document as string, $index as string, $query as string) as object()", "description" : "

    Executes a Lucene query against a view and returns the query result.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    This method searches for documents whose index fields match the Lucene query.\n Which fields of a document are indexed and how is determined by the index functions\n in the design document.

    \n

    The information is returned as a JSON structure containing meta information\n about the return structure, and the list of documents each with its ID, revision\n and key. The key is generated from the document ID.

    \n

    For example,\n

    cloudant:lucene-query($connection, \"db\", \"designdoc\", \"view\", \"a*\")
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"total_rows\": 3,\n   \"bookmark\": \"g1AAAACWeJzLYWBgYMpgTmFQSElKzi9KdUhJMtbLTS3KLElMT9VLzskvTUnMK9HLSy3JAalMcgCSSfX____PAvPdQHwQSGTIIt6UPBaQlgNA6j_CJPsPcJOyANNEKzY\",\n   \"rows\":\n   [\n     {\n       \"id\": \"dd828eb4-c3f1-470f-aeff-c375ef70e4ad\",\n       \"order\": [0.0, 1],\n       \"fields\":\n       {\n         \"default\": \"aa\",\n         \"foo\": 0.0\n       }\n     },\n     {\n       \"id\": \"ea522cf1-eb8e-4477-aa92-d1fa459bb216\",\n       \"order\": [1.0, 0],\n       \"fields\":\n       {\n         \"default\": \"ab\",\n         \"foo\": 1.0\n       }\n     },\n     {\n       \"id\": \"c838baed-d573-43ea-9c34-621cf0f13301\",\n       \"order\": [2.0, 0],\n       \"fields\":\n       {\n         \"default\": \"ac\",\n         \"foo\": 2.0\n       }\n     }\n   ]\n }\n 
    \n

    \n

    The fields have the following meaning:\n

      \n
    • total_rows: number of results returned.
    • \n
    • bookmark: string to be submitted in the next query to page through results.\n If this response contained no results, the bookmark will be the same as the\n one used to obtain this response.
    • \n
    • rows: array of document objects, each document contains the following fields:\n
        \n
      • order: specifies the order with regard to the indexed fields.
      • \n
      • fields: Object containing other search indexes.
      • \n
      \n
    • \n
    \n

    \n", "summary" : "

    Executes a Lucene query against a view and returns the query result.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "design-document", "type" : "string", "occurrence" : null, "description" : "
    A design document name
    " }, { "name" : "index", "type" : "string", "occurrence" : null, "description" : "
    An index name
    " }, { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A Lucene query
    " } ], "returns" : { "type" : "object()", "description" : "The Lucene query results" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 6, "name" : "lucene-query", "qname" : "cloudant:lucene-query", "signature" : "($connection as anyURI, $database as string, $design-document as string, $index as string, $query as string, $options as object()) as object()", "description" : "

    Executes a Lucene query against a view and returns the query result.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    This method searches for documents whose index fields match the Lucene query.\n Which fields of a document are indexed and how is determined by the index functions\n in the design document.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • bookmark: A bookmark that was received from a previous search. This\n allows you to page through the results. If there are no more results after\n the bookmark, you will get a response with an empty rows array and the\n same bookmark. That way you can determine that you have reached the end\n of the result list (string).
    • \n
    • stale: allow the results from a stale view to be used (string, allowed\n value: \"ok\").
    • \n
    • limit: limit the number of the returned documents to the specified\n number (numeric).
    • \n
    • include_docs: include the full content of the documents in the return\n (boolean, default: false).
    • \n
    • sort: specifies the sort order of the results. A JSON string of the\n form \"fieldname<type>\" or -fieldname<type>\n for descending order, where fieldname is the name of a string or number field\n and type is either number or string. The type part is optional and defaults\n to number. Some examples are \"foo\", \"-foo\",\n \"bar<string>\", \"-foo<number>\". String\n fields used for sorting must not be analyzed fields. The field(s) used for\n sorting must be indexed by the same indexer used for the search query.\n Alternatively, a JSON array of such strings is allowed.
    • \n
    \n

    \n

    The information is returned as a JSON structure containing meta information\n about the return structure, and the list of documents each with its ID, revision\n and key. The key is generated from the document ID.

    \n

    For example,\n

    cloudant:lucene-query($connection, \"db\", \"designdoc\", \"view\", \"a*\",\n {\"database-owner\": \"username\"})
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"total_rows\": 3,\n   \"bookmark\": \"g1AAAACWeJzLYWBgYMpgTmFQSElKzi9KdUhJMtbLTS3KLElMT9VLzskvTUnMK9HLSy3JAalMcgCSSfX____PAvPdQHwQSGTIIt6UPBaQlgNA6j_CJPsPcJOyANNEKzY\",\n   \"rows\":\n   [\n     {\n       \"id\": \"dd828eb4-c3f1-470f-aeff-c375ef70e4ad\",\n       \"order\": [0.0, 1],\n       \"fields\":\n       {\n         \"default\": \"aa\",\n         \"foo\": 0.0\n       }\n     },\n     {\n       \"id\": \"ea522cf1-eb8e-4477-aa92-d1fa459bb216\",\n       \"order\": [1.0, 0],\n       \"fields\":\n       {\n         \"default\": \"ab\",\n         \"foo\": 1.0\n       }\n     },\n     {\n       \"id\": \"c838baed-d573-43ea-9c34-621cf0f13301\",\n       \"order\": [2.0, 0],\n       \"fields\":\n       {\n         \"default\": \"ac\",\n         \"foo\": 2.0\n       }\n     }\n   ]\n }\n 
    \n

    \n

    The fields have the following meaning:\n

      \n
    • total_rows: number of results returned.
    • \n
    • bookmark: string to be submitted in the next query to page through results.\n If this response contained no results, the bookmark will be the same as the\n one used to obtain this response.
    • \n
    • rows: array of document objects, each document contains the following fields:\n
        \n
      • order: specifies the order with regard to the indexed fields.
      • \n
      • fields: Object containing other search indexes.
      • \n
      \n
    • \n
    \n

    \n", "summary" : "

    Executes a Lucene query against a view and returns the query result.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "design-document", "type" : "string", "occurrence" : null, "description" : "
    A design document name
    " }, { "name" : "index", "type" : "string", "occurrence" : null, "description" : "
    An index name
    " }, { "name" : "query", "type" : "string", "occurrence" : null, "description" : "
    A Lucene query
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "The Lucene query results" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 3, "name" : "multiple-documents-nondeterministic", "qname" : "cloudant:multiple-documents-nondeterministic", "signature" : "($connection as anyURI, $database as string, $keys as string*) as object()", "description" : "

    List the specified documents in a given database.

    \n

    This function has the same semantics as\n multiple-documents#3,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    List the specified documents in a given database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "keys", "type" : "string", "occurrence" : "*", "description" : "
    The keys of the documents which must be retrieved
    " } ], "returns" : { "type" : "object()", "description" : "An object listing the specified documents in the specified database" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 4, "name" : "multiple-documents-nondeterministic", "qname" : "cloudant:multiple-documents-nondeterministic", "signature" : "($connection as anyURI, $database as string, $keys as string*, $options as object()) as object()", "description" : "

    Lists the specified documents in a given database.

    \n

    This function has the same semantics as\n multiple-documents#4,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists the specified documents in a given database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "keys", "type" : "string", "occurrence" : "*", "description" : "
    The keys of the documents which must be retrieved
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object listing the specified documents in the specified database" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 3, "name" : "multiple-documents", "qname" : "cloudant:multiple-documents", "signature" : "($connection as anyURI, $database as string, $keys as string*) as object()", "description" : "

    List the specified documents in a given database.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The information is returned as a JSON structure containing meta information\n about the return structure, and the list of documents each with its ID, revision\n and key. The key is generated from the document ID.

    \n

    For example,\n

    cloudant:multiple-documents($connection, \"db\",\n   (\"5a049246-179f-42ad-87ac-8f080426c17c\",\n    \"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n    \"96f898f0-f6ff-4a9b-aac4-503992f31b01\"))
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"total_rows\":3,\n   \"offset\":0,\n   \"rows\":[\n   {\n     \"id\":\"5a049246-179f-42ad-87ac-8f080426c17c\",\n     \"key\":\"5a049246-179f-42ad-87ac-8f080426c17c\",\n     \"value\":\n     {\n       \"rev\":\"2-9d5401898196997853b5ac4163857a29\"\n     }\n   },\n   {\n     \"id\":\"96f898f0-f6ff-4a9b-aac4-503992f31b01\",\n     \"key\":\"96f898f0-f6ff-4a9b-aac4-503992f31b01\",\n     \"value\":\n     {\n       \"rev\":\"2-ff7b85665c4c297838963c80ecf481a3\"\n      }\n   },\n   {\n     \"id\":\"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n     \"key\":\"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n     \"value\":\n     {\n       \"rev\":\"2-cbdef49ef3ddc127eff86350844a6108\"\n     }\n   }]\n }\n 
    \n

    \n

    The fields have the following meaning:\n

      \n
    • offset: offset where the document list started.
    • \n
    • rows: array of document objects, each containing id, key and revision number.
    • \n
    • total_rows: number of documents in the database.
    • \n
    • update_seq: current update sequence database.
    • \n
    \n

    \n", "summary" : "

    List the specified documents in a given database.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "keys", "type" : "string", "occurrence" : "*", "description" : "
    The keys of the documents which must be retrieved
    " } ], "returns" : { "type" : "object()", "description" : "An object listing the specified documents in the specified database" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 4, "name" : "multiple-documents", "qname" : "cloudant:multiple-documents", "signature" : "($connection as anyURI, $database as string, $keys as string*, $options as object()) as object()", "description" : "

    Lists the specified documents in a given database.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The information is returned as a JSON structure containing meta information\n about the return structure, and the list of documents each with its ID, revision\n and key. The key is generated from the document ID.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • descending: return the documents in descending by key order (boolean,\n default: false).
    • \n
    • endkey: stop returning records when the specified key is reached (string).
    • \n
    • endkey_docid: stop returning records when the specified document ID is\n reached (string).
    • \n
    • group: group the results using the reduce function to a group or single\n row (boolean, default: false).
    • \n
    • group_level: specify the group level to be used (numeric).
    • \n
    • include_docs: include the full content of the documents in the return\n (boolean, default: false).
    • \n
    • inclusive_end: specifies whether the specified end key should be included\n in the result (boolean, default: true).
    • \n
    • key: return only documents that match the specified key (string).
    • \n
    • limit: limit the number of the returned documents to the specified number\n (numeric).
    • \n
    • reduce: use the reduction function (boolean, default: true).
    • \n
    • skip: skip this number of records before starting to return the results\n (numeric, default: 0).
    • \n
    • stale: allow the results from a stale view to be used (string, allowed\n value: \"ok\").
    • \n
    • startkey: start returning records when the specified key is reached\n (string).
    • \n
    • startkey_docid: start returning records when the specified document ID\n is reached (string).
    • \n
    • database-owner: specifies the database owner (string, default: connection\n user).
    • \n
    \n

    \n

    For example,\n

    cloudant:multiple-documents($connection, \"db\",\n   (\"5a049246-179f-42ad-87ac-8f080426c17c\",\n    \"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n    \"96f898f0-f6ff-4a9b-aac4-503992f31b01\"),\n   {\"database-owner\": \"username\"})
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"total_rows\":3,\n   \"offset\":0,\n   \"rows\":[\n   {\n     \"id\":\"5a049246-179f-42ad-87ac-8f080426c17c\",\n     \"key\":\"5a049246-179f-42ad-87ac-8f080426c17c\",\n     \"value\":\n     {\n       \"rev\":\"2-9d5401898196997853b5ac4163857a29\"\n     }\n   },\n   {\n     \"id\":\"96f898f0-f6ff-4a9b-aac4-503992f31b01\",\n     \"key\":\"96f898f0-f6ff-4a9b-aac4-503992f31b01\",\n     \"value\":\n     {\n       \"rev\":\"2-ff7b85665c4c297838963c80ecf481a3\"\n      }\n   },\n   {\n     \"id\":\"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n     \"key\":\"d1f61e66-7708-4da6-aa05-7cbc33b44b7e\",\n     \"value\":\n     {\n       \"rev\":\"2-cbdef49ef3ddc127eff86350844a6108\"\n     }\n   }]\n }\n 
    \n

    \n

    The fields have the following meaning:\n

      \n
    • offset: offset where the document list started.
    • \n
    • rows: array of document objects, each containing id, key and revision number.
    • \n
    • total_rows: number of documents in the database.
    • \n
    • update_seq: current update sequence database.
    • \n
    \n

    \n", "summary" : "

    Lists the specified documents in a given database.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "keys", "type" : "string", "occurrence" : "*", "description" : "
    The keys of the documents which must be retrieved
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object listing the specified documents in the specified database" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 5, "name" : "multiple-view-documents-nondeterministic", "qname" : "cloudant:multiple-view-documents-nondeterministic", "signature" : "($connection as anyURI, $database as string, $design-document as string, $view as string, $keys as string*) as object()", "description" : "

    List the specified documents in a given view.

    \n

    This function has the same semantics as\n multiple-view-documents#5,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    List the specified documents in a given view.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "design-document", "type" : "string", "occurrence" : null, "description" : "
    A design document name
    " }, { "name" : "view", "type" : "string", "occurrence" : null, "description" : "
    A view name
    " }, { "name" : "keys", "type" : "string", "occurrence" : "*", "description" : "
    The keys of the documents which must be retrieved
    " } ], "returns" : { "type" : "object()", "description" : "An object listing all the specified documents in the specified view" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 6, "name" : "multiple-view-documents-nondeterministic", "qname" : "cloudant:multiple-view-documents-nondeterministic", "signature" : "($connection as anyURI, $database as string, $design-document as string, $view as string, $keys as string*, $options as object()) as object()", "description" : "

    Lists the specified documents in a given view.

    \n

    This function has the same semantics as\n multiple-view-documents#6,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Lists the specified documents in a given view.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "design-document", "type" : "string", "occurrence" : null, "description" : "
    A design document name
    " }, { "name" : "view", "type" : "string", "occurrence" : null, "description" : "
    A view name
    " }, { "name" : "keys", "type" : "string", "occurrence" : "*", "description" : "
    The keys of the documents which must be retrieved
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object listing all the specified documents in the specified view" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] }, { "isDocumented" : true, "arity" : 5, "name" : "multiple-view-documents", "qname" : "cloudant:multiple-view-documents", "signature" : "($connection as anyURI, $database as string, $design-document as string, $view as string, $keys as string*) as object()", "description" : "

    List the specified documents in a given view.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The information is returned as a JSON structure containing meta information\n about the return structure, and the list of documents each with its ID, revision\n and key. The key is generated from the document ID.

    \n

    For example,\n

    cloudant:multiple-view-documents($connection, \"db\", \"recipes\", \"by_ingredient\",\n (\"claret\", \"clear apple juice\"))\n 
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"total_rows\" : 26484,\n   \"rows\" : [\n     {\n       \"value\" : [\"Scotch collops\"]],\n       \"id\" : \"Scotchcollops\",\n       \"key\" : \"claret\"\n     },\n     {\n       \"value\" : [\"Stand pie\"],\n       \"id\" : \"Standpie\",\n       \"key\" : \"clear apple juice\"\n     }\n   ],\n   \"offset\" : 6324\n }\n 
    \n

    \n

    The fields have the following meaning:\n

      \n
    • offset: offset where the document list started.
    • \n
    • rows: array of document objects, each containing id, key and revision\n number.
    • \n
    • total_rows: number of documents in the database.
    • \n
    • update_seq: current update sequence database.
    • \n
    \n

    \n", "summary" : "

    List the specified documents in a given view.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "design-document", "type" : "string", "occurrence" : null, "description" : "
    A design document name
    " }, { "name" : "view", "type" : "string", "occurrence" : null, "description" : "
    A view name
    " }, { "name" : "keys", "type" : "string", "occurrence" : "*", "description" : "
    The keys of the documents which must be retrieved
    " } ], "returns" : { "type" : "object()", "description" : "An object listing all the specified documents in the specified view" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error" ] }, { "isDocumented" : true, "arity" : 6, "name" : "multiple-view-documents", "qname" : "cloudant:multiple-view-documents", "signature" : "($connection as anyURI, $database as string, $design-document as string, $view as string, $keys as string*, $options as object()) as object()", "description" : "

    Lists the specified documents in a given view.

    \n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The information is returned as a JSON structure containing meta information\n about the return structure, and the list of documents each with its ID, revision\n and key. The key is generated from the document ID.

    \n

    This function allows to specify an additional options object.\n The following options are supported:\n

      \n
    • descending: return the documents in descending by key order (boolean,\n default: false).
    • \n
    • endkey: stop returning records when the specified key is reached (string).
    • \n
    • endkey_docid: stop returning records when the specified document ID is\n reached (string).
    • \n
    • group: group the results using the reduce function to a group or single\n row (boolean, default: false).
    • \n
    • group_level: specify the group level to be used (numeric).
    • \n
    • include_docs: include the full content of the documents in the return\n (boolean, default: false).
    • \n
    • inclusive_end: specifies whether the specified end key should be included\n in the result (boolean, default: true).
    • \n
    • key: return only documents that match the specified key (string).
    • \n
    • limit: limit the number of the returned documents to the specified number\n (numeric).
    • \n
    • reduce: use the reduction function (boolean, default: true).
    • \n
    • skip: skip this number of records before starting to return the results\n (numeric, default: 0).
    • \n
    • stale: allow the results from a stale view to be used (string, allowed\n value: \"ok\").
    • \n
    • startkey: start returning records when the specified key is reached\n (string).
    • \n
    • startkey_docid: start returning records when the specified document ID\n is reached (string).
    • \n
    • database-owner: specifies the database owner (string, default: connection\n user).
    • \n
    \n

    \n

    For example,\n

    cloudant:multiple-view-documents($connection, \"db\", \"recipes\",\n   \"by_ingredient\", (\"claret\", \"clear apple juice\"),\n   {\"database-owner\": \"username\"})\n 
    .\n

    \n

    An object with the following format is returned:\n

    \n {\n   \"total_rows\" : 26484,\n   \"rows\" : [\n     {\n       \"value\" : [\"Scotch collops\"]],\n       \"id\" : \"Scotchcollops\",\n       \"key\" : \"claret\"\n     },\n     {\n       \"value\" : [\"Stand pie\"],\n       \"id\" : \"Standpie\",\n       \"key\" : \"clear apple juice\"\n     }\n   ],\n   \"offset\" : 6324\n }\n 
    \n

    \n

    The fields have the following meaning:\n

      \n
    • offset: offset where the document list started.
    • \n
    • rows: array of document objects, each containing id, key and revision number.
    • \n
    • total_rows: number of documents in the database.
    • \n
    • update_seq: current update sequence database.
    • \n
    \n

    \n", "summary" : "

    Lists the specified documents in a given view.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection", "type" : "anyURI", "occurrence" : null, "description" : "
    A connection identifier
    " }, { "name" : "database", "type" : "string", "occurrence" : null, "description" : "
    A database name
    " }, { "name" : "design-document", "type" : "string", "occurrence" : null, "description" : "
    A design document name
    " }, { "name" : "view", "type" : "string", "occurrence" : null, "description" : "
    A view name
    " }, { "name" : "keys", "type" : "string", "occurrence" : "*", "description" : "
    The keys of the documents which must be retrieved
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    An object specifying additional request options
    " } ], "returns" : { "type" : "object()", "description" : "An object listing all the specified documents in the specified view" }, "errors" : [ "cloudant:AUTHORIZATION Authorization error", "cloudant:HTTP An HTTP error occurred when issuing the request", "cloudant:RESPONSE An error occurred parsing the server response", "cloudant:CONNECTION The specified connection does not exist", "cloudant:INTERNAL Cloudant internal error", "cloudant:OPTIONS Malformed options object" ] } ], "variables" : [ ] }, "http://api.28.io/exportimport" : { "ns" : "http://api.28.io/exportimport", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://api.28.io/collections", "prefix" : "cm" }, { "uri" : "http://api.28.io/exportimport", "prefix" : "exportimport" }, { "uri" : "http://zorba.io/modules/fetch", "prefix" : "fetch" }, { "uri" : "http://api.28.io/indices", "prefix" : "in" }, { "uri" : "http://www.28msec.com/modules/maps", "prefix" : "map" }, { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "req" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "resp" }, { "uri" : "http://www.28msec.com/modules/store", "prefix" : "store" }, { "uri" : "http://api.28.io/validation", "prefix" : "validate" } ], "functions" : [ { "isDocumented" : false, "arity" : 1, "name" : "create-map", "qname" : "exportimport:create-map", "signature" : "($map as object())", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "map", "type" : "object()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "export", "qname" : "exportimport:export", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "import", "qname" : "exportimport:import", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "import", "qname" : "exportimport:import", "signature" : "($import as object(), $overwrite as xs:boolean)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "import", "type" : "object()", "occurrence" : null, "description" : "" }, { "name" : "overwrite", "type" : "xs:boolean", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "is-system-collection", "qname" : "exportimport:is-system-collection", "signature" : "($name as xs:string) as xs:boolean", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "validate-map", "qname" : "exportimport:validate-map", "signature" : "($map as object()) as empty-sequence()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "map", "type" : "object()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "empty-sequence()", "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://jsoniq.org/errors" : { "ns" : "http://jsoniq.org/errors", "description" : " This module contains one variable declaration for each diagnostic of the\n http://jsoniq.org/errors namespace.\n The variables serves as documentation for the errors but can also\n be used in the code. For example, one useful scenario is to compare\n an error caught in the catch clause of a try-catch expression with one of\n the variables.\n", "sees" : [ ], "authors" : [ "Carlos Lopez" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://jsoniq.org/errors", "prefix" : "jerr" } ], "functions" : [ ], "variables" : [ { "name" : "jerr:JNSE0013", "type" : "xs:QName", "description" : "It is a dynamic error to serialize an atomic value not\n supported by JSON or a node with the JSON output method and with\n the jsoniq-serialization-extensions serialization parameter\n set to false.\n" }, { "name" : "jerr:JNDY0021", "type" : "xs:QName", "description" : "parser error raised by jn:parse-json\n" }, { "name" : "jerr:JNTY0021", "type" : "xs:QName", "description" : "array or object selector on heterogeneous sequence\n" }, { "name" : "jerr:JNTY0020", "type" : "xs:QName", "description" : "parser error for invalid option type\n" }, { "name" : "jerr:JNTY0024", "type" : "xs:QName", "description" : "objects or arrays don't have a string value\n" }, { "name" : "jerr:JNTY0023", "type" : "xs:QName", "description" : "It is a type error if the prefix is not a string or if the\n serialization parameters are not an element.\n" }, { "name" : "jerr:JNUP0019", "type" : "xs:QName", "description" : "It is a dynamic error if the content expression, in an object insert expression, does not evaluate to a sequence of objects.\n" }, { "name" : "jerr:JNTY0018", "type" : "xs:QName", "description" : "It is a dynamic error if there is not exactly one supplied parameter for an object or array selector.\n" }, { "name" : "jerr:JNUP0017", "type" : "xs:QName", "description" : " It is a dynamic error if the value in a replace expression is not exactly a single item.\n" }, { "name" : "jerr:JNUP0016", "type" : "xs:QName", "description" : "It is a dynamic error if it is attempted to create a replace, delete or rename update primitive with a selector that cannot be resolved against the target array or object.\n" }, { "name" : "jerr:JNSE0022", "type" : "xs:QName", "description" : "It is a dynamic error to serialize a sequence that does\n not exist of exactly one document node with XML, HTML, XHTML, Text.\n" }, { "name" : "jerr:JNSE0014", "type" : "xs:QName", "description" : "It is a dynamic error to serialize a function or a node with the\n JSON output method.\n" }, { "name" : "jerr:NS", "type" : "item()*", "description" : "" }, { "name" : "jerr:JNSE0012", "type" : "xs:QName", "description" : "It is a dynamic error to serialize a sequence of less\n or more than one item with the JSON output method if the\n jsoniq-serialization-multiple-items is set to no.\n" }, { "name" : "jerr:JNTY0011", "type" : "xs:QName", "description" : "It is a type error if the content sequence in a node constructor or in an XQUF insert or replace update expression contains an object or an array.\n" }, { "name" : "jerr:JNUP0010", "type" : "xs:QName", "description" : "It is a dynamic error if a pending update list contains two renaming update primitives on the same object and with the same selector.\n" }, { "name" : "jerr:JNUP0009", "type" : "xs:QName", "description" : "It is a dynamic error if a pending update list contains two replacing update primitives on the same object or array, and with the same selector.\n" }, { "name" : "jerr:JNUP0008", "type" : "xs:QName", "description" : "It is a dynamic error if the target of a deleting or replacing expression is not an array or an object.\n It is a dynamic error if the target of a renaming expression is not an object.\n It is a dynamic error if the target of an appending expression is not an array.\n It is a dynamic error if the target of a position-inserting expression is not an array.\n It is a dynamic error if the target of a non-position-inserting expression is not an object.\n" }, { "name" : "jerr:JNUP0007", "type" : "xs:QName", "description" : "It is a type error if, in an updating expression, an array selector cannot be cast to xs:integer or if an object selector cannot be cast to xs:string.\n" }, { "name" : "jerr:JNUP0006", "type" : "xs:QName", "description" : "It is a dynamic error if upd:applyUpdates causes an object to contain two pairs with the same name.\n" }, { "name" : "jerr:JNUP0005", "type" : "xs:QName", "description" : "It is a dynamic error if a pending update list contains two inserting update primitives on the same object and pair name.\n" }, { "name" : "jerr:JNTY0004", "type" : "xs:QName", "description" : "It is a type error to call fn:data on a sequence containing an array or an object.\n" }, { "name" : "jerr:JNDY0003", "type" : "xs:QName", "description" : "It is a dynamic error if two pairs in an object constructor or in a simple object union have the same name.\n" }, { "name" : "jerr:JNTY0002", "type" : "xs:QName", "description" : "It is a type error if the right-hand-side expression of a pair constructor does not return exactly one item.\n" } ] }, "http://zorba.io/modules/sctx" : { "ns" : "http://zorba.io/modules/sctx", "description" : " This module provides functions that gets components of the static context.\n", "sees" : [ "http://www.w3.org/TR/xquery/#id-xq-static-context-components" ], "authors" : [ "Nicolae Brinza" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/sctx", "prefix" : "sctx" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "base-uri", "qname" : "sctx:base-uri", "signature" : "() as xs:string? external", "description" : " Gets the base URI.\n", "summary" : "

    Gets the base URI.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string?", "description" : "The base URI." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "boundary-space-policy", "qname" : "sctx:boundary-space-policy", "signature" : "() as xs:string external", "description" : " Gets the boundary whitespace policy used by direct element constructors.\n", "summary" : "

    Gets the boundary whitespace policy used by direct element constructors.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "Either preserve or strip." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "construction-mode", "qname" : "sctx:construction-mode", "signature" : "() as xs:string external", "description" : " Gets the static context construction mode of element and document nodes.\n", "summary" : "

    Gets the static context construction mode of element and document nodes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "Either preserve or strip." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "copy-namespaces-mode", "qname" : "sctx:copy-namespaces-mode", "signature" : "() as xs:string+ external", "description" : " Gets the static context components that control the the namespace bindings\n that are assigned when an existing element node is copied\n by an element constructor.\n", "summary" : "

    Gets the static context components that control the the namespace bindings\n that are assigned when an existing element node is copied\n by an element constructor.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string+", "description" : "A sequence of two strings: the first is either preserve or no-preserve and the second is either inherit or no-inherit." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "default-collation", "qname" : "sctx:default-collation", "signature" : "() as xs:string external", "description" : " Gets one of statically known collations used by functions and operators\n for comparing and ordering values of type xs:string\n or xs:anyURI when no explicit collation is specified.\n", "summary" : "

    Gets one of statically known collations used by functions and operators\n for comparing and ordering values of type xs:string \n or xs:anyURI when no explicit collation is specified.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The collations that is used by default." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "default-collection-type", "qname" : "sctx:default-collection-type", "signature" : "() as xs:string external", "description" : " Gets the statically known default collection type.\n This is the type of the sequence of nodes that would result from calling the\n fn:collection function with no arguments.\n", "summary" : "

    Gets the statically known default collection type.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The type of the default collection." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "default-function-namespace", "qname" : "sctx:default-function-namespace", "signature" : "() as xs:string external", "description" : " Gets the URI of the default function namespace.\n", "summary" : "

    Gets the URI of the default function namespace.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The URI of the of the default function namespace." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "default-order", "qname" : "sctx:default-order", "signature" : "() as xs:string external", "description" : " Gets the component that controls the processing of empty sequences and NaN\n values as ordering keys in an order by clause\n in a FLWOR expression.\n", "summary" : "

    Gets the component that controls the processing of empty sequences and NaN\n values as ordering keys in an order by clause\n in a FLWOR expression.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "Either greatest or least." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "function-annotations", "qname" : "sctx:function-annotations", "signature" : "($name as xs:QName, $arity as xs:integer) as xs:QName* external", "description" : " Gets the list of annotations declared for the given function.\n", "summary" : "

    Gets the list of annotations declared for the given function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the function.
    " }, { "name" : "arity", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of arguments the function takes.
    " } ], "returns" : { "type" : "xs:QName*", "description" : "the list of annotations" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "function-arguments-count", "qname" : "sctx:function-arguments-count", "signature" : "($function as xs:QName) as xs:int* external", "description" : " Gets the number of arguments the given XQuery function takes.\n", "summary" : "

    Gets the number of arguments the given XQuery function takes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "function", "type" : "xs:QName", "occurrence" : null, "description" : "
    A QName identifying a function.
    " } ], "returns" : { "type" : "xs:int*", "description" : "Either a sequence of zero or more integers (one for each overloaded version of the given function) or an empty sequence if the function is not defined." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "function-names", "qname" : "sctx:function-names", "signature" : "() as xs:QName* external", "description" : " Gets a sequence containing the QNames of all defined functions\n that are available to be called from within an expression.\n", "summary" : "

    Gets a sequence containing the QNames of all defined functions\n that are available to be called from within an expression.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName*", "description" : "A sequence for QNames identifying all functions." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "functions", "qname" : "sctx:functions", "signature" : "() as object()* external", "description" : " Gets a sequence of JSON objects containing the name, arity, and annotations\n of all defined functions that are available to be called form within an\n expression.\n", "summary" : "

    Gets a sequence of JSON objects containing the name, arity, and annotations\n of all defined functions that are available to be called form within an\n expression.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()*", "description" : "A sequence of objects." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "in-scope-attribute-declarations", "qname" : "sctx:in-scope-attribute-declarations", "signature" : "() as xs:QName* external", "description" : " Gets a sequence of QNames identifying declared attributes\n in the imported schemas.\n", "summary" : "

    Gets a sequence of QNames identifying declared attributes\n in the imported schemas.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName*", "description" : "A sequence of QNames, one for each attribute." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "in-scope-attribute-groups", "qname" : "sctx:in-scope-attribute-groups", "signature" : "() as xs:QName* external", "description" : " Gets a sequence of QNames identifying declared in-scope\n schema attribute groups.\n", "summary" : "

    Gets a sequence of QNames identifying declared in-scope\n schema attribute groups.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName*", "description" : "A sequence of QNames, one for each attribute group." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "in-scope-element-declarations", "qname" : "sctx:in-scope-element-declarations", "signature" : "() as xs:QName* external", "description" : " Gets a sequence of QNames identifying declared elements\n in the imported schemas.\n", "summary" : "

    Gets a sequence of QNames identifying declared elements\n in the imported schemas.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName*", "description" : "A sequence of QNames, one for each declared element." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "in-scope-element-groups", "qname" : "sctx:in-scope-element-groups", "signature" : "() as xs:QName* external", "description" : " Gets a sequence of QNames identifying declared in-scope\n schema element groups.\n", "summary" : "

    Gets a sequence of QNames identifying declared in-scope\n schema element groups.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName*", "description" : "A sequence of QNames, one for each element group." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "in-scope-schema-types", "qname" : "sctx:in-scope-schema-types", "signature" : "() as xs:QName* external", "description" : " Gets a sequence of QNames identifying in-scope schema types\n including all the predefined schema types and all definitions\n found in imported schemas.\n", "summary" : "

    Gets a sequence of QNames identifying in-scope schema types\n including all the predefined schema types and all definitions\n found in imported schemas.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName*", "description" : "A sequence of QNames, one for each defined type." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "in-scope-variables", "qname" : "sctx:in-scope-variables", "signature" : "() as xs:QName* external", "description" : " Gets a sequence of QNames identifying declared variables\n from the static context.\n", "summary" : "

    Gets a sequence of QNames identifying declared variables\n from the static context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName*", "description" : "A sequence of QNames, one for each variable." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "option", "qname" : "sctx:option", "signature" : "($name as xs:QName) as xs:string? external", "description" : " Gets the value of an option that is declared in the prolog of the module.\n", "summary" : "

    Gets the value of an option that is declared in the prolog of the module.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    the name of the option value to retrieve
    " } ], "returns" : { "type" : "xs:string?", "description" : "the value of the option if contained in the static context or the empty sequence otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "ordering-mode", "qname" : "sctx:ordering-mode", "signature" : "() as xs:string external", "description" : " Gets the ordering mode that affects the ordering of the result sequences\n returned by certain expressions.\n", "summary" : "

    Gets the ordering mode that affects the ordering of the result sequences\n returned by certain expressions.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "Either ordered or unordered." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "statically-known-collations", "qname" : "sctx:statically-known-collations", "signature" : "() as xs:anyURI* external", "description" : " Gets a sequence that contains the statically known collations.\n", "summary" : "

    Gets a sequence that contains the statically known collations.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:anyURI*", "description" : "The sequence of collations." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "statically-known-document-type", "qname" : "sctx:statically-known-document-type", "signature" : "($document as xs:string) as xs:QName external", "description" : " For the given document, returns the static type of its root node.\n", "summary" : "

    For the given document, returns the static type of its root node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "document", "type" : "xs:string", "occurrence" : null, "description" : "
    A URI of a document.
    " } ], "returns" : { "type" : "xs:QName", "description" : "The static type of the given document." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "statically-known-documents", "qname" : "sctx:statically-known-documents", "signature" : "() as xs:anyURI* external", "description" : " Gets a sequence that contains the URIs of all statically known documents.\n", "summary" : "

    Gets a sequence that contains the URIs of all statically known documents.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:anyURI*", "description" : "The sequence of document URIs." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "statically-known-namespace-binding", "qname" : "sctx:statically-known-namespace-binding", "signature" : "($prefix as xs:string) as xs:string? external", "description" : " Gets the bound URI for the given prefix.\n", "summary" : "

    Gets the bound URI for the given prefix.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "prefix", "type" : "xs:string", "occurrence" : null, "description" : "
    The prefix of the known namespace for which the bound URI is being requested.
    " } ], "returns" : { "type" : "xs:string?", "description" : "The URI bound to the prefix is returned, or an empty sequence if the prefix is not known." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "statically-known-namespaces", "qname" : "sctx:statically-known-namespaces", "signature" : "() as xs:string* external", "description" : " Gets a list of known statically known namespaces as prefixes\n (fn, xml, xs, xsi, etc).\n", "summary" : "

    Gets a list of known statically known namespaces as prefixes\n (fn, xml, xs, xsi, etc).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string*", "description" : "A sequence of xs:strings, one for each known namespace prefix." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "xpath10-compatibility-mode", "qname" : "sctx:xpath10-compatibility-mode", "signature" : "() as xs:boolean external", "description" : " Gets true or false depending on whether rules for compatibility\n with XPath 1.0 are in effect.\n XQuery set the value of this component to false.\n", "summary" : "

    Gets true or false depending on whether rules for compatibility\n with XPath 1.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "The function should return false." }, "errors" : [ ] } ], "variables" : [ ] }, "http://xbrl.io/modules/bizql/profiles/sec/import" : { "ns" : "http://xbrl.io/modules/bizql/profiles/sec/import", "description" : "

    This module provides functionality for querying XBRL Infosets of financial reports submitted to the SEC.\n

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/archives", "prefix" : "archives" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://xbrl.io/modules/bizql/entities", "prefix" : "entities" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/import", "prefix" : "imp" }, { "uri" : "http://www.28msec.com/modules/mongodb", "prefix" : "m" }, { "uri" : "http://zorba.io/modules/string", "prefix" : "string" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "disclosure-for-network-label", "qname" : "imp:disclosure-for-network-label", "signature" : "($component as object()) as object()", "description" : "

    \n Compute the disclore for a component's network label.\n

    \n", "summary" : "

    \n Compute the disclore for a component's network label.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "component", "type" : "object()", "occurrence" : null, "description" : "
    the component
    " } ], "returns" : { "type" : "object()", "description" : "returns the given component ammended with the disclosure" }, "errors" : [ ] } ], "variables" : [ { "name" : "imp:disclosure-matching", "type" : "object()", "description" : " Declarative description of the disclosure matching heuristics.\n" } ] }, "http://xbrl.io/modules/bizql/profiles/sec/core" : { "ns" : "http://xbrl.io/modules/bizql/profiles/sec/core", "description" : "

    This module provides functionality for querying XBRL Models of financial reports submitted to the SEC.\n

    \n

    Standard $options Parameter

    \n

    Most functions in the BizQL package allow an additional $options\n parameter. The options parameter is a JSON object which is defined in the documentation\n of the facts module.

    \n

    In addition to the option fields defined in the\n facts module the following\n fields can be used in the options of a function in the SEC profile:

    \n
      \n
    • HideAmendedFacts: if set to true (default behavior) all facts that have been\n amended are not included in the result.
    • \n
    • IncludeImpliedTable: set to true in order to output the implied table if\n there is no Table (default is false).
    • \n
    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/archives", "prefix" : "archives" }, { "uri" : "http://xbrl.io/modules/bizql/concept-maps", "prefix" : "concept-maps" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://xbrl.io/modules/bizql/entities", "prefix" : "entities" }, { "uri" : "http://xbrl.io/modules/bizql/facts", "prefix" : "facts" }, { "uri" : "http://xbrl.io/modules/bizql/hypercubes", "prefix" : "hypercubes" }, { "uri" : "http://www.28msec.com/modules/mongodb", "prefix" : "m" }, { "uri" : "http://xbrl.io/modules/bizql/report-schemas", "prefix" : "report-schemas" }, { "uri" : "http://xbrl.io/modules/bizql/profiles/sec/core", "prefix" : "sec" }, { "uri" : "http://zorba.io/modules/string", "prefix" : "string" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "edgar-facts-for-archives", "qname" : "sec:edgar-facts-for-archives", "signature" : "($archive_or_ids as item()*) as object()*", "description" : "

    Return all facts for concepts that are defined by one of the common\n edgar taxonomies. In particular, this function returns facts for concepts\n having one of the following prefixes:

    \n
      \n
    • xbrli
    • \n
    • link
    • \n
    • xl
    • \n
    • xlink
    • \n
    • xbrldt
    • \n
    • xbrldi
    • \n
    • nonnum
    • \n
    • num
    • \n
    • ref
    • \n
    • us-gaap
    • \n
    • dei
    • \n
    • us-types
    • \n
    • invest
    • \n
    • country
    • \n
    • currency
    • \n
    • exch
    • \n
    • naics
    • \n
    • sic
    • \n
    • stpr
    • \n
    • rr
    • \n
    • rr-ent
    • \n
    • rr-cal
    • \n
    • rr-def
    • \n
    • rr-pre
    • \n
    \n", "summary" : "

    Return all facts for concepts that are defined by one of the common\n edgar taxonomies.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive_or_ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archive or archive IDs to filter.
    " } ], "returns" : { "type" : "object()*", "description" : "all facts having one of the above prefixes." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "end-date", "qname" : "sec:end-date", "signature" : "($filing-fact-or-id as item()?) as xs:date?", "description" : "

    Retrieves the document end date of a filing or a fact.

    \n", "summary" : "

    Retrieves the document end date of a filing or a fact.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "filing-fact-or-id", "type" : "item()", "occurrence" : "?", "description" : "
    a filing, a fact, or its id.
    " } ], "returns" : { "type" : "xs:date?", "description" : "the document end date (e.g., xs:date(\"2011-04-30\"))." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "extension-facts-for-archives", "qname" : "sec:extension-facts-for-archives", "signature" : "($archive_or_ids as item()*) as object()*", "description" : "

    Return all facts for concepts that are NOT defined by one of the common\n edgar taxonomies. In particular, this function returns facts for concepts\n having none of the prefixes listed under function\n sec:edgar-facts-for-archives.

    \n", "summary" : "

    Return all facts for concepts that are NOT defined by one of the common\n edgar taxonomies.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive_or_ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archive or archive IDs to filter.
    " } ], "returns" : { "type" : "object()*", "description" : "all facts having none of the common edgar prefixes." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "fact-table-for-schema", "qname" : "sec:fact-table-for-schema", "signature" : "($schema as item(), $archives as item()*) as array()", "description" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied schema, and populates them with the default dimension values\n when missing.

    \n", "summary" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied schema, and populates them with the default dimension values\n when missing.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "schema", "type" : "item()", "occurrence" : null, "description" : "
    a report schema or its RID.
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs or $sec:ALL_OF_THEM for no filtering.
    " } ], "returns" : { "type" : "array()", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "facts-for-archives-and-concepts", "qname" : "sec:facts-for-archives-and-concepts", "signature" : "($archive_or_ids as item()*, $concepts as item()*) as object()*", "description" : "

    Retrieves the facts associated with the supplied concepts\n from the supplied archive, that match the fiscal focus of the archive.

    \n", "summary" : "

    Retrieves the facts associated with the supplied concepts\n from the supplied archive, that match the fiscal focus of the archive.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive_or_ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their ids or $sec:ALL_OF_THEM for no filtering.
    " }, { "name" : "concepts", "type" : "item()", "occurrence" : "*", "description" : "
    the concepts or $sec:ALL_OF_THEM for no filtering.
    " } ], "returns" : { "type" : "object()*", "description" : "the latest facts associated with the supplied concept." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "facts-for-archives-and-concepts", "qname" : "sec:facts-for-archives-and-concepts", "signature" : "($archive_or_ids as item()*, $concepts as item()*, $options as object()?) as object()*", "description" : "

    Retrieves the facts associated with the supplied concepts\n from the supplied archive, that match the fiscal focus of the archive.

    \n", "summary" : "

    Retrieves the facts associated with the supplied concepts\n from the supplied archive, that match the fiscal focus of the archive.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive_or_ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their ids or $sec:ALL_OF_THEM for no filtering.
    " }, { "name" : "concepts", "type" : "item()", "occurrence" : "*", "description" : "
    the concepts or $sec:ALL_OF_THEM for no filtering.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "the latest facts associated with the supplied concept." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "facts-for-schema", "qname" : "sec:facts-for-schema", "signature" : "($schema as item(), $archives as item()*) as item()*", "description" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied schema and to the fiscal focus, and populates\n them with the default dimension values when missing.

    \n", "summary" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied schema and to the fiscal focus, and populates\n them with the default dimension values when missing.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "schema", "type" : "item()", "occurrence" : null, "description" : "
    a schema.
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs or $sec:ALL_OF_THEM for no filtering.
    " } ], "returns" : { "type" : "item()*", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "hide-amended-facts", "qname" : "sec:hide-amended-facts", "signature" : "($facts as object()*) as object()*", "description" : "

    Filters a list of facts and returns only the latest amending facts.\n Accordingly, all amended facts are filtered out.

    \n", "summary" : "

    Filters a list of facts and returns only the latest amending facts.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "facts", "type" : "object()", "occurrence" : "*", "description" : "
    a list of facts.
    " } ], "returns" : { "type" : "object()*", "description" : "a sequence of facts without amended facts." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "populate-schema-with-facts", "qname" : "sec:populate-schema-with-facts", "signature" : "($schema as item(), $archives as item()*) as object()*", "description" : "

    Populates a concept-tree network with all facts from the supplied archives,\n that are relevant to the\n supplied schema. Default dimension values are added to the facts\n when missing.

    \n", "summary" : "

    Populates a concept-tree network with all facts from the supplied archives,\n that are relevant to the\n supplied schema.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "schema", "type" : "item()", "occurrence" : null, "description" : "
    a report schema or its RID.
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs.
    " } ], "returns" : { "type" : "object()*", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "populate-schema-with-facts", "qname" : "sec:populate-schema-with-facts", "signature" : "($schema as item(), $archives as item()*, $options as object()?) as object()*", "description" : "

    Populates a concept-tree network with all facts from the supplied archives,\n that are relevant to the\n supplied schema. Default dimension values are added to the facts\n when missing.

    \n", "summary" : "

    Populates a concept-tree network with all facts from the supplied archives,\n that are relevant to the\n supplied schema.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "schema", "type" : "item()", "occurrence" : null, "description" : "
    a report schema or its RID.
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs or $sec:ALL_OF_THEM for no filtering.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] } ], "variables" : [ { "name" : "sec:CIK", "type" : "xs:string", "description" : " Scheme for the SEC entity identifiers (i.e. http://www.sec.gov/CIK)\n" }, { "name" : "sec:ALL_OF_THEM", "type" : "boolean", "description" : " Joker value for all archives or all concepts.\n" }, { "name" : "sec:EDGAR_PREFIXES", "type" : "item()*", "description" : " All prefixes pre-declared in SEC's EDGAR.\n" } ] }, "http://zorba.io/modules/excel/logical" : { "ns" : "http://zorba.io/modules/excel/logical", "description" : " This is a library module offering the same set of functions\n defined by Microsoft Excel, under Logical Functions.\n", "sees" : [ "Excel Documentation: Logical Functions" ], "authors" : [ "Sorin Nasoi" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/excel/errors", "prefix" : "excel-err" }, { "uri" : "http://zorba.io/modules/excel/logical", "prefix" : "excel-logical" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "and", "qname" : "excel-logical:and", "signature" : "($values as xs:anyAtomicType*) as xs:boolean", "description" : " Returns TRUE if all its arguments are TRUE; FALSE if one or more arguments are FALSE.\n", "summary" : "

    Returns TRUE if all its arguments are TRUE; FALSE if one or more arguments are FALSE.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "values", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of arguments.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "TRUE if all its arguments are TRUE; FALSE if one or more arguments are FALSE." }, "errors" : [ "excel-err:Value provided sequence is empty." ] }, { "isDocumented" : true, "arity" : 2, "name" : "and", "qname" : "excel-logical:and", "signature" : "($arg1 as xs:anyAtomicType, $arg2 as xs:anyAtomicType) as xs:boolean", "description" : " Returns TRUE if all its arguments are TRUE; FALSE if one or more arguments are FALSE.\n", "summary" : "

    Returns TRUE if all its arguments are TRUE; FALSE if one or more arguments are FALSE.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the first argument.
    " }, { "name" : "arg2", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the second argument.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "TRUE if all its arguments are TRUE; FALSE if one or more arguments are FALSE." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "if", "qname" : "excel-logical:if", "signature" : "($logical_test as xs:boolean, $value_if_true as item()*, $value_if_false as item()*) as item()*", "description" : " Returns one value if a condition you specify evaluates to TRUE and another value if it evaluates to FALSE.\n", "summary" : "

    Returns one value if a condition you specify evaluates to TRUE and another value if it evaluates to FALSE.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "logical_test", "type" : "xs:boolean", "occurrence" : null, "description" : "
    is any value or expression that can be evaluated to TRUE or FALSE.
    " }, { "name" : "value_if_true", "type" : "item()", "occurrence" : "*", "description" : "
    the value that is returned if logical_test is TRUE.
    " }, { "name" : "value_if_false", "type" : "item()", "occurrence" : "*", "description" : "
    the value that is returned if logical_test is FALSE.
    " } ], "returns" : { "type" : "item()*", "description" : "One value if a condition you specify evaluates to TRUE and another value if it evaluates to FALSE." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "or", "qname" : "excel-logical:or", "signature" : "($values as xs:anyAtomicType*) as xs:boolean", "description" : " Returns TRUE if any argument is TRUE; FALSE if all arguments are FALSE.\n", "summary" : "

    Returns TRUE if any argument is TRUE; FALSE if all arguments are FALSE.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "values", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of arguments.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "TRUE if any argument is TRUE; FALSE if all arguments are FALSE." }, "errors" : [ "excel-err:Value provided sequence is empty." ] }, { "isDocumented" : true, "arity" : 2, "name" : "or", "qname" : "excel-logical:or", "signature" : "($arg1 as xs:anyAtomicType, $arg2 as xs:anyAtomicType) as xs:boolean", "description" : " Returns TRUE if any argument is TRUE; FALSE if all arguments are FALSE.\n", "summary" : "

    Returns TRUE if any argument is TRUE; FALSE if all arguments are FALSE.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the first argument.
    " }, { "name" : "arg2", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the second argument.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "TRUE if any argument is TRUE; FALSE if all arguments are FALSE." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/sequence" : { "ns" : "http://www.28msec.com/modules/sequence", "description" : " The sequence module allows you to generate consecutive\n application-unique xs:integer ids. This is required e.g. in accounting\n applications as some legislations require consecutive invoice numbers.\n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://zorba.io/modules/store/static/collections/dml", "prefix" : "cdml" }, { "uri" : "http://zorba.io/modules/store/static/indexes/dml", "prefix" : "idml" }, { "uri" : "http://www.28msec.com/modules/lock", "prefix" : "lock" }, { "uri" : "http://www.28msec.com/modules/sequence", "prefix" : "seq" }, { "uri" : "http://www.28msec.com/modules/sleep", "prefix" : "sleep" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "id", "qname" : "seq:id", "signature" : "($uri as xs:string) as xs:integer", "description" : " Returns a unique (sequentially incremented) id for the\n uri specified as parameter.\n Here the function is used to create consecutive invoice numbers:\n
    \n if (order:fulfilled($order-id))\n then\n   {\n     variable $invoice-id := seq:id(\"invoice\");\n     invoice:create($invoice-id, $order-id);\n   }\n else\n   ...\n 
    \n", "summary" : "

    Returns a unique (sequentially incremented) id for the\n uri specified as parameter.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the sequence counter as uri.
    " } ], "returns" : { "type" : "xs:integer", "description" : "A sequentially incremented id." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "reset", "qname" : "seq:reset", "signature" : "($uri as xs:string) as empty-sequence()", "description" : " Resets the unique (sequentially incremented) id generation\n for the uri specified as parameter.\n", "summary" : "

    Resets the unique (sequentially incremented) id generation\n for the uri specified as parameter.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the sequence counter as uri.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "empty-sequence()" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "value", "qname" : "seq:value", "signature" : "($uri as xs:string) as xs:integer", "description" : " Returns the id for the uri specified as parameter without incrementing it.\n", "summary" : "

    Returns the id for the uri specified as parameter without incrementing it.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the sequence counter as uri.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The current value" }, "errors" : [ "seq:not-found if no counter with the given $uri was found" ] } ], "variables" : [ { "name" : "seq:counters", "type" : "item()*", "description" : " The QName for the counters collection.\n" }, { "name" : "seq:counters-by-uri", "type" : "item()*", "description" : " The QName for the counters-by-uri collection.\n" } ] }, "http://api.28.io/databrowser" : { "ns" : "http://api.28.io/databrowser", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://api.28.io/databrowser", "prefix" : "api" }, { "uri" : "http://zorba.io/modules/base64", "prefix" : "base64" }, { "uri" : "http://zorba.io/modules/store/static/collections/dml", "prefix" : "dml" }, { "uri" : "http://www.zorba-xquery.com/extensions", "prefix" : "ext" }, { "uri" : "http://www.functx.com", "prefix" : "functx" }, { "uri" : "http://expath.org/ns/http-client", "prefix" : "http" }, { "uri" : "http://www.zorba-xquery.com/modules/http-client", "prefix" : "http-client" }, { "uri" : "http://zorba.io/modules/xml-options", "prefix" : "opt" }, { "uri" : "http://www.28msec.com/modules/project", "prefix" : "project" }, { "uri" : "http://zorba.io/modules/reflection", "prefix" : "r" }, { "uri" : "http://zorba.io/modules/reference", "prefix" : "ref" }, { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "req" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "res" }, { "uri" : "http://zorba.io/modules/xml", "prefix" : "xmlmod" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : false, "arity" : 1, "name" : "collection", "qname" : "api:collection", "signature" : "($name as xs:string)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "delete", "qname" : "api:delete", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "dispatch", "qname" : "api:dispatch", "signature" : "()", "description" : " Data Browser API dispatched.\n Handles API authorization to the portal and dispatching.\n", "summary" : "

    Data Browser API dispatched.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "edit", "qname" : "api:edit", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "options", "qname" : "api:options", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "run", "qname" : "api:run", "signature" : "($sequential as xs:boolean) as object()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "sequential", "type" : "xs:boolean", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "object()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "serialize", "qname" : "api:serialize", "signature" : "($items as item()*) as object()", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "object()", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 0, "name" : "upload", "qname" : "api:upload", "signature" : "()", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://xbrl.io/modules/bizql/footnotes" : { "ns" : "http://xbrl.io/modules/bizql/footnotes", "description" : "

    This module provides functions for retrieving XBRL footnotes\n (see section 4.11 Footnotes of the XBRL 2.1 specification).

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/archives", "prefix" : "archives" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://xbrl.io/modules/bizql/entities", "prefix" : "entities" }, { "uri" : "http://xbrl.io/modules/bizql/facts", "prefix" : "facts" }, { "uri" : "http://xbrl.io/modules/bizql/footnotes", "prefix" : "footnotes" }, { "uri" : "http://www.28msec.com/modules/mongodb/types", "prefix" : "m" }, { "uri" : "http://www.28msec.com/modules/mongodb", "prefix" : "mongo" }, { "uri" : "http://zorba.io/modules/string", "prefix" : "string" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "fnid", "qname" : "footnotes:fnid", "signature" : "($footnote-or-id as item()) as atomic", "description" : "

    Converts the input to a normalized footnote id (FNID). The input\n can be either an FNID, or a footnote object which contains an _id.

    \n", "summary" : "

    Converts the input to a normalized footnote id (FNID).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "footnote-or-id", "type" : "item()", "occurrence" : null, "description" : "
    an footnote object or FNID.
    " } ], "returns" : { "type" : "atomic", "description" : "the normalized FNID." }, "errors" : [ "footnotes:INVALID-PARAMETER if the FNID or footnote is not valid." ] }, { "isDocumented" : true, "arity" : 1, "name" : "footnotes-for-archives", "qname" : "footnotes:footnotes-for-archives", "signature" : "($archive-or-ids as item()*) as object()*", "description" : "

    Return all footnotes reported within a given archive.

    \n", "summary" : "

    Return all footnotes reported within a given archive.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or AIDs to filter.
    " } ], "returns" : { "type" : "object()*", "description" : "all footnotes reported in these archives." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "footnotes-for-facts", "qname" : "footnotes:footnotes-for-facts", "signature" : "($facts-or-ids as item()*) as object()*", "description" : "

    Return all footnotes associated with the given facts.

    \n", "summary" : "

    Return all footnotes associated with the given facts.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "facts-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of facts or fact IDs to filter
    " } ], "returns" : { "type" : "object()*", "description" : "all footnotes associated with these facts." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "footnotes-for-facts", "qname" : "footnotes:footnotes-for-facts", "signature" : "($facts-or-ids as item()*, $options as object()?) as object()*", "description" : "

    Return all footnotes associated with the given facts.

    \n", "summary" : "

    Return all footnotes associated with the given facts.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "facts-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of facts or fact IDs to filter
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "all footnotes associated with these facts." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "footnotes-search", "qname" : "footnotes:footnotes-search", "signature" : "($search as string) as object()*", "description" : "

    Return all footnotes that match the given search term.

    \n", "summary" : "

    Return all footnotes that match the given search term.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "search", "type" : "string", "occurrence" : null, "description" : "
    the search query
    " } ], "returns" : { "type" : "object()*", "description" : "all footnotes matching the given search query" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "footnotes", "qname" : "footnotes:footnotes", "signature" : "() as object()*", "description" : "

    Return all footnotes.

    \n", "summary" : "

    Return all footnotes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()*", "description" : "all footnotes." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "footnotes", "qname" : "footnotes:footnotes", "signature" : "($footnote-or-ids as item()*) as object()?", "description" : "

    Return the footnote with the given FNIDs.

    \n", "summary" : "

    Return the footnote with the given FNIDs.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "footnote-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    the FNIDs or the footnotes themselves.
    " } ], "returns" : { "type" : "object()?", "description" : "the footnotes with the given FNIDs the empty sequence if no footnote was found or if the input is an empty sequence." }, "errors" : [ ] } ], "variables" : [ { "name" : "footnotes:col", "type" : "string", "description" : " Name of the collection the footnotes are stored in.\n" }, { "name" : "footnotes:ARCHIVE", "type" : "string", "description" : " Name of the field that points to the archive.\n" }, { "name" : "footnotes:FACTS", "type" : "string", "description" : " Name of the field that points to the facts linked to this footnote.\n" }, { "name" : "footnotes:LANG", "type" : "string", "description" : " Name of the field that holds the language attribute of the footnote.\n" } ] }, "http://zorba.io/modules/store/static/indexes/dml" : { "ns" : "http://zorba.io/modules/store/static/indexes/dml", "description" : " This module defines a set of functions to probe and refresh indexes which are\n declared in the prolog of a module.\n

    \n This module is part of\n Zorba's XQuery Data Definition Facility.\n All the indexes managed by this module have to be pre-declared in the prolog\n of a library module.\n Please refer to the\n general documentation\n for more information and examples.\n", "sees" : [ "Data Lifecycle", "XQuery Data Definition Facility", "http://zorba.io/modules/store/static/indexes/ddl", "http://zorba.io/modules/store/static/collections/dml", "http://zorba.io/modules/store/static/collections/ddl", "http://zorba.io/modules/store/static/integrity-constraints/ddl", "http://zorba.io/modules/store/static/integrity-constraints/dml", "http://zorba.io/errors" ], "authors" : [ "Zorba Team" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://zorba.io/modules/store/static/indexes/dml", "prefix" : "idml" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "keys", "qname" : "idml:keys", "signature" : "($name as xs:QName) as node()* external", "description" : " Gets a sequence of all keys contained in the index with the given name.\n Each element has the following structure:\n

    \n   <key xmlns=\"http://zorba.io/modules/store/static/indexes/dml\">\n     <attribute value=\"key1_value\"/>\n     <attribute value=\"key2_value\"/>\n     <attribute value=\"key3_value\"/>\n   </key>\n  
    \n Note that the order of the attribute elements reflects the order of\n the keys in the index specification. Also note that the values in\n these attributes have the type that is declared in the corresponding\n index specification.\n", "summary" : "

    Gets a sequence of all keys contained in the index with the given name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the index to get the keys for.
    " } ], "returns" : { "type" : "node()*", "description" : "A sequence of elements comprising the keys in the index." }, "errors" : [ "zerr:ZDDY0021 if the index was not declared.", "zerr:ZDDY0023 if the index does not exist." ] }, { "isDocumented" : true, "arity" : 2, "name" : "probe-index-point-general", "qname" : "idml:probe-index-point-general", "signature" : "($name as xs:QName, $key as xs:anyAtomicType*) as node()* external", "description" : " Gets from an index the domain nodes associated by general equality with a\n given search sequence .\n The search sequence consists of an arbitrary number of search keys\n where each search key is an atomic item.\n The function is supported by general indexes only.\n", "summary" : "

    Gets from an index the domain nodes associated by general equality with a\n given search sequence .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the index to probe.
    " }, { "name" : "key", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The search sequence.
    " } ], "returns" : { "type" : "node()*", "description" : "The set of domain nodes for which the following XQuery expression returns true:
     $keys = $node/keyExpr 
    where keyExpr is the expression specified in the keyspec of the index (remember that for general indexes, there can be only one keyspec)." }, "errors" : [ "err:XPTY0004 if the search sequence contains a search key whose type does not match the sequence type specified in the keyspec of the index.", "zerr:ZDDY0021 if the index with name $name is not declared.", "zerr:ZDDY0023 if the index with name $name does not exist.", "zerr:ZDDY0029 if the index is not general." ] }, { "isDocumented" : true, "arity" : 3, "name" : "probe-index-point-value-skip", "qname" : "idml:probe-index-point-value-skip", "signature" : "($name as xs:QName, $skip as xs:integer, $key_i as xs:anyAtomicType?) as node()* external", "description" : " This is an extension of the probe-index-point-value() function\n in that it allows index items to be skipped.\n", "summary" : "

    This is an extension of the probe-index-point-value() function\n in that it allows index items to be skipped.

    ", "annotation_str" : " %an:variadic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "variadic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the index to probe.
    " }, { "name" : "skip", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of index items to skip.
    " }, { "name" : "key_i", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    The search keys used to probe the index with. The i-th search key corresponds to the i-th key expression in the index declaration.
    " } ], "returns" : { "type" : "node()*", "description" : "The set of domain nodes that satisfy the search condition." }, "errors" : [ "zerr:ZDDY0021 if the index is not declared.", "zerr:ZDDY0023 if the index does not exist.", "zerr:ZDDY0025 if the number of search keys passed as arguments is not the same as the number of keys declared for the index.", "err:XPTY0004 if a non-empty seach key is given whose type does not match the sequence type specified in the corresponding keyspec." ] }, { "isDocumented" : true, "arity" : 2, "name" : "probe-index-point-value", "qname" : "idml:probe-index-point-value", "signature" : "($name as xs:QName, $key_i as xs:anyAtomicType?) as node()* external", "description" : " Gets the domain nodes from an index associated by value equality with a\n given search tuple.\n

    \n The search tuple consists of a number of search keys where each\n search key is either an atomic item or the empty sequence. The number of\n search keys given must be equal to the number of keys declared for the\n index. Since the number of keys differs from one index to another, this\n function is variadic.\n", "summary" : "

    Gets the domain nodes from an index associated by value equality with a\n given search tuple .

    ", "annotation_str" : " %an:variadic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "variadic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The of the index to probe.
    " }, { "name" : "key_i", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    A search key used to probe the index with. The i-th search key corresponds to the i-th key expression in the index declaration.
    " } ], "returns" : { "type" : "node()*", "description" : "The set of domain nodes for which the following XQuery expression returns true:
     $key1 eq $node/keyExpr1 and ... and $keyM eq $node/keyExprM 
    where keyExpri is the expression specified in the i-th keyspec of the index." }, "errors" : [ "zerr:ZDDY0021 if the index is not declared.", "zerr:ZDDY0023 if the index does not exist.", "zerr:ZDDY0025 if the number of search keys passed as arguments is not the same as the number of keys declared for the index.", "err:XPTY0004 if a non-empty seach key is given whose type does not match the sequence type specified in the corresponding keyspec." ] }, { "isDocumented" : true, "arity" : 7, "name" : "probe-index-range-general", "qname" : "idml:probe-index-range-general", "signature" : "($name as xs:QName, $lowerBound as xs:anyAtomicType*, $upperBound as xs:anyAtomicType*, $haveLowerBound as xs:boolean, $haveUpperBound as xs:boolean, $lowerBoundIncluded as xs:boolean, $upperBoundIncluded as xs:boolean) as node()* external", "description" : " Gets the domain nodes associated by general order-comparison (operators\n <=, <, >=,\n >) with one or two search sequences.\n

    \n Each search sequence consists of an arbitrary number of\n search keys where each search key is an atomic item.\n This method is supported by general range indexes only.\n Its result is either an error or the set of domain nodes for which the\n following XQuery expression returns true:\n

    \n    if ( $haveLowerBound and $haveUpperBound ) then\n      $lowerBoundKeys lop $node/keyExpr and $node/keyExpr uop $upperBoundKeys\n    else if ( $haveLowerBound ) then\n      $lowerBoundKeys lop $node/keyExpr\n    else if ( $haveUpperBound ) then\n      $node/keyExpr uop $upperBoundKeys\n    else\n      fn:true()\n  
    \n where keyExpr is the expression specified in the keyspec of the\n index, lop is either the <= or the <\n operator depending on whether $lowerBoundsIncluded is true or\n false, and uop is either the <= or the\n < operator depending on whether\n $upperBoundsIncluded is true or false.\n", "summary" : "

    Gets the domain nodes associated by general order-comparison (operators\n <= , < , >= ,\n > ) with one or two search sequences .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The of the index to probe.
    " }, { "name" : "lowerBound", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The lower bound search sequence.
    " }, { "name" : "upperBound", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    The upper bound search sequence.
    " }, { "name" : "haveLowerBound", "type" : "xs:boolean", "occurrence" : null, "description" : "
    Whether a lower bound search sequence exists or not.
    " }, { "name" : "haveUpperBound", "type" : "xs:boolean", "occurrence" : null, "description" : "
    Whether an upper bound search sequence exists or not.
    " }, { "name" : "lowerBoundIncluded", "type" : "xs:boolean", "occurrence" : null, "description" : "
    Whether to use the <= or the < operator when comparing a search key from $lowerBound with an index key.
    " }, { "name" : "upperBoundIncluded", "type" : "xs:boolean", "occurrence" : null, "description" : "
    Whether to use the <= or the < operator when comparing an index key with a search key from $upperBound.
    " } ], "returns" : { "type" : "node()*", "description" : "The set of domain nodes that satisfy the search condition." }, "errors" : [ "zerr:ZDDY0021 if the index was not declared.", "zerr:ZDDY0023 if the index does not exist.", "zerr:ZDDY0030 if the index is not a general range index.", "err:XPTY0004 if $haveLowerBound is true and $lowerBoundKeys contains an atomic item whose type does not match the sequence type specified by the index keyspec, or $haveUpperBound is true and $upperBoundKeys contains an atomic item whose type does not match the sequence type specified by the index keyspec." ] }, { "isDocumented" : true, "arity" : 8, "name" : "probe-index-range-value-skip", "qname" : "idml:probe-index-range-value-skip", "signature" : "($name as xs:QName, $skip as xs:integer, $lowerBound-i as xs:anyAtomicType?, $upperBound-i as xs:anyAtomicType?, $haveLowerBound-i as xs:boolean, $haveUpperBound-i as xs:boolean, $lowerBoundIncluded-i as xs:boolean, $upperBoundIncluded-i as xs:boolean) as node()* external", "description" : " This function is an extension of the probe-index-range-value()\n function that index items to be skipped.\n", "summary" : "

    This function is an extension of the probe-index-range-value() \n function that index items to be skipped.

    ", "annotation_str" : " %an:variadic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "variadic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The QName of the index to probe
    " }, { "name" : "skip", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of index items to skip.
    " }, { "name" : "lowerBound-i", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    The lower bound in a range of key values.
    " }, { "name" : "upperBound-i", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    The upper bound in a range of key values.
    " }, { "name" : "haveLowerBound-i", "type" : "xs:boolean", "occurrence" : null, "description" : "
    If false, then there is no lower bound, or equivalently, the lower bound is -INFINITY. Otherwise, the lower bound is the one given by the $lowerBound-i value.
    " }, { "name" : "haveUpperBound-i", "type" : "xs:boolean", "occurrence" : null, "description" : "
    If false, then there is no upper bound, or equivalently, the upper bound is +INFINITY. Otherwise, the upper bound is the one given by the $upperBound-i value.
    " }, { "name" : "lowerBoundIncluded-i", "type" : "xs:boolean", "occurrence" : null, "description" : "
    If false, then the range is open from below, i.e., the lowerBound-i value is not considered part of the range. Otherwise, the range is closed from below, i.e., the $lowerBound-i value is part of the range.
    " }, { "name" : "upperBoundIncluded-i", "type" : "xs:boolean", "occurrence" : null, "description" : "
    If false, then the range is open from above, i.e., the upperBound-i value is not considered part of the range. Otherwise, the range is closed from above, i.e., the $upperBound-i value is part of the range.
    " } ], "returns" : { "type" : "node()*", "description" : "The set of domain nodes that satisfy the search condition." }, "errors" : [ "zerr:ZDDY0021 if the index with name $name is not declared.", "zerr:ZDDY0023 if the index with name $name does not exist.", "zerr:ZDDY0025 if the number of rangespecs passed as arguments is zero or greater than the number of keys declared for the index.", "zerr:ZDDY0026 if the index is not a range index.", "err:XPTY0004 if $haveLowerBound-i is true and $lowerBound-i is an atomic item whose type does not match the sequence type specified by the ith keyspec, or $haveUpperBound-i is true and $upperBound-i is an atomic item whose type does not match the sequence type specified by the ith keyspec.", "zerr:ZDDY0034 if (a) the index is general (in which case there is only one rangespac), (b) the index is untyped, (c) there is both a lower and an upper bound, and (d) if T1 and T2 are the types of the lower and upper bound, neither T1 is a subtype of T2 nor T2 is a subtype of T1." ] }, { "isDocumented" : true, "arity" : 7, "name" : "probe-index-range-value", "qname" : "idml:probe-index-range-value", "signature" : "($name as xs:QName, $lowerBound-i as xs:anyAtomicType?, $upperBound-i as xs:anyAtomicType?, $haveLowerBound-i as xs:boolean, $haveUpperBound-i as xs:boolean, $lowerBoundIncluded-i as xs:boolean, $upperBoundIncluded-i as xs:boolean) as node()* external", "description" : " Gets the domain nodes associated by value order-comparison (operators\n le, lt, ge, gt) with a\n given search box.\n

    \n The search box is specified as a number M of rangespecs\n where each rangespec consists of six values.\n The number M must be greater than 0 and less than or equal to the\n number N of keyspecs found in the index declaration.\n If M < N, then the \"missing\" rangespecs are assumed to have\n the following value: [(), (), false, false, false, false].\n As a result, we can assume that M = N.\n Remember that for general indexes, there can be only one IndexKeySpec and,\n as a result for general indexes, M = N = 1.\n Since the number of keys differs from one index to another,\n this function is variadic.\n

    \n The ith rangespec corresponds to the ith keyspec, and\n specifies a search condition on the key values that are produced by\n evaluating that keyspec for every domain node.\n Specifically, we define the ith rangespec result as the\n set of domain nodes for which the following XQuery expression returns\n true:\n

    \n    if ( $haveLowerBound-i and $haveUpperBound-i ) then\n      $lowerBound-i lop $node/keyExpr-i and $node/keyExpr-i uop $upperBound-i\n    else if ( $haveLowerBound-i ) then\n      $lowerBound-i lop $node/keyExpr-i\n    else if ( $haveUpperBound-i ) then\n      $node/keyExpr-i uop $upperBound-i\n    else\n      fn:true()\n  
    \n where keyExpr-i is the expression specified by the ith\n keyspec of the index, lop is either the le or the\n lt operator depending on whether\n $lowerBoundsIncluded-i is true or false, and uop is\n either the le or the lt operator depending on whether\n $upperBoundsIncluded-i is true or false.\n", "summary" : "

    Gets the domain nodes associated by value order-comparison (operators\n le , lt , ge , gt ) with a\n given search box .

    ", "annotation_str" : " %an:variadic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "variadic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the index to probe.
    " }, { "name" : "lowerBound-i", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    The lower bound in a range of key values.
    " }, { "name" : "upperBound-i", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    The upper bound in a range of key values.
    " }, { "name" : "haveLowerBound-i", "type" : "xs:boolean", "occurrence" : null, "description" : "
    If false, then there is no lower bound, or equivalently, the lower bound is -INFINITY. Otherwise, the lower bound is the one given by the $lowerBound-i value.
    " }, { "name" : "haveUpperBound-i", "type" : "xs:boolean", "occurrence" : null, "description" : "
    If false, then there is no upper bound, or equivalently, the upper bound is +INFINITY. Otherwise, the upper bound is the one given by the $upperBound-i value.
    " }, { "name" : "lowerBoundIncluded-i", "type" : "xs:boolean", "occurrence" : null, "description" : "
    If false, then the range is open from below, i.e., the $lowerBound-i value is not considered part of the range. Otherwise, the range is closed from below, i.e., the $lowerBound-i value is part of the range.
    " }, { "name" : "upperBoundIncluded-i", "type" : "xs:boolean", "occurrence" : null, "description" : "
    If false, then the range is open from above, i.e., the $upperBound-i value is not considered part of the range. Otherwise, the range is closed from above, i.e., the $upperBound-i value is part of the range.
    " } ], "returns" : { "type" : "node()*", "description" : "The intersection of all the rangespec results." }, "errors" : [ "zerr:ZDDY0021 if the index is not declared.", "zerr:ZDDY0023 if the index does not exist.", "zerr:ZDDY0025 if the number of rangespecs passed as arguments is zero or greater than the number of keys declared for the index.", "zerr:ZDDY0026 if the index is not a range index.", "err:XPTY0004 if $haveLowerBound-i is true and $lowerBound-i is an atomic item whose type does not match the sequence type specified by the ith keyspec, or $haveUpperBound-i is true and $upperBound-i is an atomic item whose type does not match the sequence type specified by the ith keyspec.", "zerr:ZDDY0034 if (a) the index is general (in which case there is only one rangespac), (b) the index is untyped, (c) there is both a lower and an upper bound, and (d) if T1 and T2 are the types of the lower and upper bound, neither T1 is a subtype of T2 nor T2 is a subtype of T1." ] }, { "isDocumented" : true, "arity" : 1, "name" : "refresh-index", "qname" : "idml:refresh-index", "signature" : "($name as xs:QName) external", "description" : " Updates the index with the given name. Note that if the maintenance\n property of the index is automatic, this function does nothing.\n", "summary" : "

    Updates the index with the given name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the index to refresh.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, when applied, refreshes the contents of the index." }, "errors" : [ "zerr:ZDDY0021 if the index is not declared.", "zerr:ZDDY0023 if the index does not exist." ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/full-text" : { "ns" : "http://www.28msec.com/modules/full-text", "description" : " This module provides an API to full-text functions such as tokenization,\n stemming, or stop word detection. The default language is set to english\n for all functions that don't take an explicit language parameter.\n

    Notes on stemming

    \n The stem() functions return the\n stem\n of a word.\n On 28.io,\n the stem of a word itself, however, is not guaranteed to be a word.\n It is best to consider a stem as an opaque byte sequence.\n All that is guaranteed about a stem is that,\n for a given word,\n the stem of that word will always be the same byte sequence.\n Hence,\n you sould never compare the result of one of the stem()\n functions against a non-stemmed string,\n for example:\n
    \n  if ( ft:stem( \"apples\" ) eq \"apple\" )             ** WRONG **\n 
    \n Instead do:\n
    \n  if ( ft:stem( \"apples\" ) eq ft:stem( \"apple\" ) )  ** CORRECT **\n 
    \n

    Notes on the thesaurus

    \n 28msec uses the\n WordNet lexical database version 3.0,\n In WordNet, the number of \"levels\" that two phrases are apart\n are how many hierarchical meanings apart they are.\n For example,\n \"canary\" is 5 levels away from \"vertebrate\"\n (carary > finch > oscine > passerine > bird > vertebrate).\n

    \n When using the WordNet implementation,\n 28msec supports all of the relationships (and their abbreviations)\n specified by\n ISO 2788\n and\n ANSI/NISO Z39.19-2005\n with the exceptions of \"HN\" (history note)\n and \"X SN\" (see scope note for).\n These relationships are:\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    Rel.MeaningWordNet Rel.
    BTbroader termhypernym
    BTGbroader term generichypernym
    BTIbroader term instanceinstance hypernym
    BTPbroader term partitivepart meronym
    NTnarrower termhyponym
    NTGnarrower term generichyponym
    NTInarrower term instanceinstance hyponym
    NTPnarrower term partitivepart holonym
    RTrelated termalso see
    SNscope noten/a
    TTtop termhypernym
    UFnon-preferred termn/a
    USEpreferred termn/a
    \n Note that you can specify relationships\n either by their abbreviation\n or their meaning.\n Relationships are case-insensitive.\n In addition to the\n ISO 2788\n and\n ANSI/NISO Z39.19-2005\n relationships,\n 28msec also supports all of the relationships offered by WordNet.\n These relationships are:\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    RelationshipMeaning
    also see\n A word that is related to another,\n e.g., for \"varnished\" (furniture)\n one should also see \"finished.\"\n
    antonym\n A word opposite in meaning to another,\n e.g., \"light\" is an antonym for \"heavy.\"\n
    attribute\n A noun for which adjectives express values,\n e.g., \"weight\" is an attribute\n for which the adjectives \"light\" and \"heavy\"\n express values.\n
    cause\n A verb that causes another,\n e.g., \"show\" is a cause of \"see.\"\n
    derivationally related form\n A word that is derived from a root word,\n e.g., \"metric\" is a derivationally related form of \"meter.\"\n
    derived from adjective\n An adverb that is derived from an adjective,\n e.g., \"correctly\" is derived from the adjective \"correct.\"\n
    entailment\n A verb that presupposes another,\n e.g., \"snoring\" entails \"sleeping.\"\n
    hypernym\n A word with a broad meaning that more specific words fall under,\n e.g., \"meal\" is a hypernym of \"breakfast.\"\n
    hyponym\n A word of more specific meaning than a general term applicable to it,\n e.g., \"breakfast\" is a hyponym of \"meal.\"\n
    instance hypernym\n A word that denotes a category of some specific instance,\n e.g., \"author\" is an instance hypernym of \"Asimov.\"\n
    instance hyponym\n A term that donotes a specific instance of some general category,\n e.g., \"Asimov\" is an instance hyponym of \"author.\"\n
    member holonym\n A word that denotes a collection of individuals,\n e.g., \"faculty\" is a member holonym of \"professor.\"\n
    member meronym\n A word that denotes a member of a larger group,\n e.g., a \"person\" is a member meronym of a \"crowd.\"\n
    part holonym\n A word that denotes a larger whole comprised of some part,\n e.g., \"car\" is a part holonym of \"engine.\"\n
    part meronym\n A word that denotes a part of a larger whole,\n e.g., an \"engine\" is part meronym of a \"car.\"\n
    participle of verb\n An adjective that is the participle of some verb,\n e.g., \"breaking\" is the participle of the verb \"break.\"\n
    pertainym\n An adjective that classifies its noun,\n e.g., \"musical\" is a pertainym in \"musical instrument.\"\n
    similar to\n Similar, though not necessarily interchangeable, adjectives.\n For example, \"shiny\" is similar to \"bright\",\n but they have subtle differences.\n
    substance holonym\n A word that denotes a larger whole containing some constituent\n substance, e.g., \"bread\" is a substance holonym of \"flour.\"\n
    substance meronym\n A word that denotes a constituant substance of some larger whole,\n e.g., \"flour\" is a substance meronym of \"bread.\"\n
    verb group\n A verb that is a member of a group of similar verbs,\n e.g., \"live\" is in the verb group\n of \"dwell\", \"live\", \"inhabit\", etc.\n
    \n", "sees" : [ ], "authors" : [ "Paul J. Lucas" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://www.28msec.com/modules/full-text", "prefix" : "ft" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" }, { "uri" : "http://zorba.io/modules/full-text", "prefix" : "zft" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "is-stem-lang-supported", "qname" : "ft:is-stem-lang-supported", "signature" : "($lang as language) as boolean", "description" : " Checks whether the given language is supported for stemming.\n", "summary" : "

    Checks whether the given language is supported for stemming.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lang", "type" : "language", "occurrence" : null, "description" : "
    The language to check.
    " } ], "returns" : { "type" : "boolean", "description" : "true only if the language is supported." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-stop-word-lang-supported", "qname" : "ft:is-stop-word-lang-supported", "signature" : "($lang as language) as boolean", "description" : " Checks whether the given language\n is supported for stop words.\n", "summary" : "

    Checks whether the given language\n is supported for stop words.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lang", "type" : "language", "occurrence" : null, "description" : "
    The language to check.
    " } ], "returns" : { "type" : "boolean", "description" : "true only if the language is supported." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-stop-word", "qname" : "ft:is-stop-word", "signature" : "($word as string) as boolean", "description" : " Checks whether the given word is a stop-word.\n", "summary" : "

    Checks whether the given word is a stop-word.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "word", "type" : "string", "occurrence" : null, "description" : "
    The word to check. The word's language is assumed to be the one returned by ft:current-lang().
    " } ], "returns" : { "type" : "boolean", "description" : "true only if $word is a stop-word." }, "errors" : [ "err:FTST0009 if ft:current-lang() is not supported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "is-stop-word", "qname" : "ft:is-stop-word", "signature" : "($word as string, $lang as language) as boolean", "description" : " Checks whether the given word is a stop-word.\n", "summary" : "

    Checks whether the given word is a stop-word.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "word", "type" : "string", "occurrence" : null, "description" : "
    The word to check.
    " }, { "name" : "lang", "type" : "language", "occurrence" : null, "description" : "
    The language of $word.
    " } ], "returns" : { "type" : "boolean", "description" : "true only if $word is a stop-word." }, "errors" : [ "err:FTST0009 if $lang is not supported." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-thesaurus-lang-supported", "qname" : "ft:is-thesaurus-lang-supported", "signature" : "($lang as language) as boolean", "description" : " Checks whether the given language\n is supported for look-up using the Wordnet thesaurus.\n", "summary" : "

    Checks whether the given language\n is supported for look-up using the Wordnet thesaurus.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lang", "type" : "language", "occurrence" : null, "description" : "
    The language to check.
    " } ], "returns" : { "type" : "boolean", "description" : "true only if the language is supported." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-tokenizer-lang-supported", "qname" : "ft:is-tokenizer-lang-supported", "signature" : "($lang as language) as boolean", "description" : " Checks whether the given language\n is supported for tokenization.\n", "summary" : "

    Checks whether the given language\n is supported for tokenization.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lang", "type" : "language", "occurrence" : null, "description" : "
    The language to check.
    " } ], "returns" : { "type" : "boolean", "description" : "true only if the language is supported." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "stem", "qname" : "ft:stem", "signature" : "($word as string) as string", "description" : " Stems the given word.\n", "summary" : "

    Stems the given word.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "word", "type" : "string", "occurrence" : null, "description" : "
    The word to stem. The word's language is assumed to be the one returned by ft:current-lang().
    " } ], "returns" : { "type" : "string", "description" : "the stem of $word." }, "errors" : [ "err:FTST0009 if ft:current-lang() is not supported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "stem", "qname" : "ft:stem", "signature" : "($word as string, $lang as language) as string", "description" : " Stems the given word.\n", "summary" : "

    Stems the given word.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "word", "type" : "string", "occurrence" : null, "description" : "
    The word to stem.
    " }, { "name" : "lang", "type" : "language", "occurrence" : null, "description" : "
    The language of $word.
    " } ], "returns" : { "type" : "string", "description" : "the stem of $word." }, "errors" : [ "err:FTST0009 if $lang is not supported." ] }, { "isDocumented" : true, "arity" : 1, "name" : "strip-diacritics", "qname" : "ft:strip-diacritics", "signature" : "($string as string) as string", "description" : " Strips all diacritical marks from all characters.\n", "summary" : "

    Strips all diacritical marks from all characters.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "string", "type" : "string", "occurrence" : null, "description" : "
    The string to strip diacritical marks from.
    " } ], "returns" : { "type" : "string", "description" : "$string with diacritical marks stripped." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "thesaurus-lookup", "qname" : "ft:thesaurus-lookup", "signature" : "($phrase as string) as string*", "description" : " Looks-up the given phrase in the Wordnet thesaurus.\n", "summary" : "

    Looks-up the given phrase in the Wordnet thesaurus.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "phrase", "type" : "string", "occurrence" : null, "description" : "
    The phrase to look up.
    " } ], "returns" : { "type" : "string*", "description" : "the related phrases if $phrase is found in the thesaurus or the empty sequence if not." }, "errors" : [ "err:FTST0009 if ft:current-lang() is not supported.", "zerr:ZXQP8401 if the thesaurus data file's version is not supported by the currently running version of Zorba.", "zerr:ZXQP8402 if the thesaurus data file's endianness does not match that of the CPU on which Zorba is currently running.", "zerr:ZXQP8403 if there was an error reading the thesaurus data." ] }, { "isDocumented" : true, "arity" : 2, "name" : "thesaurus-lookup", "qname" : "ft:thesaurus-lookup", "signature" : "($phrase as string, $relationship as string) as string*", "description" : " Looks-up the given phrase in a thesaurus.\n", "summary" : "

    Looks-up the given phrase in a thesaurus.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "phrase", "type" : "string", "occurrence" : null, "description" : "
    The phrase to look up.
    " }, { "name" : "relationship", "type" : "string", "occurrence" : null, "description" : "
    The relationship the results are to have to $phrase.
    " } ], "returns" : { "type" : "string*", "description" : "the related phrases if $phrase is found in the thesaurus or the empty sequence if not." }, "errors" : [ "err:FTST0018 if $uri refers to a thesaurus that is not found in the statically known thesauri.", "err:FTST0009 if $lang is not supported.", "zerr:ZOSE0001 if the thesaurus data file could not be found.", "zerr:ZOSE0002 if the thesaurus data file is not a plain file.", "zerr:ZXQP8401 if the thesaurus data file's version is not supported by the currently running version of Zorba.", "zerr:ZXQP8402 if the thesaurus data file's endianness does not match that of the CPU on which Zorba is currently running.", "zerr:ZXQP8403 if there was an error reading the thesaurus data file." ] }, { "isDocumented" : true, "arity" : 4, "name" : "thesaurus-lookup", "qname" : "ft:thesaurus-lookup", "signature" : "($phrase as string, $relationship as string, $level-least as integer, $level-most as integer) as string*", "description" : " Looks-up the given phrase in a thesaurus.\n", "summary" : "

    Looks-up the given phrase in a thesaurus.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "phrase", "type" : "string", "occurrence" : null, "description" : "
    The phrase to look up.
    " }, { "name" : "relationship", "type" : "string", "occurrence" : null, "description" : "
    The relationship the results are to have to $phrase.
    " }, { "name" : "level-least", "type" : "integer", "occurrence" : null, "description" : "
    The minimum number of levels within the thesaurus to be traversed.
    " }, { "name" : "level-most", "type" : "integer", "occurrence" : null, "description" : "
    The maximum number of levels within the thesaurus to be traversed.
    " } ], "returns" : { "type" : "string*", "description" : "the related phrases if $phrase is found in the thesaurus or the empty sequence if not." }, "errors" : [ "err:FOCA0003 if either $level-least or $level-most is either negative or too large.", "err:FTST0018 if $uri refers to a thesaurus that is not found in the statically known thesauri.", "err:FTST0009 if $lang is not supported.", "zerr:ZOSE0001 if the thesaurus data file could not be found.", "zerr:ZOSE0002 if the thesaurus data file is not a plain file.", "zerr:ZXQP8401 if the thesaurus data file's version is not supported by the currently running version of Zorba.", "zerr:ZXQP8402 if the thesaurus data file's endianness does not match that of the CPU on which Zorba is currently running.", "zerr:ZXQP8403 if there was an error reading the thesaurus data file." ] }, { "isDocumented" : true, "arity" : 1, "name" : "tokenize", "qname" : "ft:tokenize", "signature" : "($string as string) as string*", "description" : " Tokenizes the given string.\n", "summary" : "

    Tokenizes the given string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "string", "type" : "string", "occurrence" : null, "description" : "
    The string to tokenize. The string's language is assumed to be the one returned by ft:current-lang().
    " } ], "returns" : { "type" : "string*", "description" : "a (possibly empty) sequence of tokens." }, "errors" : [ "err:FTST0009 if ft:current-lang() is not supported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "tokenize", "qname" : "ft:tokenize", "signature" : "($string as string, $lang as language) as string*", "description" : " Tokenizes the given string.\n", "summary" : "

    Tokenizes the given string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "string", "type" : "string", "occurrence" : null, "description" : "
    The string to tokenize.
    " }, { "name" : "lang", "type" : "language", "occurrence" : null, "description" : "
    The language of $string.
    " } ], "returns" : { "type" : "string*", "description" : "a (possibly empty) sequence of tokens." }, "errors" : [ "err:FTST0009 if $lang is not supported." ] } ], "variables" : [ { "name" : "ft:lang-da", "type" : "language", "description" : " Predeclared constant for the Danish language.\n" }, { "name" : "ft:lang-de", "type" : "language", "description" : " Predeclared constant for the German language.\n" }, { "name" : "ft:lang-en", "type" : "language", "description" : " Predeclared constant for the English language.\n" }, { "name" : "ft:lang-es", "type" : "language", "description" : " Predeclared constant for the Spanish language.\n" }, { "name" : "ft:lang-fi", "type" : "language", "description" : " Predeclared constant for the Finnish language.\n" }, { "name" : "ft:lang-fr", "type" : "language", "description" : " Predeclared constant for the French language.\n" }, { "name" : "ft:lang-hu", "type" : "language", "description" : " Predeclared constant for the Hungarian language.\n" }, { "name" : "ft:lang-it", "type" : "language", "description" : " Predeclared constant for the Italian language.\n" }, { "name" : "ft:lang-nl", "type" : "language", "description" : " Predeclared constant for the Dutch language.\n" }, { "name" : "ft:lang-no", "type" : "language", "description" : " Predeclared constant for the Norwegian language.\n" }, { "name" : "ft:lang-pt", "type" : "language", "description" : " Predeclared constant for the Portuguese language.\n" }, { "name" : "ft:lang-ro", "type" : "language", "description" : " Predeclared constant for the Romanian language.\n" }, { "name" : "ft:lang-ru", "type" : "language", "description" : " Predeclared constant for the Russian language.\n" }, { "name" : "ft:lang-sv", "type" : "language", "description" : " Predeclared constant for the Swedish language.\n" }, { "name" : "ft:lang-tr", "type" : "language", "description" : " Predeclared constant for the Turkish language.\n" } ] }, "http://xbrl.io/modules/bizql/report-schemas" : { "ns" : "http://xbrl.io/modules/bizql/report-schemas", "description" : "

    This module provides functions for storing, retrieving, and modifying\n report schemas. Report schemas can be used in BizQL queries. They can be\n instantiated generating a business report.

    \n

    Report schemas are nothing else than a user-defined component. However,\n one of their hypercubes (the default hypercube), as well as two of their\n networks (presentation, concept-map) are special. A report schema is identified\n with an RID (Report schema ID).

    \n

    With this module, you can retrieve facts from an archive according to a report\n schema. You can retrieve them as a (2D) fact table, or populate the presentation\n network of the report schema with them. The concept map network will be used\n by default to map the report schema concepts to reported concepts.

    \n

    Report schemas are stored in the collection reportschemas in\n the project's MongoDB database.

    \n

    A report schema needs to be a syntactically valid JSound document.

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://xbrl.io/modules/bizql/hypercubes", "prefix" : "hypercubes" }, { "uri" : "http://xbrl.io/modules/bizql/networks", "prefix" : "networks" }, { "uri" : "http://xbrl.io/modules/bizql/report-schemas", "prefix" : "report-schemas" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "add", "qname" : "report-schemas:add", "signature" : "($report-schema as object()) as empty-sequence()", "description" : "

    Adds the given report schema to the database.

    \n", "summary" : "

    Adds the given report schema to the database.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "report-schema", "type" : "object()", "occurrence" : null, "description" : "
    the report schema to add.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty sequence." }, "errors" : [ "report-schemas:INVALID-SCHEMA if the given report schema object does not contain a name field", "report-schemas:EXISTS if a report schema with the given name already exists" ] }, { "isDocumented" : true, "arity" : 1, "name" : "delete", "qname" : "report-schemas:delete", "signature" : "($report-schema-or-id as item()) as empty-sequence()", "description" : "

    Deletes a report schema from the database.

    \n", "summary" : "

    Deletes a report schema from the database.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "report-schema-or-id", "type" : "item()", "occurrence" : null, "description" : "
    the report schema to delete or its RID.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty sequence." }, "errors" : [ "report-schemas:DOES-NOT-EXIST if no report schema with the given RID exists." ] }, { "isDocumented" : true, "arity" : 2, "name" : "fact-table", "qname" : "report-schemas:fact-table", "signature" : "($schema as item(), $archives as item()*) as array()", "description" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied schema, and populates them with the default dimension values\n when missing.

    \n", "summary" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied schema, and populates them with the default dimension values\n when missing.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "schema", "type" : "item()", "occurrence" : null, "description" : "
    a schema or its RID,
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs.
    " } ], "returns" : { "type" : "array()", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "fact-table", "qname" : "report-schemas:fact-table", "signature" : "($schema as item(), $archives as item()*, $options as object()?) as array()", "description" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied schema, and populates them with the default dimension values\n when missing.

    \n", "summary" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied schema, and populates them with the default dimension values\n when missing.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "schema", "type" : "item()", "occurrence" : null, "description" : "
    a schema or its RID,
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs or $report-schemas:ALL_ARCHIVES for no filtering.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "array()", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "facts", "qname" : "report-schemas:facts", "signature" : "($schema as item(), $archives as item()*) as object()*", "description" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied schema, and populates them with the default dimension values\n when missing.

    \n", "summary" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied schema, and populates them with the default dimension values\n when missing.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "schema", "type" : "item()", "occurrence" : null, "description" : "
    a report schema or its RID,
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs or $report-schemas:ALL_ARCHIVES for no filtering.
    " } ], "returns" : { "type" : "object()*", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "facts", "qname" : "report-schemas:facts", "signature" : "($schema as item(), $archives as item()*, $options as object()?) as object()*", "description" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied schema, and populates them with the default dimension values\n when missing.

    \n", "summary" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied schema, and populates them with the default dimension values\n when missing.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "schema", "type" : "item()", "occurrence" : null, "description" : "
    a report schema or its RID,
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs or $report-schemas:ALL_ARCHIVES for no filtering.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "populate-with-facts", "qname" : "report-schemas:populate-with-facts", "signature" : "($schema as item(), $archives as item()*) as object()*", "description" : "

    Populates a concept-tree network with all facts from the supplied archives,\n that are relevant to the\n supplied schema. Default dimension values are added to the facts\n when missing.

    \n", "summary" : "

    Populates a concept-tree network with all facts from the supplied archives,\n that are relevant to the\n supplied schema.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "schema", "type" : "item()", "occurrence" : null, "description" : "
    .
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs or $report-schemas:ALL_ARCHIVES for no filtering.
    " } ], "returns" : { "type" : "object()*", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "populate-with-facts", "qname" : "report-schemas:populate-with-facts", "signature" : "($schema as item(), $archives as item()*, $options as object()?) as object()*", "description" : "

    Populates a concept-tree network with all facts from the supplied archives,\n that are relevant to the\n supplied schema. Default dimension values are added to the facts\n when missing.

    \n", "summary" : "

    Populates a concept-tree network with all facts from the supplied archives,\n that are relevant to the\n supplied schema.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "schema", "type" : "item()", "occurrence" : null, "description" : "
    .
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs or $report-schemas:ALL_ARCHIVES for no filtering.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "report-schemas", "qname" : "report-schemas:report-schemas", "signature" : "() as object()*", "description" : "

    Retrieves all report schemas.

    \n", "summary" : "

    Retrieves all report schemas.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()*", "description" : "all report schemas." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "report-schemas", "qname" : "report-schemas:report-schemas", "signature" : "($report-schemas-or-ids as item()*) as object()*", "description" : "

    Return the report schemas with the given names (RIDs).

    \n", "summary" : "

    Return the report schemas with the given names (RIDs).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "report-schemas-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    the ids of the report schemas (RIDs) or the report schemas themselves.
    " } ], "returns" : { "type" : "object()*", "description" : "the report schemas with the given RIDs or the empty sequence if no report schema was found or the input is an empty sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "rid", "qname" : "report-schemas:rid", "signature" : "($report-schema-or-id as item()) as atomic", "description" : "

    Converts the input to a normalized report schema identifier (RID). The input\n can be either a pure RID, or a report schema object which contains an RID.

    \n", "summary" : "

    Converts the input to a normalized report schema identifier (RID).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "report-schema-or-id", "type" : "item()", "occurrence" : null, "description" : "
    a report schema identifier (RID)) or a report schema object.
    " } ], "returns" : { "type" : "atomic", "description" : "the normalized RID." }, "errors" : [ "report-schemas:INVALID_PARAMETER if the RID or report schema is not valid" ] }, { "isDocumented" : true, "arity" : 1, "name" : "update", "qname" : "report-schemas:update", "signature" : "($report-schema as object()) as empty-sequence()", "description" : "

    Updates a report schema.

    \n

    Replaces a report schema in the database with the given schema.\n The schema to be replaced is identified by the value of the _id\n field of the given schema (RID).

    \n", "summary" : "

    Updates a report schema.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "report-schema", "type" : "object()", "occurrence" : null, "description" : "
    the new report schema
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty sequence" }, "errors" : [ "report-schemas:DOES-NOT-EXIST if a report schema with the given name does not exist." ] } ], "variables" : [ { "name" : "report-schemas:col", "type" : "string", "description" : " Name of the collection the report schemas are stored in.\n" }, { "name" : "report-schemas:ALL_ARCHIVES", "type" : "boolean", "description" : " Joker for all archives.\n" } ] }, "http://zorba.io/modules/store/static/integrity-constraints/ddl" : { "ns" : "http://zorba.io/modules/store/static/integrity-constraints/ddl", "description" : " This module defines a set of functions to manage integrity constraints\n that are declared in the prolog of a module.\n For example, it provides functions to activate or deactivate integrity\n constraints.\n

    \n This module is part of\n Zorba's XQuery Data Definition Facility.\n All the integrity constraints managed by this module have to be pre-declared\n in the prolog of a module.\n Please refer to the\n general documentation\n for more information and examples.\n", "sees" : [ "Data Lifecycle", "XQuery Data Definition Facility", "http://zorba.io/modules/store/static/collections/dml", "http://zorba.io/modules/store/static/collections/ddl", "http://zorba.io/modules/store/static/indexes/ddl", "http://zorba.io/modules/store/static/indexes/dml", "http://zorba.io/modules/store/static/integrity-constraints/dml", "http://zorba.io/errors" ], "authors" : [ "Nicolae Brinza, Matthias Brantner, David Graf, Till Westmann, Markos Zaharioudakis" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/store/static/integrity-constraints/ddl", "prefix" : "icddl" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "activate", "qname" : "icddl:activate", "signature" : "($name as xs:QName) external", "description" : " Activates an integrity constraint in the dynamic context.\n", "summary" : "

    Activates an integrity constraint in the dynamic context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the integrity constraint to activate.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that consists of a upd:activateIntegrityConstraint($name) update primitive." }, "errors" : [ "zerr:ZDDY0031 if the integrity constraint does not exist in the static context." ] }, { "isDocumented" : true, "arity" : 0, "name" : "activated-integrity-constraints", "qname" : "icddl:activated-integrity-constraints", "signature" : "() as xs:QName* external", "description" : " Gets the integrity constraints that are activated, if any.\n", "summary" : "

    Gets the integrity constraints that are activated, if any.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName*", "description" : "A sequence of QNames, one for each activated integrity constraint, or an empty sequence if none." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "deactivate", "qname" : "icddl:deactivate", "signature" : "($name as xs:QName) external", "description" : " Deactivates the integrity constraint.\n", "summary" : "

    Deactivates the integrity constraint.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the integrity constraint to deactivate.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, deactivates the integrity constraint." }, "errors" : [ "zerr:ZDDY0032 if the integrity constraint was not declared in the the static context.", "zerr:ZDDY0032 if the integrity constraints is not activated." ] }, { "isDocumented" : true, "arity" : 0, "name" : "declared-integrity-constraints", "qname" : "icddl:declared-integrity-constraints", "signature" : "() as xs:QName* external", "description" : " Gets the sequence of QNames representing the integrity constraints that have\n been declared in the prolog of the static context.\n", "summary" : "

    Gets the sequence of QNames representing the integrity constraints that have\n been declared in the prolog of the static context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:QName*", "description" : "A sequence of QNames, one for each created integrity constraints, or an emtpy sequence if none." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-activated-integrity-constraint", "qname" : "icddl:is-activated-integrity-constraint", "signature" : "($name as xs:QName) as xs:boolean external", "description" : " Gets whether an integrity constraints is activated.\n", "summary" : "

    Gets whether an integrity constraints is activated.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the constraint to check.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the integrity constraint is activated; false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-declared-integrity-constraint", "qname" : "icddl:is-declared-integrity-constraint", "signature" : "($name as xs:QName) as xs:boolean external", "description" : " Gets whether an integrity constraint is declared in the prolog of the static\n context.\n", "summary" : "

    Gets whether an integrity constraint is declared in the prolog of the static\n context.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the constraint to check.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the constraint is declared; false otherwise." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.functx.com" : { "ns" : "http://www.functx.com", "description" : " --------------------------------\n The FunctX XQuery Function Library\n --------------------------------\n Copyright (C) 2007 Datypic\n This library is free software; you can redistribute it and/or\n modify it under the terms of the GNU Lesser General Public\n License as published by the Free Software Foundation; either\n version 2.1 of the License.\n This library is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n Lesser General Public License for more details.\n You should have received a copy of the GNU Lesser General Public\n License along with this library; if not, write to the Free Software\n Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n For more information on the FunctX XQuery library, contact contrib@functx.com.\n", "sees" : [ "http://www.xqueryfunctions.com" ], "authors" : [ ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.functx.com", "prefix" : "functx" } ], "functions" : [ { "isDocumented" : true, "arity" : 3, "name" : "add-attributes", "qname" : "functx:add-attributes", "signature" : "($elements as element(*)*, $attrNames as xs:QName*, $attrValues as xs:anyAtomicType*) as element(*)?", "description" : " Adds attributes to XML elements\n", "summary" : "

    Adds attributes to XML elements\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "elements", "type" : "element(*)", "occurrence" : "*", "description" : "
    the element(s) to which you wish to add the attribute
    " }, { "name" : "attrNames", "type" : "xs:QName", "occurrence" : "*", "description" : "
    the name(s) of the attribute(s) to add
    " }, { "name" : "attrValues", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the value(s) of the attribute(s) to add
    " } ], "returns" : { "type" : "element(*)?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "add-months", "qname" : "functx:add-months", "signature" : "($date as xs:anyAtomicType?, $months as xs:integer) as xs:date?", "description" : " Adds months to a date\n", "summary" : "

    Adds months to a date\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " }, { "name" : "months", "type" : "xs:integer", "occurrence" : null, "description" : "
    the number of months to add
    " } ], "returns" : { "type" : "xs:date?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "add-or-update-attributes", "qname" : "functx:add-or-update-attributes", "signature" : "($elements as element(*)*, $attrNames as xs:QName*, $attrValues as xs:anyAtomicType*) as element(*)?", "description" : " Adds attributes to XML elements\n", "summary" : "

    Adds attributes to XML elements\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "elements", "type" : "element(*)", "occurrence" : "*", "description" : "
    the element(s) to which you wish to add the attribute
    " }, { "name" : "attrNames", "type" : "xs:QName", "occurrence" : "*", "description" : "
    the name(s) of the attribute(s) to add
    " }, { "name" : "attrValues", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the value(s) of the attribute(s) to add
    " } ], "returns" : { "type" : "element(*)?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "all-whitespace", "qname" : "functx:all-whitespace", "signature" : "($arg as xs:string?) as xs:boolean", "description" : " Whether a value is all whitespace or a zero-length string\n", "summary" : "

    Whether a value is all whitespace or a zero-length string\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string (or node) to test
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "are-distinct-values", "qname" : "functx:are-distinct-values", "signature" : "($seq as xs:anyAtomicType*) as xs:boolean", "description" : " Whether all the values in a sequence are distinct\n", "summary" : "

    Whether all the values in a sequence are distinct\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of values
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "atomic-type", "qname" : "functx:atomic-type", "signature" : "($values as xs:anyAtomicType*) as xs:string*", "description" : " The built-in type of an atomic value\n", "summary" : "

    The built-in type of an atomic value\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "values", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the value(s) whose type you want to determine
    " } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "avg-empty-is-zero", "qname" : "functx:avg-empty-is-zero", "signature" : "($values as xs:anyAtomicType*, $allNodes as node()*) as xs:double", "description" : " The average, counting \"empty\" values as zero\n", "summary" : "

    The average, counting \"empty\" values as zero\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "values", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the values to be averaged
    " }, { "name" : "allNodes", "type" : "node()", "occurrence" : "*", "description" : "
    the sequence of all nodes to find the average over
    " } ], "returns" : { "type" : "xs:double", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "between-exclusive", "qname" : "functx:between-exclusive", "signature" : "($value as xs:anyAtomicType?, $minValue as xs:anyAtomicType, $maxValue as xs:anyAtomicType) as xs:boolean", "description" : " Whether a value is between two provided values\n", "summary" : "

    Whether a value is between two provided values\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the value to be tested
    " }, { "name" : "minValue", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the minimum value
    " }, { "name" : "maxValue", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the maximum value
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "between-inclusive", "qname" : "functx:between-inclusive", "signature" : "($value as xs:anyAtomicType?, $minValue as xs:anyAtomicType, $maxValue as xs:anyAtomicType) as xs:boolean", "description" : " Whether a value is between two provided values, or equal to one of them\n", "summary" : "

    Whether a value is between two provided values, or equal to one of them\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the value to be tested
    " }, { "name" : "minValue", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the minimum value
    " }, { "name" : "maxValue", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the maximum value
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "camel-case-to-words", "qname" : "functx:camel-case-to-words", "signature" : "($arg as xs:string?, $delim as xs:string) as xs:string", "description" : " Turns a camelCase string into space-separated words\n", "summary" : "

    Turns a camelCase string into space-separated words\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to modify
    " }, { "name" : "delim", "type" : "xs:string", "occurrence" : null, "description" : "
    the delimiter for the words (e.g. a space)
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "capitalize-first", "qname" : "functx:capitalize-first", "signature" : "($arg as xs:string?) as xs:string?", "description" : " Capitalizes the first character of a string\n", "summary" : "

    Capitalizes the first character of a string\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the word or phrase to capitalize
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "change-element-names-deep", "qname" : "functx:change-element-names-deep", "signature" : "($nodes as node()*, $oldNames as xs:QName*, $newNames as xs:QName*) as node()*", "description" : " Changes the names of elements in an XML fragment\n", "summary" : "

    Changes the names of elements in an XML fragment\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the element(s) to change
    " }, { "name" : "oldNames", "type" : "xs:QName", "occurrence" : "*", "description" : "
    the sequence of names to change from
    " }, { "name" : "newNames", "type" : "xs:QName", "occurrence" : "*", "description" : "
    the sequence of names to change to
    " } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "change-element-ns-deep", "qname" : "functx:change-element-ns-deep", "signature" : "($nodes as node()*, $newns as xs:string, $prefix as xs:string) as node()*", "description" : " Changes the namespace of XML elements and its descendants\n", "summary" : "

    Changes the namespace of XML elements and its descendants\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the nodes to change
    " }, { "name" : "newns", "type" : "xs:string", "occurrence" : null, "description" : "
    the new namespace
    " }, { "name" : "prefix", "type" : "xs:string", "occurrence" : null, "description" : "
    the prefix to use for the new namespace
    " } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "change-element-ns", "qname" : "functx:change-element-ns", "signature" : "($elements as element(*)*, $newns as xs:string, $prefix as xs:string) as element(*)?", "description" : " Changes the namespace of XML elements\n", "summary" : "

    Changes the namespace of XML elements\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "elements", "type" : "element(*)", "occurrence" : "*", "description" : "
    the elements to change
    " }, { "name" : "newns", "type" : "xs:string", "occurrence" : null, "description" : "
    the new namespace
    " }, { "name" : "prefix", "type" : "xs:string", "occurrence" : null, "description" : "
    the prefix to use for the new namespace
    " } ], "returns" : { "type" : "element(*)?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "chars", "qname" : "functx:chars", "signature" : "($arg as xs:string?) as xs:string*", "description" : " Converts a string to a sequence of characters\n", "summary" : "

    Converts a string to a sequence of characters\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to split
    " } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "contains-any-of", "qname" : "functx:contains-any-of", "signature" : "($arg as xs:string?, $searchStrings as xs:string*) as xs:boolean", "description" : " Whether a string contains any of a sequence of strings\n", "summary" : "

    Whether a string contains any of a sequence of strings\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to test
    " }, { "name" : "searchStrings", "type" : "xs:string", "occurrence" : "*", "description" : "
    the strings to look for
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "contains-case-insensitive", "qname" : "functx:contains-case-insensitive", "signature" : "($arg as xs:string?, $substring as xs:string) as xs:boolean?", "description" : " Whether one string contains another, without regard to case\n", "summary" : "

    Whether one string contains another, without regard to case\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to search
    " }, { "name" : "substring", "type" : "xs:string", "occurrence" : null, "description" : "
    the substring to find
    " } ], "returns" : { "type" : "xs:boolean?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "contains-word", "qname" : "functx:contains-word", "signature" : "($arg as xs:string?, $word as xs:string) as xs:boolean", "description" : " Whether one string contains another, as a separate word\n", "summary" : "

    Whether one string contains another, as a separate word\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to search
    " }, { "name" : "word", "type" : "xs:string", "occurrence" : null, "description" : "
    the word to find
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "copy-attributes", "qname" : "functx:copy-attributes", "signature" : "($copyTo as element(*), $copyFrom as element(*)) as element(*)", "description" : " Copies attributes from one element to another\n", "summary" : "

    Copies attributes from one element to another\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "copyTo", "type" : "element(*)", "occurrence" : null, "description" : "
    the element to copy attributes to
    " }, { "name" : "copyFrom", "type" : "element(*)", "occurrence" : null, "description" : "
    the element to copy attributes from
    " } ], "returns" : { "type" : "element(*)", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "date", "qname" : "functx:date", "signature" : "($year as xs:anyAtomicType, $month as xs:anyAtomicType, $day as xs:anyAtomicType) as xs:date", "description" : " Construct a date from a year, month and day\n", "summary" : "

    Construct a date from a year, month and day\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "year", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the year
    " }, { "name" : "month", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the month
    " }, { "name" : "day", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the day
    " } ], "returns" : { "type" : "xs:date", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "dateTime", "qname" : "functx:dateTime", "signature" : "($year as xs:anyAtomicType, $month as xs:anyAtomicType, $day as xs:anyAtomicType, $hour as xs:anyAtomicType, $minute as xs:anyAtomicType, $second as xs:anyAtomicType) as xs:dateTime", "description" : " Construct a date/time from individual components\n", "summary" : "

    Construct a date/time from individual components\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "year", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the year
    " }, { "name" : "month", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the month
    " }, { "name" : "day", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the day
    " }, { "name" : "hour", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the hour
    " }, { "name" : "minute", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the minute
    " }, { "name" : "second", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the second
    " } ], "returns" : { "type" : "xs:dateTime", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "day-in-year", "qname" : "functx:day-in-year", "signature" : "($date as xs:anyAtomicType?) as xs:integer?", "description" : " The day of the year (a number between 1 and 366)\n", "summary" : "

    The day of the year (a number between 1 and 366)\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "day-of-week-abbrev-en", "qname" : "functx:day-of-week-abbrev-en", "signature" : "($date as xs:anyAtomicType?) as xs:string?", "description" : " The abbreviated day of the week, from a date, in English\n", "summary" : "

    The abbreviated day of the week, from a date, in English\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "day-of-week-name-en", "qname" : "functx:day-of-week-name-en", "signature" : "($date as xs:anyAtomicType?) as xs:string?", "description" : " The name of the day of the week, from a date, in English\n", "summary" : "

    The name of the day of the week, from a date, in English\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "day-of-week", "qname" : "functx:day-of-week", "signature" : "($date as xs:anyAtomicType?) as xs:integer?", "description" : " The day of the week, from a date\n", "summary" : "

    The day of the week, from a date\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "dayTimeDuration", "qname" : "functx:dayTimeDuration", "signature" : "($days as xs:decimal?, $hours as xs:decimal?, $minutes as xs:decimal?, $seconds as xs:decimal?) as xs:dayTimeDuration", "description" : " Construct a dayTimeDuration from a number of days, hours, etc.\n", "summary" : "

    Construct a dayTimeDuration from a number of days, hours, etc.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "days", "type" : "xs:decimal", "occurrence" : "?", "description" : "
    the number of days
    " }, { "name" : "hours", "type" : "xs:decimal", "occurrence" : "?", "description" : "
    the number of hours
    " }, { "name" : "minutes", "type" : "xs:decimal", "occurrence" : "?", "description" : "
    the number of minutes
    " }, { "name" : "seconds", "type" : "xs:decimal", "occurrence" : "?", "description" : "
    the number of seconds
    " } ], "returns" : { "type" : "xs:dayTimeDuration", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "days-in-month", "qname" : "functx:days-in-month", "signature" : "($date as xs:anyAtomicType?) as xs:integer?", "description" : " Number of days in the month\n", "summary" : "

    Number of days in the month\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "depth-of-node", "qname" : "functx:depth-of-node", "signature" : "($node as node()?) as xs:integer", "description" : " The depth (level) of a node in an XML tree\n", "summary" : "

    The depth (level) of a node in an XML tree\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : "?", "description" : "
    the node to check
    " } ], "returns" : { "type" : "xs:integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "distinct-attribute-names", "qname" : "functx:distinct-attribute-names", "signature" : "($nodes as node()*) as xs:string*", "description" : " The distinct names of all attributes in an XML fragment\n", "summary" : "

    The distinct names of all attributes in an XML fragment\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the root to start from
    " } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "distinct-deep", "qname" : "functx:distinct-deep", "signature" : "($nodes as node()*) as node()*", "description" : " The XML nodes with distinct values, taking into account attributes and descendants\n", "summary" : "

    The XML nodes with distinct values, taking into account attributes and descendants\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the sequence of nodes to test
    " } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "distinct-element-names", "qname" : "functx:distinct-element-names", "signature" : "($nodes as node()*) as xs:string*", "description" : " The distinct names of all elements in an XML fragment\n", "summary" : "

    The distinct names of all elements in an XML fragment\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the root(s) to start from
    " } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "distinct-element-paths", "qname" : "functx:distinct-element-paths", "signature" : "($nodes as node()*) as xs:string*", "description" : " The distinct paths of all descendant elements in an XML fragment\n", "summary" : "

    The distinct paths of all descendant elements in an XML fragment\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the root(s) to start from
    " } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "distinct-nodes", "qname" : "functx:distinct-nodes", "signature" : "($nodes as node()*) as node()*", "description" : " The distinct XML nodes in a sequence (by node identity)\n", "summary" : "

    The distinct XML nodes in a sequence (by node identity)\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the node sequence
    " } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "duration-from-timezone", "qname" : "functx:duration-from-timezone", "signature" : "($timezone as xs:string) as xs:dayTimeDuration", "description" : " Converts a timezone like \"-05:00\" or \"Z\" into xs:dayTimeDuration\n", "summary" : "

    Converts a timezone like \"-05:00\" or \"Z\" into xs:dayTimeDuration\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "timezone", "type" : "xs:string", "occurrence" : null, "description" : "
    the time zone, in (+|-)HH:MM format
    " } ], "returns" : { "type" : "xs:dayTimeDuration", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "dynamic-path", "qname" : "functx:dynamic-path", "signature" : "($parent as node(), $path as xs:string) as item()*", "description" : " Dynamically evaluates a simple XPath path\n", "summary" : "

    Dynamically evaluates a simple XPath path\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "parent", "type" : "node()", "occurrence" : null, "description" : "
    the root to start from
    " }, { "name" : "path", "type" : "xs:string", "occurrence" : null, "description" : "
    the path expression
    " } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "escape-for-regex", "qname" : "functx:escape-for-regex", "signature" : "($arg as xs:string?) as xs:string", "description" : " Escapes regex special characters\n", "summary" : "

    Escapes regex special characters\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to escape
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "exclusive-or", "qname" : "functx:exclusive-or", "signature" : "($arg1 as xs:boolean?, $arg2 as xs:boolean?) as xs:boolean?", "description" : " Whether one (and only one) of two boolean values is true\n", "summary" : "

    Whether one (and only one) of two boolean values is true\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:boolean", "occurrence" : "?", "description" : "
    the first boolean value
    " }, { "name" : "arg2", "type" : "xs:boolean", "occurrence" : "?", "description" : "
    the second boolean value
    " } ], "returns" : { "type" : "xs:boolean?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "first-day-of-month", "qname" : "functx:first-day-of-month", "signature" : "($date as xs:anyAtomicType?) as xs:date?", "description" : " The first day of the month of a date\n", "summary" : "

    The first day of the month of a date\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " } ], "returns" : { "type" : "xs:date?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "first-day-of-year", "qname" : "functx:first-day-of-year", "signature" : "($date as xs:anyAtomicType?) as xs:date?", "description" : " The first day of the year of a date\n", "summary" : "

    The first day of the year of a date\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " } ], "returns" : { "type" : "xs:date?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "first-node", "qname" : "functx:first-node", "signature" : "($nodes as node()*) as node()?", "description" : " The XML node in a sequence that appears first in document order\n", "summary" : "

    The XML node in a sequence that appears first in document order\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the sequence of nodes
    " } ], "returns" : { "type" : "node()?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "follows-not-descendant", "qname" : "functx:follows-not-descendant", "signature" : "($a as node()?, $b as node()?) as xs:boolean", "description" : " Whether an XML node follows another without being its descendant\n", "summary" : "

    Whether an XML node follows another without being its descendant\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "a", "type" : "node()", "occurrence" : "?", "description" : "
    the first node
    " }, { "name" : "b", "type" : "node()", "occurrence" : "?", "description" : "
    the second node
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "format-as-title-en", "qname" : "functx:format-as-title-en", "signature" : "($titles as xs:string*) as xs:string*", "description" : " Moves title words like \"the\" and \"a\" to the end of strings\n", "summary" : "

    Moves title words like \"the\" and \"a\" to the end of strings\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "titles", "type" : "xs:string", "occurrence" : "*", "description" : "
    the titles to format
    " } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "fragment-from-uri", "qname" : "functx:fragment-from-uri", "signature" : "($uri as xs:string?) as xs:string?", "description" : " Returns the fragment from a URI\n", "summary" : "

    Returns the fragment from a URI\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : "?", "description" : "
    the URI
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "get-matches-and-non-matches", "qname" : "functx:get-matches-and-non-matches", "signature" : "($string as xs:string?, $regex as xs:string) as element(*)*", "description" : " Splits a string into matching and non-matching regions\n", "summary" : "

    Splits a string into matching and non-matching regions\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "string", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to split
    " }, { "name" : "regex", "type" : "xs:string", "occurrence" : null, "description" : "
    the pattern
    " } ], "returns" : { "type" : "element(*)*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "get-matches", "qname" : "functx:get-matches", "signature" : "($string as xs:string?, $regex as xs:string) as xs:string*", "description" : " Return the matching regions of a string\n", "summary" : "

    Return the matching regions of a string\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "string", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to split
    " }, { "name" : "regex", "type" : "xs:string", "occurrence" : null, "description" : "
    the pattern
    " } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "has-element-only-content", "qname" : "functx:has-element-only-content", "signature" : "($element as element(*)) as xs:boolean", "description" : " Whether an element has element-only content\n", "summary" : "

    Whether an element has element-only content\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "element", "type" : "element(*)", "occurrence" : null, "description" : "
    the XML element to test
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "has-empty-content", "qname" : "functx:has-empty-content", "signature" : "($element as element(*)) as xs:boolean", "description" : " Whether an element has empty content\n", "summary" : "

    Whether an element has empty content\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "element", "type" : "element(*)", "occurrence" : null, "description" : "
    the XML element to test
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "has-mixed-content", "qname" : "functx:has-mixed-content", "signature" : "($element as element(*)) as xs:boolean", "description" : " Whether an element has mixed content\n", "summary" : "

    Whether an element has mixed content\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "element", "type" : "element(*)", "occurrence" : null, "description" : "
    the XML element to test
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "has-simple-content", "qname" : "functx:has-simple-content", "signature" : "($element as element(*)) as xs:boolean", "description" : " Whether an element has simple content\n", "summary" : "

    Whether an element has simple content\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "element", "type" : "element(*)", "occurrence" : null, "description" : "
    the XML element to test
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "id-from-element", "qname" : "functx:id-from-element", "signature" : "($element as element(*)?) as xs:string?", "description" : " Gets the ID of an XML element\n", "summary" : "

    Gets the ID of an XML element\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "element", "type" : "element(*)", "occurrence" : "?", "description" : "
    the element
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "id-untyped", "qname" : "functx:id-untyped", "signature" : "($node as node()*, $id as xs:anyAtomicType) as element(*)*", "description" : " Gets XML element(s) that have an attribute with a particular value\n", "summary" : "

    Gets XML element(s) that have an attribute with a particular value\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : "*", "description" : "
    the root node(s) to start from
    " }, { "name" : "id", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the \"id\" to find
    " } ], "returns" : { "type" : "element(*)*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "if-absent", "qname" : "functx:if-absent", "signature" : "($arg as item()*, $value as item()*) as item()*", "description" : " The first argument if it is not empty, otherwise the second argument\n", "summary" : "

    The first argument if it is not empty, otherwise the second argument\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "*", "description" : "
    the item(s) that may be absent
    " }, { "name" : "value", "type" : "item()", "occurrence" : "*", "description" : "
    the item(s) to use if the item is absent
    " } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "if-empty", "qname" : "functx:if-empty", "signature" : "($arg as item()?, $value as item()*) as item()*", "description" : " The first argument if it is not blank, otherwise the second argument\n", "summary" : "

    The first argument if it is not blank, otherwise the second argument\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : "?", "description" : "
    the node that may be empty
    " }, { "name" : "value", "type" : "item()", "occurrence" : "*", "description" : "
    the item(s) to use if the node is empty
    " } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "index-of-deep-equal-node", "qname" : "functx:index-of-deep-equal-node", "signature" : "($nodes as node()*, $nodeToFind as node()) as xs:integer*", "description" : " The position of a node in a sequence, based on contents and attributes\n", "summary" : "

    The position of a node in a sequence, based on contents and attributes\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the node sequence
    " }, { "name" : "nodeToFind", "type" : "node()", "occurrence" : null, "description" : "
    the node to find in the sequence
    " } ], "returns" : { "type" : "xs:integer*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "index-of-match-first", "qname" : "functx:index-of-match-first", "signature" : "($arg as xs:string?, $pattern as xs:string) as xs:integer?", "description" : " The first position of a matching substring\n", "summary" : "

    The first position of a matching substring\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string
    " }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "
    the pattern to match
    " } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "index-of-node", "qname" : "functx:index-of-node", "signature" : "($nodes as node()*, $nodeToFind as node()) as xs:integer*", "description" : " The position of a node in a sequence, based on node identity\n", "summary" : "

    The position of a node in a sequence, based on node identity\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the node sequence
    " }, { "name" : "nodeToFind", "type" : "node()", "occurrence" : null, "description" : "
    the node to find in the sequence
    " } ], "returns" : { "type" : "xs:integer*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "index-of-string-first", "qname" : "functx:index-of-string-first", "signature" : "($arg as xs:string?, $substring as xs:string) as xs:integer?", "description" : " The first position of a substring\n", "summary" : "

    The first position of a substring\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string
    " }, { "name" : "substring", "type" : "xs:string", "occurrence" : null, "description" : "
    the substring to find
    " } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "index-of-string-last", "qname" : "functx:index-of-string-last", "signature" : "($arg as xs:string?, $substring as xs:string) as xs:integer?", "description" : " The last position of a substring\n", "summary" : "

    The last position of a substring\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string
    " }, { "name" : "substring", "type" : "xs:string", "occurrence" : null, "description" : "
    the substring to find
    " } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "index-of-string", "qname" : "functx:index-of-string", "signature" : "($arg as xs:string?, $substring as xs:string) as xs:integer*", "description" : " The position(s) of a substring\n", "summary" : "

    The position(s) of a substring\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string
    " }, { "name" : "substring", "type" : "xs:string", "occurrence" : null, "description" : "
    the substring to find
    " } ], "returns" : { "type" : "xs:integer*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "insert-string", "qname" : "functx:insert-string", "signature" : "($originalString as xs:string?, $stringToInsert as xs:string?, $pos as xs:integer) as xs:string", "description" : " Inserts a string at a specified position\n", "summary" : "

    Inserts a string at a specified position\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "originalString", "type" : "xs:string", "occurrence" : "?", "description" : "
    the original string to insert into
    " }, { "name" : "stringToInsert", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to insert
    " }, { "name" : "pos", "type" : "xs:integer", "occurrence" : null, "description" : "
    the position
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-a-number", "qname" : "functx:is-a-number", "signature" : "($value as xs:anyAtomicType?) as xs:boolean", "description" : " Whether a value is numeric\n", "summary" : "

    Whether a value is numeric\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the value to test
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-absolute-uri", "qname" : "functx:is-absolute-uri", "signature" : "($uri as xs:string?) as xs:boolean", "description" : " Whether a URI is absolute\n", "summary" : "

    Whether a URI is absolute\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : "?", "description" : "
    the URI to test
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "is-ancestor", "qname" : "functx:is-ancestor", "signature" : "($node1 as node(), $node2 as node()) as xs:boolean", "description" : " Whether an XML node is an ancestor of another node\n", "summary" : "

    Whether an XML node is an ancestor of another node\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node1", "type" : "node()", "occurrence" : null, "description" : "
    the first node
    " }, { "name" : "node2", "type" : "node()", "occurrence" : null, "description" : "
    the second node
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "is-descendant", "qname" : "functx:is-descendant", "signature" : "($node1 as node(), $node2 as node()) as xs:boolean", "description" : " Whether an XML node is a descendant of another node\n", "summary" : "

    Whether an XML node is a descendant of another node\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node1", "type" : "node()", "occurrence" : null, "description" : "
    the first node
    " }, { "name" : "node2", "type" : "node()", "occurrence" : null, "description" : "
    the second node
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-leap-year", "qname" : "functx:is-leap-year", "signature" : "($date as xs:anyAtomicType?) as xs:boolean", "description" : " Whether a date falls in a leap year\n", "summary" : "

    Whether a date falls in a leap year\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date or year
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "is-node-among-descendants-deep-equal", "qname" : "functx:is-node-among-descendants-deep-equal", "signature" : "($node as node()?, $seq as node()*) as xs:boolean", "description" : " Whether an XML node is among the descendants of a sequence, based on contents and attributes\n", "summary" : "

    Whether an XML node is among the descendants of a sequence, based on contents and attributes\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : "?", "description" : "
    the node to test
    " }, { "name" : "seq", "type" : "node()", "occurrence" : "*", "description" : "
    the sequence of nodes to search
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "is-node-among-descendants", "qname" : "functx:is-node-among-descendants", "signature" : "($node as node()?, $seq as node()*) as xs:boolean", "description" : " Whether an XML node is among the descendants of a sequence, based on node identity\n", "summary" : "

    Whether an XML node is among the descendants of a sequence, based on node identity\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : "?", "description" : "
    the node to test
    " }, { "name" : "seq", "type" : "node()", "occurrence" : "*", "description" : "
    the sequence of nodes to search
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "is-node-in-sequence-deep-equal", "qname" : "functx:is-node-in-sequence-deep-equal", "signature" : "($node as node()?, $seq as node()*) as xs:boolean", "description" : " Whether an XML node is in a sequence, based on contents and attributes\n", "summary" : "

    Whether an XML node is in a sequence, based on contents and attributes\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : "?", "description" : "
    the node to test
    " }, { "name" : "seq", "type" : "node()", "occurrence" : "*", "description" : "
    the sequence of nodes to search
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "is-node-in-sequence", "qname" : "functx:is-node-in-sequence", "signature" : "($node as node()?, $seq as node()*) as xs:boolean", "description" : " Whether an XML node is in a sequence, based on node identity\n", "summary" : "

    Whether an XML node is in a sequence, based on node identity\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : "?", "description" : "
    the node to test
    " }, { "name" : "seq", "type" : "node()", "occurrence" : "*", "description" : "
    the sequence of nodes to search
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "is-value-in-sequence", "qname" : "functx:is-value-in-sequence", "signature" : "($value as xs:anyAtomicType?, $seq as xs:anyAtomicType*) as xs:boolean", "description" : " Whether an atomic value appears in a sequence\n", "summary" : "

    Whether an atomic value appears in a sequence\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the atomic value to test
    " }, { "name" : "seq", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of values to search
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "last-day-of-month", "qname" : "functx:last-day-of-month", "signature" : "($date as xs:anyAtomicType?) as xs:date?", "description" : " The last day of the month of a date\n", "summary" : "

    The last day of the month of a date\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " } ], "returns" : { "type" : "xs:date?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "last-day-of-year", "qname" : "functx:last-day-of-year", "signature" : "($date as xs:anyAtomicType?) as xs:date?", "description" : " The last day of the month of a date\n", "summary" : "

    The last day of the month of a date\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " } ], "returns" : { "type" : "xs:date?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "last-node", "qname" : "functx:last-node", "signature" : "($nodes as node()*) as node()?", "description" : " The XML node in a sequence that is last in document order\n", "summary" : "

    The XML node in a sequence that is last in document order\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the sequence of nodes
    " } ], "returns" : { "type" : "node()?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "leaf-elements", "qname" : "functx:leaf-elements", "signature" : "($root as node()?) as element(*)*", "description" : " All XML elements that don't have any child elements\n", "summary" : "

    All XML elements that don't have any child elements\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "root", "type" : "node()", "occurrence" : "?", "description" : "
    the root
    " } ], "returns" : { "type" : "element(*)*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "left-trim", "qname" : "functx:left-trim", "signature" : "($arg as xs:string?) as xs:string", "description" : " Trims leading whitespace\n", "summary" : "

    Trims leading whitespace\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to trim
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "line-count", "qname" : "functx:line-count", "signature" : "($arg as xs:string?) as xs:integer", "description" : " The number of lines\n", "summary" : "

    The number of lines\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to test
    " } ], "returns" : { "type" : "xs:integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "lines", "qname" : "functx:lines", "signature" : "($arg as xs:string?) as xs:string*", "description" : " Split a string into separate lines\n", "summary" : "

    Split a string into separate lines\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to split
    " } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "max-depth", "qname" : "functx:max-depth", "signature" : "($root as node()?) as xs:integer?", "description" : " The maximum depth of elements in an XML tree\n", "summary" : "

    The maximum depth of elements in an XML tree\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "root", "type" : "node()", "occurrence" : "?", "description" : "
    the root to start from
    " } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "max-determine-type", "qname" : "functx:max-determine-type", "signature" : "($seq as xs:anyAtomicType*) as xs:anyAtomicType?", "description" : " The maximum value in a sequence, figuring out its type (numeric or string)\n", "summary" : "

    The maximum value in a sequence, figuring out its type (numeric or string)\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of values to test
    " } ], "returns" : { "type" : "xs:anyAtomicType?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "max-line-length", "qname" : "functx:max-line-length", "signature" : "($arg as xs:string?) as xs:integer", "description" : " The maximum line length\n", "summary" : "

    The maximum line length\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to test
    " } ], "returns" : { "type" : "xs:integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "max-node", "qname" : "functx:max-node", "signature" : "($nodes as node()*) as node()*", "description" : " The XML node whose typed value is the maximum\n", "summary" : "

    The XML node whose typed value is the maximum\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the sequence of nodes to test
    " } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "max-string", "qname" : "functx:max-string", "signature" : "($strings as xs:anyAtomicType*) as xs:string?", "description" : " The maximum of a sequence of values, treating them like strings\n", "summary" : "

    The maximum of a sequence of values, treating them like strings\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "strings", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of values
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "min-determine-type", "qname" : "functx:min-determine-type", "signature" : "($seq as xs:anyAtomicType*) as xs:anyAtomicType?", "description" : " The minimum value in a sequence, figuring out its type (numeric or string)\n", "summary" : "

    The minimum value in a sequence, figuring out its type (numeric or string)\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of values to test
    " } ], "returns" : { "type" : "xs:anyAtomicType?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "min-node", "qname" : "functx:min-node", "signature" : "($nodes as node()*) as node()*", "description" : " The XML node whose typed value is the minimum\n", "summary" : "

    The XML node whose typed value is the minimum\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the sequence of nodes to test
    " } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "min-non-empty-string", "qname" : "functx:min-non-empty-string", "signature" : "($strings as xs:string*) as xs:string?", "description" : " The minimum of a sequence of strings, ignoring \"empty\" values\n", "summary" : "

    The minimum of a sequence of strings, ignoring \"empty\" values\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "strings", "type" : "xs:string", "occurrence" : "*", "description" : "
    the sequence of strings to search
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "min-string", "qname" : "functx:min-string", "signature" : "($strings as xs:anyAtomicType*) as xs:string?", "description" : " The minimum of a sequence of values, treating them like strings\n", "summary" : "

    The minimum of a sequence of values, treating them like strings\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "strings", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of strings
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "mmddyyyy-to-date", "qname" : "functx:mmddyyyy-to-date", "signature" : "($dateString as xs:string?) as xs:date?", "description" : " Converts a string with format MMDDYYYY (with any delimiters) to a date\n", "summary" : "

    Converts a string with format MMDDYYYY (with any delimiters) to a date\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "dateString", "type" : "xs:string", "occurrence" : "?", "description" : "
    the MMDDYYYY string
    " } ], "returns" : { "type" : "xs:date?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "month-abbrev-en", "qname" : "functx:month-abbrev-en", "signature" : "($date as xs:anyAtomicType?) as xs:string?", "description" : " The month of a date as an abbreviated word (Jan, Feb, etc.)\n", "summary" : "

    The month of a date as an abbreviated word (Jan, Feb, etc.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "month-name-en", "qname" : "functx:month-name-en", "signature" : "($date as xs:anyAtomicType?) as xs:string?", "description" : " The month of a date as a word (January, February, etc.)\n", "summary" : "

    The month of a date as a word (January, February, etc.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "name-test", "qname" : "functx:name-test", "signature" : "($testname as xs:string?, $names as xs:string*) as xs:boolean", "description" : " Whether a name matches a list of names or name wildcards\n", "summary" : "

    Whether a name matches a list of names or name wildcards\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "testname", "type" : "xs:string", "occurrence" : "?", "description" : "
    the name to test
    " }, { "name" : "names", "type" : "xs:string", "occurrence" : "*", "description" : "
    the list of names or name wildcards
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "namespaces-in-use", "qname" : "functx:namespaces-in-use", "signature" : "($root as node()?) as xs:anyURI*", "description" : " A list of namespaces used in element/attribute names in an XML fragment\n", "summary" : "

    A list of namespaces used in element/attribute names in an XML fragment\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "root", "type" : "node()", "occurrence" : "?", "description" : "
    the root node to start from
    " } ], "returns" : { "type" : "xs:anyURI*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "next-day", "qname" : "functx:next-day", "signature" : "($date as xs:anyAtomicType?) as xs:date?", "description" : " The next day\n", "summary" : "

    The next day\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " } ], "returns" : { "type" : "xs:date?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "node-kind", "qname" : "functx:node-kind", "signature" : "($nodes as node()*) as xs:string*", "description" : " The XML node kind (element, attribute, text, etc.)\n", "summary" : "

    The XML node kind (element, attribute, text, etc.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the node(s) whose kind you want to determine
    " } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "non-distinct-values", "qname" : "functx:non-distinct-values", "signature" : "($seq as xs:anyAtomicType*) as xs:anyAtomicType*", "description" : " Returns any values that appear more than once in a sequence\n", "summary" : "

    Returns any values that appear more than once in a sequence\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the sequence of values
    " } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "number-of-matches", "qname" : "functx:number-of-matches", "signature" : "($arg as xs:string?, $pattern as xs:string) as xs:integer", "description" : " The number of regions that match a pattern\n", "summary" : "

    The number of regions that match a pattern\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to test
    " }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "
    the regular expression
    " } ], "returns" : { "type" : "xs:integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "ordinal-number-en", "qname" : "functx:ordinal-number-en", "signature" : "($num as xs:integer?) as xs:string", "description" : " Reformats a number as an ordinal number, e.g. 1st, 2nd, 3rd.\n", "summary" : "

    Reformats a number as an ordinal number, e.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "num", "type" : "xs:integer", "occurrence" : "?", "description" : "
    the number
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "pad-integer-to-length", "qname" : "functx:pad-integer-to-length", "signature" : "($integerToPad as xs:anyAtomicType?, $length as xs:integer) as xs:string", "description" : " Pads an integer to a desired length by adding leading zeros\n", "summary" : "

    Pads an integer to a desired length by adding leading zeros\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "integerToPad", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the integer to pad
    " }, { "name" : "length", "type" : "xs:integer", "occurrence" : null, "description" : "
    the desired length
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "pad-string-to-length", "qname" : "functx:pad-string-to-length", "signature" : "($stringToPad as xs:string?, $padChar as xs:string, $length as xs:integer) as xs:string", "description" : " Pads a string to a desired length\n", "summary" : "

    Pads a string to a desired length\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "stringToPad", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to pad
    " }, { "name" : "padChar", "type" : "xs:string", "occurrence" : null, "description" : "
    the character(s) to use as padding
    " }, { "name" : "length", "type" : "xs:integer", "occurrence" : null, "description" : "
    the desired length
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "path-to-node-with-pos", "qname" : "functx:path-to-node-with-pos", "signature" : "($node as node()?) as xs:string", "description" : " A unique path to an XML node (or sequence of nodes)\n", "summary" : "

    A unique path to an XML node (or sequence of nodes)\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : "?", "description" : "
    the node sequence
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "path-to-node", "qname" : "functx:path-to-node", "signature" : "($nodes as node()*) as xs:string*", "description" : " A path to an XML node (or sequence of nodes)\n", "summary" : "

    A path to an XML node (or sequence of nodes)\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the node sequence
    " } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "precedes-not-ancestor", "qname" : "functx:precedes-not-ancestor", "signature" : "($a as node()?, $b as node()?) as xs:boolean", "description" : " Whether an XML node precedes another without being its ancestor\n", "summary" : "

    Whether an XML node precedes another without being its ancestor\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "a", "type" : "node()", "occurrence" : "?", "description" : "
    the first node
    " }, { "name" : "b", "type" : "node()", "occurrence" : "?", "description" : "
    the second node
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "previous-day", "qname" : "functx:previous-day", "signature" : "($date as xs:anyAtomicType?) as xs:date?", "description" : " The previous day\n", "summary" : "

    The previous day\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "date", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "
    the date
    " } ], "returns" : { "type" : "xs:date?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "remove-attributes-deep", "qname" : "functx:remove-attributes-deep", "signature" : "($nodes as node()*, $names as xs:string*) as node()*", "description" : " Removes attributes from an XML fragment, based on name\n", "summary" : "

    Removes attributes from an XML fragment, based on name\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the root(s) to start from
    " }, { "name" : "names", "type" : "xs:string", "occurrence" : "*", "description" : "
    the names of the attributes to remove, or * for all attributes
    " } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "remove-attributes", "qname" : "functx:remove-attributes", "signature" : "($elements as element(*)*, $names as xs:string*) as element(*)", "description" : " Removes attributes from an XML element, based on name\n", "summary" : "

    Removes attributes from an XML element, based on name\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "elements", "type" : "element(*)", "occurrence" : "*", "description" : "
    the element(s) from which to remove the attributes
    " }, { "name" : "names", "type" : "xs:string", "occurrence" : "*", "description" : "
    the names of the attributes to remove, or * for all attributes
    " } ], "returns" : { "type" : "element(*)", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "remove-elements-deep", "qname" : "functx:remove-elements-deep", "signature" : "($nodes as node()*, $names as xs:string*) as node()*", "description" : " Removes descendant elements from an XML node, based on name\n", "summary" : "

    Removes descendant elements from an XML node, based on name\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    root(s) to start from
    " }, { "name" : "names", "type" : "xs:string", "occurrence" : "*", "description" : "
    the names of the elements to remove
    " } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "remove-elements-not-contents", "qname" : "functx:remove-elements-not-contents", "signature" : "($nodes as node()*, $names as xs:string*) as node()*", "description" : " Removes descendant XML elements but keeps their content\n", "summary" : "

    Removes descendant XML elements but keeps their content\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : "node()", "occurrence" : "*", "description" : "
    the root(s) to start from
    " }, { "name" : "names", "type" : "xs:string", "occurrence" : "*", "description" : "
    the names of the elements to remove
    " } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "remove-elements", "qname" : "functx:remove-elements", "signature" : "($elements as element(*)*, $names as xs:string*) as element(*)*", "description" : " Removes child elements from an XML node, based on name\n", "summary" : "

    Removes child elements from an XML node, based on name\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "elements", "type" : "element(*)", "occurrence" : "*", "description" : "
    the element(s) from which you wish to remove the children
    " }, { "name" : "names", "type" : "xs:string", "occurrence" : "*", "description" : "
    the names of the child elements to remove
    " } ], "returns" : { "type" : "element(*)*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "repeat-string", "qname" : "functx:repeat-string", "signature" : "($stringToRepeat as xs:string?, $count as xs:integer) as xs:string", "description" : " Repeats a string a given number of times\n", "summary" : "

    Repeats a string a given number of times\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "stringToRepeat", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to repeat
    " }, { "name" : "count", "type" : "xs:integer", "occurrence" : null, "description" : "
    the desired number of copies
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "replace-beginning", "qname" : "functx:replace-beginning", "signature" : "($arg as xs:string?, $pattern as xs:string, $replacement as xs:string) as xs:string", "description" : " Replaces the beginning of a string, up to a matched pattern\n", "summary" : "

    Replaces the beginning of a string, up to a matched pattern\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the entire string to change
    " }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "
    the pattern of characters to replace up to
    " }, { "name" : "replacement", "type" : "xs:string", "occurrence" : null, "description" : "
    the replacement string
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "replace-element-values", "qname" : "functx:replace-element-values", "signature" : "($elements as element(*)*, $values as xs:anyAtomicType*) as element(*)*", "description" : " Updates the content of one or more elements\n", "summary" : "

    Updates the content of one or more elements\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "elements", "type" : "element(*)", "occurrence" : "*", "description" : "
    the elements whose content you wish to replace
    " }, { "name" : "values", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the replacement values
    " } ], "returns" : { "type" : "element(*)*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "replace-first", "qname" : "functx:replace-first", "signature" : "($arg as xs:string?, $pattern as xs:string, $replacement as xs:string) as xs:string", "description" : " Replaces the first match of a pattern\n", "summary" : "

    Replaces the first match of a pattern\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the entire string to change
    " }, { "name" : "pattern", "type" : "xs:string", "occurrence" : null, "description" : "
    the pattern of characters to replace
    " }, { "name" : "replacement", "type" : "xs:string", "occurrence" : null, "description" : "
    the replacement string
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "replace-multi", "qname" : "functx:replace-multi", "signature" : "($arg as xs:string?, $changeFrom as xs:string*, $changeTo as xs:string*) as xs:string?", "description" : " Performs multiple replacements, using pairs of replace parameters\n", "summary" : "

    Performs multiple replacements, using pairs of replace parameters\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to manipulate
    " }, { "name" : "changeFrom", "type" : "xs:string", "occurrence" : "*", "description" : "
    the sequence of strings or patterns to change from
    " }, { "name" : "changeTo", "type" : "xs:string", "occurrence" : "*", "description" : "
    the sequence of strings to change to
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "reverse-string", "qname" : "functx:reverse-string", "signature" : "($arg as xs:string?) as xs:string", "description" : " Reverses the order of characters\n", "summary" : "

    Reverses the order of characters\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to reverse
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "right-trim", "qname" : "functx:right-trim", "signature" : "($arg as xs:string?) as xs:string", "description" : " Trims trailing whitespace\n", "summary" : "

    Trims trailing whitespace\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to trim
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "scheme-from-uri", "qname" : "functx:scheme-from-uri", "signature" : "($uri as xs:string?) as xs:string?", "description" : " Returns the scheme from a URI\n", "summary" : "

    Returns the scheme from a URI\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : "?", "description" : "
    the URI
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "sequence-deep-equal", "qname" : "functx:sequence-deep-equal", "signature" : "($seq1 as item()*, $seq2 as item()*) as xs:boolean", "description" : " Whether two sequences have the same XML node content and/or values\n", "summary" : "

    Whether two sequences have the same XML node content and/or values\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq1", "type" : "item()", "occurrence" : "*", "description" : "
    the first sequence
    " }, { "name" : "seq2", "type" : "item()", "occurrence" : "*", "description" : "
    the second sequence
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "sequence-node-equal-any-order", "qname" : "functx:sequence-node-equal-any-order", "signature" : "($seq1 as node()*, $seq2 as node()*) as xs:boolean", "description" : " Whether two sequences contain the same XML nodes, regardless of order\n", "summary" : "

    Whether two sequences contain the same XML nodes, regardless of order\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq1", "type" : "node()", "occurrence" : "*", "description" : "
    the first sequence of nodes
    " }, { "name" : "seq2", "type" : "node()", "occurrence" : "*", "description" : "
    the second sequence of nodes
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "sequence-node-equal", "qname" : "functx:sequence-node-equal", "signature" : "($seq1 as node()*, $seq2 as node()*) as xs:boolean", "description" : " Whether two sequences contain the same XML nodes, in the same order\n", "summary" : "

    Whether two sequences contain the same XML nodes, in the same order\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq1", "type" : "node()", "occurrence" : "*", "description" : "
    the first sequence of nodes
    " }, { "name" : "seq2", "type" : "node()", "occurrence" : "*", "description" : "
    the second sequence of nodes
    " } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sequence-type", "qname" : "functx:sequence-type", "signature" : "($items as item()*) as xs:string", "description" : " The sequence type that represents a sequence of nodes or values\n", "summary" : "

    The sequence type that represents a sequence of nodes or values\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    the items whose sequence type you want to determine
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "siblings-same-name", "qname" : "functx:siblings-same-name", "signature" : "($element as element(*)?) as element(*)*", "description" : " The siblings of an XML element that have the same name\n", "summary" : "

    The siblings of an XML element that have the same name\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "element", "type" : "element(*)", "occurrence" : "?", "description" : "
    the node
    " } ], "returns" : { "type" : "element(*)*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "siblings", "qname" : "functx:siblings", "signature" : "($node as node()?) as node()*", "description" : " The siblings of an XML node\n", "summary" : "

    The siblings of an XML node\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : "?", "description" : "
    the node
    " } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sort-as-numeric", "qname" : "functx:sort-as-numeric", "signature" : "($seq as item()*) as item()*", "description" : " Sorts a sequence of numeric values or nodes\n", "summary" : "

    Sorts a sequence of numeric values or nodes\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "item()", "occurrence" : "*", "description" : "
    the sequence to sort
    " } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sort-case-insensitive", "qname" : "functx:sort-case-insensitive", "signature" : "($seq as item()*) as item()*", "description" : " Sorts a sequence of values or nodes regardless of capitalization\n", "summary" : "

    Sorts a sequence of values or nodes regardless of capitalization\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "item()", "occurrence" : "*", "description" : "
    the sequence to sort
    " } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sort-document-order", "qname" : "functx:sort-document-order", "signature" : "($seq as node()*) as node()*", "description" : " Sorts a sequence of nodes in document order\n", "summary" : "

    Sorts a sequence of nodes in document order\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "node()", "occurrence" : "*", "description" : "
    the sequence to sort
    " } ], "returns" : { "type" : "node()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "sort", "qname" : "functx:sort", "signature" : "($seq as item()*) as item()*", "description" : " Sorts a sequence of values or nodes\n", "summary" : "

    Sorts a sequence of values or nodes\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "seq", "type" : "item()", "occurrence" : "*", "description" : "
    the sequence to sort
    " } ], "returns" : { "type" : "item()*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "substring-after-if-contains", "qname" : "functx:substring-after-if-contains", "signature" : "($arg as xs:string?, $delim as xs:string) as xs:string?", "description" : " Performs substring-after, returning the entire string if it does not contain the delimiter\n", "summary" : "

    Performs substring-after, returning the entire string if it does not contain the delimiter\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to substring
    " }, { "name" : "delim", "type" : "xs:string", "occurrence" : null, "description" : "
    the delimiter
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "substring-after-last-match", "qname" : "functx:substring-after-last-match", "signature" : "($arg as xs:string?, $regex as xs:string) as xs:string", "description" : " The substring after the last text that matches a regex\n", "summary" : "

    The substring after the last text that matches a regex\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to substring
    " }, { "name" : "regex", "type" : "xs:string", "occurrence" : null, "description" : "
    the regular expression
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "substring-after-last", "qname" : "functx:substring-after-last", "signature" : "($arg as xs:string?, $delim as xs:string) as xs:string", "description" : " The substring after the last occurrence of a delimiter\n", "summary" : "

    The substring after the last occurrence of a delimiter\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to substring
    " }, { "name" : "delim", "type" : "xs:string", "occurrence" : null, "description" : "
    the delimiter
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "substring-after-match", "qname" : "functx:substring-after-match", "signature" : "($arg as xs:string?, $regex as xs:string) as xs:string?", "description" : " The substring after the first text that matches a regex\n", "summary" : "

    The substring after the first text that matches a regex\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to substring
    " }, { "name" : "regex", "type" : "xs:string", "occurrence" : null, "description" : "
    the regular expression
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "substring-before-if-contains", "qname" : "functx:substring-before-if-contains", "signature" : "($arg as xs:string?, $delim as xs:string) as xs:string?", "description" : " Performs substring-before, returning the entire string if it does not contain the delimiter\n", "summary" : "

    Performs substring-before, returning the entire string if it does not contain the delimiter\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to substring
    " }, { "name" : "delim", "type" : "xs:string", "occurrence" : null, "description" : "
    the delimiter
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "substring-before-last-match", "qname" : "functx:substring-before-last-match", "signature" : "($arg as xs:string?, $regex as xs:string) as xs:string?", "description" : " The substring after the first text that matches a regex\n", "summary" : "

    The substring after the first text that matches a regex\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to substring
    " }, { "name" : "regex", "type" : "xs:string", "occurrence" : null, "description" : "
    the regular expression
    " } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "substring-before-last", "qname" : "functx:substring-before-last", "signature" : "($arg as xs:string?, $delim as xs:string) as xs:string", "description" : " The substring before the last occurrence of a delimiter\n", "summary" : "

    The substring before the last occurrence of a delimiter\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to substring
    " }, { "name" : "delim", "type" : "xs:string", "occurrence" : null, "description" : "
    the delimiter
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "substring-before-match", "qname" : "functx:substring-before-match", "signature" : "($arg as xs:string?, $regex as xs:string) as xs:string", "description" : " The substring before the last text that matches a regex\n", "summary" : "

    The substring before the last text that matches a regex\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to substring
    " }, { "name" : "regex", "type" : "xs:string", "occurrence" : null, "description" : "
    the regular expression
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "time", "qname" : "functx:time", "signature" : "($hour as xs:anyAtomicType, $minute as xs:anyAtomicType, $second as xs:anyAtomicType) as xs:time", "description" : " Construct a time from an hour, minute and second\n", "summary" : "

    Construct a time from an hour, minute and second\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "hour", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the hour
    " }, { "name" : "minute", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the minute
    " }, { "name" : "second", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    the second
    " } ], "returns" : { "type" : "xs:time", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "timezone-from-duration", "qname" : "functx:timezone-from-duration", "signature" : "($duration as xs:dayTimeDuration) as xs:string", "description" : " Converts an xs:dayTimeDuration into a timezone like \"-05:00\" or \"Z\"\n", "summary" : "

    Converts an xs:dayTimeDuration into a timezone like \"-05:00\" or \"Z\"\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "duration", "type" : "xs:dayTimeDuration", "occurrence" : null, "description" : "
    the duration
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "total-days-from-duration", "qname" : "functx:total-days-from-duration", "signature" : "($duration as xs:dayTimeDuration?) as xs:decimal?", "description" : " The total number of days in a dayTimeDuration\n", "summary" : "

    The total number of days in a dayTimeDuration\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "duration", "type" : "xs:dayTimeDuration", "occurrence" : "?", "description" : "
    the duration
    " } ], "returns" : { "type" : "xs:decimal?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "total-hours-from-duration", "qname" : "functx:total-hours-from-duration", "signature" : "($duration as xs:dayTimeDuration?) as xs:decimal?", "description" : " The total number of hours in a dayTimeDuration\n", "summary" : "

    The total number of hours in a dayTimeDuration\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "duration", "type" : "xs:dayTimeDuration", "occurrence" : "?", "description" : "
    the duration
    " } ], "returns" : { "type" : "xs:decimal?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "total-minutes-from-duration", "qname" : "functx:total-minutes-from-duration", "signature" : "($duration as xs:dayTimeDuration?) as xs:decimal?", "description" : " The total number of minutes in a dayTimeDuration\n", "summary" : "

    The total number of minutes in a dayTimeDuration\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "duration", "type" : "xs:dayTimeDuration", "occurrence" : "?", "description" : "
    the duration
    " } ], "returns" : { "type" : "xs:decimal?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "total-months-from-duration", "qname" : "functx:total-months-from-duration", "signature" : "($duration as xs:yearMonthDuration?) as xs:decimal?", "description" : " The total number of months in a yearMonthDuration\n", "summary" : "

    The total number of months in a yearMonthDuration\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "duration", "type" : "xs:yearMonthDuration", "occurrence" : "?", "description" : "
    the duration
    " } ], "returns" : { "type" : "xs:decimal?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "total-seconds-from-duration", "qname" : "functx:total-seconds-from-duration", "signature" : "($duration as xs:dayTimeDuration?) as xs:decimal?", "description" : " The total number of seconds in a dayTimeDuration\n", "summary" : "

    The total number of seconds in a dayTimeDuration\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "duration", "type" : "xs:dayTimeDuration", "occurrence" : "?", "description" : "
    the duration
    " } ], "returns" : { "type" : "xs:decimal?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "total-years-from-duration", "qname" : "functx:total-years-from-duration", "signature" : "($duration as xs:yearMonthDuration?) as xs:decimal?", "description" : " The total number of years in a yearMonthDuration\n", "summary" : "

    The total number of years in a yearMonthDuration\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "duration", "type" : "xs:yearMonthDuration", "occurrence" : "?", "description" : "
    the duration
    " } ], "returns" : { "type" : "xs:decimal?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "trim", "qname" : "functx:trim", "signature" : "($arg as xs:string?) as xs:string", "description" : " Trims leading and trailing whitespace\n", "summary" : "

    Trims leading and trailing whitespace\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to trim
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "update-attributes", "qname" : "functx:update-attributes", "signature" : "($elements as element(*)*, $attrNames as xs:QName*, $attrValues as xs:anyAtomicType*) as element(*)?", "description" : " Updates the attribute value of an XML element\n", "summary" : "

    Updates the attribute value of an XML element\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "elements", "type" : "element(*)", "occurrence" : "*", "description" : "
    the element(s) for which you wish to update the attribute
    " }, { "name" : "attrNames", "type" : "xs:QName", "occurrence" : "*", "description" : "
    the name(s) of the attribute(s) to add
    " }, { "name" : "attrValues", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the value(s) of the attribute(s) to add
    " } ], "returns" : { "type" : "element(*)?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "value-except", "qname" : "functx:value-except", "signature" : "($arg1 as xs:anyAtomicType*, $arg2 as xs:anyAtomicType*) as xs:anyAtomicType*", "description" : " The values in one sequence that aren't in another sequence\n", "summary" : "

    The values in one sequence that aren't in another sequence\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the first sequence
    " }, { "name" : "arg2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the second sequence
    " } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "value-intersect", "qname" : "functx:value-intersect", "signature" : "($arg1 as xs:anyAtomicType*, $arg2 as xs:anyAtomicType*) as xs:anyAtomicType*", "description" : " The intersection of two sequences of values\n", "summary" : "

    The intersection of two sequences of values\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the first sequence
    " }, { "name" : "arg2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the second sequence
    " } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "value-union", "qname" : "functx:value-union", "signature" : "($arg1 as xs:anyAtomicType*, $arg2 as xs:anyAtomicType*) as xs:anyAtomicType*", "description" : " The union of two sequences of values\n", "summary" : "

    The union of two sequences of values\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg1", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the first sequence
    " }, { "name" : "arg2", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the second sequence
    " } ], "returns" : { "type" : "xs:anyAtomicType*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "word-count", "qname" : "functx:word-count", "signature" : "($arg as xs:string?) as xs:integer", "description" : " The number of words\n", "summary" : "

    The number of words\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to measure
    " } ], "returns" : { "type" : "xs:integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "words-to-camel-case", "qname" : "functx:words-to-camel-case", "signature" : "($arg as xs:string?) as xs:string", "description" : " Turns a string of words into camelCase\n", "summary" : "

    Turns a string of words into camelCase\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "xs:string", "occurrence" : "?", "description" : "
    the string to modify
    " } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "wrap-values-in-elements", "qname" : "functx:wrap-values-in-elements", "signature" : "($values as xs:anyAtomicType*, $elementName as xs:QName) as element(*)*", "description" : " Wraps a sequence of atomic values in XML elements\n", "summary" : "

    Wraps a sequence of atomic values in XML elements\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "values", "type" : "xs:anyAtomicType", "occurrence" : "*", "description" : "
    the values to wrap in elements
    " }, { "name" : "elementName", "type" : "xs:QName", "occurrence" : null, "description" : "
    the name of the elements to construct
    " } ], "returns" : { "type" : "element(*)*", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "yearMonthDuration", "qname" : "functx:yearMonthDuration", "signature" : "($years as xs:decimal?, $months as xs:integer?) as xs:yearMonthDuration", "description" : " Construct a yearMonthDuration from a number of years and months\n", "summary" : "

    Construct a yearMonthDuration from a number of years and months\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "years", "type" : "xs:decimal", "occurrence" : "?", "description" : "
    the number of years
    " }, { "name" : "months", "type" : "xs:integer", "occurrence" : "?", "description" : "
    the number of months
    " } ], "returns" : { "type" : "xs:yearMonthDuration", "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/zorba-query" : { "ns" : "http://zorba.io/modules/zorba-query", "description" : " This module contains functions to compile and evaluate queries\n written in either JSONiq or XQuery. Also, it contains function that\n allow to parameterize the static or dynamic evaluation phase.\n", "sees" : [ ], "authors" : [ "Juan Zacarias" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://zorba.io/features", "prefix" : "f" }, { "uri" : "http://zorba.io/options/features", "prefix" : "op" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/modules/zorba-query", "prefix" : "zq" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "bind-context-item", "qname" : "zq:bind-context-item", "signature" : "($query-key as xs:anyURI, $dot as item()) as empty-sequence() external", "description" : "

    This function binds the context-item of the prepared query\n identified by the given key to the $dot argument.

    \n", "summary" : "

    This function binds the context-item of the prepared query\n identified by the given key to the $dot argument.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "query-key", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the identifier for a compiled query
    " }, { "name" : "dot", "type" : "item()", "occurrence" : null, "description" : "
    the context item to bind
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function has side effects and returns the empty sequence." }, "errors" : [ "zq:NO_QUERY_MATCH if no query with the given identifier was prepared." ] }, { "isDocumented" : true, "arity" : 3, "name" : "bind-variable", "qname" : "zq:bind-variable", "signature" : "($query-key as xs:anyURI, $var as xs:QName, $value as item()*) as empty-sequence() external", "description" : "

    This function binds the variable with name $name of\n the prepared query identified by $query-key to the given sequence.

    \n", "summary" : "

    This function binds the variable with name $name of\n the prepared query identified by $query-key to the given sequence.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "query-key", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the identifier for a compiled query
    " }, { "name" : "var", "type" : "xs:QName", "occurrence" : null, "description" : "" }, { "name" : "value", "type" : "item()", "occurrence" : "*", "description" : "
    the sequence to which the external variable $name should be bound
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function has side effects and returns the empty sequence." }, "errors" : [ "zq:NO_QUERY_MATCH if no query with the given identifier was prepared.", "zq:UNDECLARED_VARIABLE if the given variable is not declared in the query." ] }, { "isDocumented" : true, "arity" : 1, "name" : "delete-query", "qname" : "zq:delete-query", "signature" : "($query-key as xs:anyURI) as empty-sequence() external", "description" : "

    Deletes the prepared query associated with the given identifier.

    \n

    After the query is deleted, the corresponding identifier should\n not be used as argument to any of the functions of this module.

    \n", "summary" : "

    Deletes the prepared query associated with the given identifier.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "query-key", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the identifier for a compiled query
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function has side effects and returns the empty sequence." }, "errors" : [ "zq:NO_QUERY_MATCH if no query with the given identifier was prepared." ] }, { "isDocumented" : true, "arity" : 1, "name" : "evaluate-sequential", "qname" : "zq:evaluate-sequential", "signature" : "($query-key as xs:string) as item()* external", "description" : "

    Evaluates the given prepared query and returns the result\n of the evaluation. The query must be sequential.

    \n", "summary" : "

    Evaluates the given prepared query and returns the result\n of the evaluation.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "query-key", "type" : "xs:string", "occurrence" : null, "description" : "
    the identifier for a compiled query
    " } ], "returns" : { "type" : "item()*", "description" : "the result of evaluating the query." }, "errors" : [ "zq:NO_QUERY_MATCH if no query with the given identifier was prepared.", "zq:QUERY_NOT_SEQUENTIAL if the query is not sequential.", "zq:QUERY_IS_UPDATING if the query is an updating query.", "any dynamic error that is raised by evaluating the given query." ] }, { "isDocumented" : true, "arity" : 1, "name" : "evaluate-updating", "qname" : "zq:evaluate-updating", "signature" : "($query-key as xs:anyURI) external", "description" : "

    Evaluates the given prepared query and applies the updates\n computed by this query. The query must be an updating query.

    \n", "summary" : "

    Evaluates the given prepared query and applies the updates\n computed by this query.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "query-key", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the identifier for a compiled query
    " } ], "returns" : { "type" : null, "description" : "the function has side effects because it applies the updates of the query. It returns the empty sequence." }, "errors" : [ "zq:NO_QUERY_MATCH if no query with the given identifier was prepared.", "zq:QUERY_NOT_UPDATING if the query is not an updating query.", "zq:QUERY_IS_SEQUENTIAL if the query is sequential.", "any dynamic error that is raised by evaluating the given query or applying its updates." ] }, { "isDocumented" : true, "arity" : 1, "name" : "evaluate", "qname" : "zq:evaluate", "signature" : "($query-key as xs:anyURI) as item()* external", "description" : "

    Evaluates the given prepared query and returns the result\n of the evaluation. The query must not be sequential or\n updating.

    \n", "summary" : "

    Evaluates the given prepared query and returns the result\n of the evaluation.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query-key", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the identifier for a compiled query
    " } ], "returns" : { "type" : "item()*", "description" : "the result of evaluating the given query" }, "errors" : [ "zq:NO_QUERY_MATCH if no query with the given identifier was prepared.", "zq:QUERY_IS_UPDATING if the query is an updating query.", "zq:QUERY_IS_SEQUENTIAL if the query is sequential.", "any dynamic error that is raised by evaluating the given query." ] }, { "isDocumented" : true, "arity" : 1, "name" : "external-variables", "qname" : "zq:external-variables", "signature" : "($query-key as xs:anyURI) as xs:QName* external", "description" : "

    The function returns the names of the external variables that\n are declared in the given query (either in the main module or\n in any of the imported library modules).

    \n", "summary" : "

    The function returns the names of the external variables that\n are declared in the given query (either in the main module or\n in any of the imported library modules).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query-key", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the identifier for a compiled query
    " } ], "returns" : { "type" : "xs:QName*", "description" : "the sequence of names of the said external variables." }, "errors" : [ "zq:NO_QUERY_MATCH if no query with the given identifier was prepared." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-bound-context-item", "qname" : "zq:is-bound-context-item", "signature" : "($query-key as xs:anyURI) as xs:boolean external", "description" : "

    The function tests if the context-item is bound for the\n execution of the query referred to by the given query identifier.

    \n", "summary" : "

    The function tests if the context-item is bound for the\n execution of the query referred to by the given query identifier.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query-key", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the identifier for a compiled query
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the context-item is bound, false otherwise." }, "errors" : [ "zq:NO_QUERY_MATCH if no query with the given identifier was prepared." ] }, { "isDocumented" : true, "arity" : 2, "name" : "is-bound-variable", "qname" : "zq:is-bound-variable", "signature" : "($query-key as xs:anyURI, $var-name as xs:QName) as xs:boolean external", "description" : "

    The function tests if the given variable is bound for the\n execution of the query referred to by the given query identifier.

    \n", "summary" : "

    The function tests if the given variable is bound for the\n execution of the query referred to by the given query identifier.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query-key", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the identifier for a compiled query
    " }, { "name" : "var-name", "type" : "xs:QName", "occurrence" : null, "description" : "
    the name of the variable
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the variable is bound, false otherwise." }, "errors" : [ "zq:NO_QUERY_MATCH if no query with the given identifier was prepared.", "zq:UNDECLARED_VARIABLE if the given variable is not declared in the query." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-sequential", "qname" : "zq:is-sequential", "signature" : "($query-key as xs:anyURI) as xs:boolean external", "description" : "

    The function tests if the query identified by the given key\n is sequential query.

    \n", "summary" : "

    The function tests if the query identified by the given key\n is sequential query.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query-key", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the identifier for a compiled query
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the query is a sequential, false otherwise." }, "errors" : [ "zq:NO_QUERY_MATCH if no query with the given identifier was prepared." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-updating", "qname" : "zq:is-updating", "signature" : "($query-key as xs:anyURI) as xs:boolean external", "description" : "

    The function tests if the query identified by the given key\n is an updating query.

    \n", "summary" : "

    The function tests if the query identified by the given key\n is an updating query.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query-key", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the identifier for a compiled query
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the query is an updating query, false otherwise." }, "errors" : [ "zq:NO_QUERY_MATCH if no query with the given identifier was prepared." ] }, { "isDocumented" : true, "arity" : 1, "name" : "load-from-query-plan", "qname" : "zq:load-from-query-plan", "signature" : "($plan as xs:base64Binary) as xs:anyURI external", "description" : "

    The function loads a given query for execution from a\n xs:base64Binary query plan, obtained through the zq:query-plan function.

    \n

    If the query was successfully loaded, the function returns an\n identifier as xs:anyURI. This URI can be passed to other functions\n of this module (e.g. to actually evaluate the query). The URI\n is opaque and its lifetime is bound by the lifetime of the query\n that invoked this function. Further reference or uses\n of the identifier lead to unexpected results.

    \n

    \n

    Successfully prepared queries need to be deleted by passing the resulting\n identifier to the zq:delete-query function of this module.

    \n", "summary" : "

    The function loads a given query for execution from a\n xs:base64Binary query plan, obtained through the zq:query-plan function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "plan", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the binary query plan.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for the compiled query that can be passed as arguments to other functions of this module." }, "errors" : [ "any (static or type) error that may be raised during the compilation of the query. For example, err:XPST0003 if the given query could not be parsed." ] }, { "isDocumented" : true, "arity" : 3, "name" : "load-from-query-plan", "qname" : "zq:load-from-query-plan", "signature" : "($plan as xs:base64Binary, $resolver as item()?, $mapper as item()?) as xs:anyURI external", "description" : "

    The function loads a given query for execution from a\n xs:base64Binary query plan, obtained through the zq:query-plan function.

    \n

    If the query was successfully loaded, the function returns an\n identifier as xs:anyURI. This URI can be passed to other functions\n of this module (e.g. to actually evaluate the query). The URI\n is opaque and its lilfetime is bound by the lifetime of the query\n that invoked this function. Further reference or uses\n of the identifier lead to unexpected results.

    \n

    \n

    For important notes regarding the second and third parameters of the\n function, review the comments in zq:prepare-main-module#3.

    \n

    \n

    Successfully prepared queries need to be deleted by passing the resulting\n identifier to the zq:delete-query function of this module.

    \n", "summary" : "

    The function loads a given query for execution from a\n xs:base64Binary query plan, obtained through the zq:query-plan function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "plan", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the binary query plan.
    " }, { "name" : "resolver", "type" : "item()", "occurrence" : "?", "description" : "
    the URL resolver function.
    " }, { "name" : "mapper", "type" : "item()", "occurrence" : "?", "description" : "
    the URI mapper function.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for the compiled query that can be passed as arguments to other functions of this module." }, "errors" : [ "any (static or type) error that may be raised during the compilation of the query. For example, err:XPST0003 if the given query could not be parsed." ] }, { "isDocumented" : true, "arity" : 1, "name" : "prepare-library-module", "qname" : "zq:prepare-library-module", "signature" : "($library-module-text as xs:string) as empty-sequence() external", "description" : "

    This function compiles a given XQuery or JSONiq library module.\n It can be used to compile-check a module.

    \n", "summary" : "

    This function compiles a given XQuery or JSONiq library module.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "library-module-text", "type" : "xs:string", "occurrence" : null, "description" : "
    the library module that should be prepared.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty-sequence." }, "errors" : [ "any (static or type) error that may be raised during the compilation of the library module. For example, err:XPST0003 if the given library module could not be parsed." ] }, { "isDocumented" : true, "arity" : 1, "name" : "prepare-main-module", "qname" : "zq:prepare-main-module", "signature" : "($main-module-text as xs:string) as xs:anyURI external", "description" : "

    The function prepares a given a query for execution.

    \n

    If the query was successfully compiled, the function returns an\n identifier as xs:anyURI. This URI can be passed to other functions\n of this module (e.g. to actually evaluate the query). The URI\n is opaque and its lifetime is bound by the lifetime of the query\n that invoked this function. Further reference or uses\n of the identifier lead to unexpected results.

    \n

    \n

    Successfully prepared queries need to be deleted by passing the resulting\n identifier to the zq:delete-query function of this module.

    \n", "summary" : "

    The function prepares a given a query for execution.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "main-module-text", "type" : "xs:string", "occurrence" : null, "description" : "
    the query that should be prepared. The query needs to be a XQuery or JSONiq main module.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for the compiled query that can be passed as arguments to other functions of this module." }, "errors" : [ "any (static or type) error that may be raised during the compilation of the query. For example, err:XPST0003 if the given query could not be parsed." ] }, { "isDocumented" : true, "arity" : 3, "name" : "prepare-main-module", "qname" : "zq:prepare-main-module", "signature" : "($main-module-text as xs:string, $resolver as function (xs:string, xs:string) as item()??, $mapper as function (xs:string, xs:string) as xs:string*?) as xs:anyURI external", "description" : "

    The function prepares a given query for execution.

    \n

    If the query was successfully compiled, the function returns an\n identifier as xs:anyURI. This URI can be passed to other functions\n of this module (e.g. to actually evaluate the query). The URI\n is opaque and its lifetime is bound by the lifetime of the query\n that invoked this function. Further reference or uses\n of the identifier lead to unexpected results.

    \n

    \n

    Important notes regarding the second and third parameters of the function:

    \n

    --------------------------------------------------------------------------

    \n

    \n

    These parameters allow you to specify a URL resolver and a URI mapper\n for Zorba to use when executing this query. See\n here

    \n

    \n

      The second parameter is a function item for a URL\n resolver. The URL resolver function must recive 2 parameters:\n
    • A $namespace as xs:string that will contain the url to be resolved.
    • \n
    • A $entity as xs:string that will contain the type of resolving needed.\n This can be one of two values: \"module\" or \"schema\".
    • \n
    \n

    The function must return the empty sequence when the specified $namespace\n or $entity are not the ones to be resolved.

    \n

    \n

    Example:

    \n

    \n

    declare function mymod:url-resolver($namespace as xs:string, $entity as xs:string) as item()?\n {\n  if($namespace = 'http://test.xq')\n  then \"module namespace test = 'http://test'; declare function test:foo(){'foo'};\"\n  else ()\n };
    \n

    \n

    The URL resolver function's namespace, name, and parameter naming are\n not restricted by ZQ.

    \n

    \n

    The URL resolver function's return type is not restricted, it could be a string, a sequence,\n a node, etc. All the outputs types are to be serialized as a string.

    \n

    \n

    The third parameter is a function item for a URI mapper.

    \n
      The URI mapper function, just like the URL resolver, receives 2 parameters:\n
    • A $namespace as xs:string that will contain the URI to be mapped.
    • \n
    • A $entity as xs:string that will contain the type of resolving needed.\n This can be one of two values: \"module\" or \"schema\".
    • \n
    \n

    The URI mapper must return an empty sequence when the specified $namesapce or $entity\n are not to be mapped. Unlike the URL resolver this function must return a sequence of strings.

    \n

    \n

    Example:

    \n

    \n

    declare function mymod:uri-mapper($namespace as xs:string, $entity as xs:string)\n {\n  if($namespace = 'http://test')\n  then (\"http://zorba.io/test\", \"http://foo.com/schema/test\")\n  else ()\n };
    \n

    \n

    The URI mapper function's namespace, name, and parameter naming are\n not restricted by ZQ.

    \n

    \n

    In order to pass the above URL resolver and URI mapper to this function,\n use the following syntax:

    \n

    \n

    variable $queryID := zq:prepare-main-module(\"..query text..\",\n      mymod:url-resolver#2, mymod:uri-mapper#2);
    \n

    \n

    That is, the QName of the function followed by \"#2\". This is XQuery\n \"higher-order function\" syntax, meaning the function with the specified\n QName which takes two arguments. Since URL resolvers and URI mappers\n must take two arguments, both will always be specified with \"#2\".

    \n

    \n

    Both the URL resolver and URI mapper functions are optional, meaning you\n may pass the empty-sequence () for either.

    \n

    \n

    Successfully prepared queries need to be deleted by passing the resulting\n identifier to the zq:delete-query function of this module.

    \n", "summary" : "

    The function prepares a given query for execution.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "main-module-text", "type" : "xs:string", "occurrence" : null, "description" : "
    the query that should be prepared. The query needs to be a XQuery or JSONiq main module.
    " }, { "name" : "resolver", "type" : "function (xs:string, xs:string) as item()?", "occurrence" : "?", "description" : "
    the URL resolver function.
    " }, { "name" : "mapper", "type" : "function (xs:string, xs:string) as xs:string*", "occurrence" : "?", "description" : "
    the URI mapper function.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "an identifier for the compiled query that can be passed as arguments to other functions of this module." }, "errors" : [ "any (static or type) error that may be raised during the compilation of the query. For example, err:XPST0003 if the given query could not be parsed." ] }, { "isDocumented" : true, "arity" : 1, "name" : "query-plan", "qname" : "zq:query-plan", "signature" : "($query-key as xs:anyURI) as xs:base64Binary external", "description" : "

    Returns the compiled query identified by the given query-key\n as binary data.

    \n", "summary" : "

    Returns the compiled query identified by the given query-key\n as binary data.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query-key", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the identifier of a compiled query.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the query as xs:base64Binary." }, "errors" : [ "zq:NO_QUERY_MATCH if no query with the given identifier was prepared.", "zq:NO_QUERY_PLAN if there is an error serializing the query." ] }, { "isDocumented" : true, "arity" : 2, "name" : "variable-value", "qname" : "zq:variable-value", "signature" : "($query-key as xs:anyURI, $var-name as xs:QName) as item()* external", "description" : "

    This function returns the value of a variable that is bound in the\n given query.

    \n", "summary" : "

    This function returns the value of a variable that is bound in the\n given query.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "query-key", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    the identifier of a compiled query.
    " }, { "name" : "var-name", "type" : "xs:QName", "occurrence" : null, "description" : "
    the name of the variable whose value should be returned.
    " } ], "returns" : { "type" : "item()*", "description" : "the value bound to the given variable." }, "errors" : [ "zq:NO_QUERY_MATCH if no query with the given identifier was prepared.", "zq:UNDECLARED_VARIABLE if the given variable is not declared in the query.", "zq:UNBOUND_VARIABLE if the given variable doesn't have a value." ] } ], "variables" : [ ] }, "http://xbrl.io/modules/bizql/hypercubes" : { "ns" : "http://xbrl.io/modules/bizql/hypercubes", "description" : "

    This module provides functionality for manipulating hypercubes.

    \n

    A hypercube provides a multi-dimensional structure to organize facts.

    \n

    The dimensions of a hypercube correspond to XBRL aspects (concepts, entities, periods,\n units, further XBRL dimensions). An XBRL hypercube only is made of XBRL dimensions, however\n including the other aspects as well is very useful in the context of NOLAP, so that xbrl.io\n does so.

    \n

    xbrl.io introduces the notion of default hypercube. A default hypercube is implicitly added\n to each component, and only contains the concept, entity, period and unit aspects.\n In other words, the default hypercube\n of a component contains all these facts that do not have any XBRL dimensions.

    \n

    With this module, you can retrieve all hypercubes contained in a component. You can\n retrieve all facts contained in a hypercube (default dimension values are processed automatically),\n either in raw form, or organized as a (2D) fact table. You can also populate a network (for example,\n a presentation network) with the facts contained in a hypercube.

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/archives", "prefix" : "archives" }, { "uri" : "http://xbrl.io/modules/bizql/concept-maps", "prefix" : "concept-maps" }, { "uri" : "http://xbrl.io/modules/bizql/entities", "prefix" : "entities" }, { "uri" : "http://xbrl.io/modules/bizql/facts", "prefix" : "facts" }, { "uri" : "http://xbrl.io/modules/bizql/hypercubes", "prefix" : "hypercubes" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "dimensionless-hypercube", "qname" : "hypercubes:dimensionless-hypercube", "signature" : "() as object()", "description" : "

    Returns an instantiation of a dimensionless Hypercube containing only the basic\n characteristics (xbrl:Concept, xbrl:Period, xbrl:Entity, and xbrl:Unit).\n For each of those included aspects the value space is not limited.

    \n", "summary" : "

    Returns an instantiation of a dimensionless Hypercube containing only the basic\n characteristics (xbrl:Concept, xbrl:Period, xbrl:Entity, and xbrl:Unit).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "dimensionless hypercube instantiation." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "dimensionless-hypercube", "qname" : "hypercubes:dimensionless-hypercube", "signature" : "($options as object()?) as object()", "description" : "

    Returns an instantiation of a dimensionless Hypercube containing only the basic\n characteristics (xbrl:Concept, xbrl:Period, xbrl:Entity, and xbrl:Unit).\n For each of those included aspects the value space is not limited.

    \n", "summary" : "

    Returns an instantiation of a dimensionless Hypercube containing only the basic\n characteristics (xbrl:Concept, xbrl:Period, xbrl:Entity, and xbrl:Unit).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    : additional options among which: - Concepts: an array of concept names to include in the hypercube. - Periods: an array of periods to include in the hypercube. - Entities: an array of EIDs to include in the hypercube. - Units: an array of units to include in the hypercube.
    " } ], "returns" : { "type" : "object()", "description" : "dimensionless hypercube instantiation." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "fact-table-for-hypercube", "qname" : "hypercubes:fact-table-for-hypercube", "signature" : "($hypercube as object(), $archives as item()*) as array()", "description" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied hypercube, and populates them with the default dimension values\n when missing.

    \n", "summary" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied hypercube, and populates them with the default dimension values\n when missing.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "hypercube", "type" : "object()", "occurrence" : null, "description" : "
    a hypercube.
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs or $hypercubes:ALL_ARCHIVES for no filtering.
    " } ], "returns" : { "type" : "array()", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "fact-table-for-hypercube", "qname" : "hypercubes:fact-table-for-hypercube", "signature" : "($hypercube as object(), $archives as item()*, $options as object()?) as array()", "description" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied hypercube, and populates them with the default dimension values\n when missing.

    \n", "summary" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied hypercube, and populates them with the default dimension values\n when missing.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "hypercube", "type" : "object()", "occurrence" : null, "description" : "
    a hypercube.
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "array()", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "facts-for-hypercube", "qname" : "hypercubes:facts-for-hypercube", "signature" : "($hypercube as object(), $archives as item()*) as item()*", "description" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied hypercube, and populates them with the default dimension values\n when missing.

    \n", "summary" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied hypercube, and populates them with the default dimension values\n when missing.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "hypercube", "type" : "object()", "occurrence" : null, "description" : "
    a hypercube.
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs or $hypercubes:ALL_ARCHIVES for no filtering.
    " } ], "returns" : { "type" : "item()*", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "facts-for-hypercube", "qname" : "hypercubes:facts-for-hypercube", "signature" : "($hypercube as object(), $archives as item()*, $options as object()?) as item()*", "description" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied hypercube, and populates them with the default dimension values\n when missing.

    \n", "summary" : "

    Retrieves all facts from the supplied archives, that are relevant to the\n supplied hypercube, and populates them with the default dimension values\n when missing.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "hypercube", "type" : "object()", "occurrence" : null, "description" : "
    a hypercube.
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs or $hypercubes:ALL_ARCHIVES for no filtering.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "item()*", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "hypercubes-for-components", "qname" : "hypercubes:hypercubes-for-components", "signature" : "($components as object()*) as object()*", "description" : "

    Retrieves all hypercubes in the supplied components.

    \n", "summary" : "

    Retrieves all hypercubes in the supplied components.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "components", "type" : "object()", "occurrence" : "*", "description" : "
    a sequence of components.
    " } ], "returns" : { "type" : "object()*", "description" : "all hypercubes." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "hypercubes-for-components", "qname" : "hypercubes:hypercubes-for-components", "signature" : "($components as object()*, $names as string*) as object()*", "description" : "

    Retrieves all hypercubes in the supplied components and\n with the given names.

    \n", "summary" : "

    Retrieves all hypercubes in the supplied components and\n with the given names.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "components", "type" : "object()", "occurrence" : "*", "description" : "
    a sequence of components.
    " }, { "name" : "names", "type" : "string", "occurrence" : "*", "description" : "
    a sequence of names.
    " } ], "returns" : { "type" : "object()*", "description" : "all hypercubes." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "populate-networks-with-facts", "qname" : "hypercubes:populate-networks-with-facts", "signature" : "($networks as object()*, $hypercube as object(), $archives as item()*) as object()*", "description" : "

    Populates a concept-tree network with all facts from the supplied archives,\n that are relevant to the\n supplied hypercube. Default dimension values are added to the facts\n when missing.

    \n", "summary" : "

    Populates a concept-tree network with all facts from the supplied archives,\n that are relevant to the\n supplied hypercube.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks", "type" : "object()", "occurrence" : "*", "description" : "
    networks.
    " }, { "name" : "hypercube", "type" : "object()", "occurrence" : null, "description" : "
    a hypercube.
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs or $hypercubes:ALL_ARCHIVES for no filtering.
    " } ], "returns" : { "type" : "object()*", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "populate-networks-with-facts", "qname" : "hypercubes:populate-networks-with-facts", "signature" : "($networks as object()*, $hypercube as object(), $archives as item()*, $options as object()?) as object()*", "description" : "

    Populates a concept-tree network with all facts from the supplied archives,\n that are relevant to the\n supplied hypercube. Default dimension values are added to the facts\n when missing.

    \n", "summary" : "

    Populates a concept-tree network with all facts from the supplied archives,\n that are relevant to the\n supplied hypercube.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "networks", "type" : "object()", "occurrence" : "*", "description" : "
    networks.
    " }, { "name" : "hypercube", "type" : "object()", "occurrence" : null, "description" : "
    a hypercube.
    " }, { "name" : "archives", "type" : "item()", "occurrence" : "*", "description" : "
    a sequence of archives or their AIDs.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "a sequence of facts with populated dimension values." }, "errors" : [ ] } ], "variables" : [ { "name" : "hypercubes:ALL_ARCHIVES", "type" : "boolean", "description" : " Joker for all archives.\n" } ] }, "http://www.zorba-xquery.com/modules/xqdoc/batch" : { "ns" : "http://www.zorba-xquery.com/modules/xqdoc/batch", "description" : " Process XQDoc batches.\n This module generates XQDoc HTML documentation from multiple\n XQuery modules.\n", "sees" : [ ], "authors" : [ "William Candillon wcandillon at gmail dot com" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.zorba-xquery.com/modules/xqdoc/batch", "prefix" : "batch" }, { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://expath.org/ns/file", "prefix" : "file" }, { "uri" : "http://www.functx.com", "prefix" : "functx" }, { "uri" : "http://www.w3.org/1999/xhtml", "prefix" : "h" }, { "uri" : "http://www.zorba-xquery.com/modules/xqdoc/html", "prefix" : "html" }, { "uri" : "http://www.zorba-xquery.com/modules/xqdoc/menu", "prefix" : "menu" }, { "uri" : "http://www.w3.org/2010/xslt-xquery-serialization", "prefix" : "out" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://www.xqdoc.org/1.0", "prefix" : "xq" }, { "uri" : "http://zorba.io/modules/xqdoc", "prefix" : "xqdoc" } ], "functions" : [ { "isDocumented" : false, "arity" : 2, "name" : "add-predeclared-namespaces", "qname" : "batch:add-predeclared-namespaces", "signature" : "($xqdoc as element(xq:xqdoc), $namespaces as element(namespace)*) as element(xq:xqdoc)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "xqdoc", "type" : "element(xq:xqdoc)", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : "element(namespace)", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "element(xq:xqdoc)", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "add-trailing-slash", "qname" : "batch:add-trailing-slash", "signature" : "($path as xs:string) as xs:string", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "path", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "build-xqdoc", "qname" : "batch:build-xqdoc", "signature" : "($output-folder as xs:string, $static-folders as xs:string*, $template as element(*), $modules as element(modules))", "description" : " Run an XQDoc batch.\n", "summary" : "

    Run an XQDoc batch.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "output-folder", "type" : "xs:string", "occurrence" : null, "description" : "
    Where to write the generated files.
    " }, { "name" : "static-folders", "type" : "xs:string", "occurrence" : "*", "description" : "
    Where to copy the static files from.
    " }, { "name" : "template", "type" : "element(*)", "occurrence" : null, "description" : "
    HTML layout of the generated files. The layount can contains different variables. For instance:
    is a valid example. Three variable names are available: page, title, and menu.
    " }, { "name" : "modules", "type" : "element(modules)", "occurrence" : null, "description" : "
    Document describing the documentation project. For instance:
       
    " } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "copy-static-folders", "qname" : "batch:copy-static-folders", "signature" : "($output-folder as xs:string, $static-folders as xs:string*)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "output-folder", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "static-folders", "type" : "xs:string", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "create-page", "qname" : "batch:create-page", "signature" : "($output-folder as xs:string, $page-name as xs:string, $page as element(h:html))", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "output-folder", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "page-name", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "page", "type" : "element(h:html)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "create-xml-folder", "qname" : "batch:create-xml-folder", "signature" : "($folder as xs:string)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "folder", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "page", "qname" : "batch:page", "signature" : "($template as element(*), $menu as element(ul), $section as element(*)) as element(h:html)", "description" : "", "summary" : "", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "template", "type" : "element(*)", "occurrence" : null, "description" : "" }, { "name" : "menu", "type" : "element(ul)", "occurrence" : null, "description" : "" }, { "name" : "section", "type" : "element(*)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "element(h:html)", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "save-xml", "qname" : "batch:save-xml", "signature" : "($output-file, $page)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "output-file", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "page", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "section", "qname" : "batch:section", "signature" : "($sections as element(section)+) as element(section)+", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "sections", "type" : "element(section)", "occurrence" : "+", "description" : "" } ], "returns" : { "type" : "element(section)+", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "section", "qname" : "batch:section", "signature" : "($sections as element(section)+, $level as xs:integer) as element(section)+", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "sections", "type" : "element(section)", "occurrence" : "+", "description" : "" }, { "name" : "level", "type" : "xs:integer", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "element(section)+", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "xqdoc", "qname" : "batch:xqdoc", "signature" : "($module as element(module)) as element(xq:xqdoc)", "description" : "", "summary" : "", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "module", "type" : "element(module)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "element(xq:xqdoc)", "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/data-cleaning/hybrid-string-similarity" : { "ns" : "http://zorba.io/modules/data-cleaning/hybrid-string-similarity", "description" : "

    This library module provides hybrid string similarity functions, combining the properties of\n character-based string similarity functions and token-based string similarity functions.

    \n

    \n

    The logic contained in this module is not specific to any particular XQuery implementation,\n although the module requires the trigonometic functions of XQuery 3.0 or a math extension\n function such as sqrt($x as numeric) for computing the square root.

    \n", "sees" : [ ], "authors" : [ "Bruno Martins and Diogo Simões" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xpath-functions/math", "prefix" : "math" }, { "uri" : "http://zorba.io/modules/data-cleaning/set-similarity", "prefix" : "set" }, { "uri" : "http://zorba.io/modules/data-cleaning/character-based-string-similarity", "prefix" : "simc" }, { "uri" : "http://zorba.io/modules/data-cleaning/hybrid-string-similarity", "prefix" : "simh" }, { "uri" : "http://zorba.io/modules/data-cleaning/phonetic-string-similarity", "prefix" : "simp" }, { "uri" : "http://zorba.io/modules/data-cleaning/token-based-string-similarity", "prefix" : "simt" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 4, "name" : "monge-elkan-jaro-winkler", "qname" : "simh:monge-elkan-jaro-winkler", "signature" : "($s1 as xs:string, $s2 as xs:string, $prefix as xs:integer, $fact as xs:double) as xs:double", "description" : "

    Returns the Monge-Elkan similarity coefficient between two strings, using the Jaro-Winkler

    \n

    similarity function to discover token identity.

    \n

    \n

    Example usage :

     monge-elkan-jaro-winkler(\"Comput. Sci. and Eng. Dept., University of California, San Diego\", \"Department of Computer Scinece, Univ. Calif., San Diego\", 4, 0.1) 

    \n

    \n

    The function invocation in the example above returns :

     0.992 

    \n", "summary" : "

    Returns the Monge-Elkan similarity coefficient between two strings, using the Jaro-Winkler \n similarity function to discover token identity.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "prefix", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of characters to consider when testing for equal prefixes with the Jaro-Winkler metric.
    " }, { "name" : "fact", "type" : "xs:double", "occurrence" : null, "description" : "
    The weighting factor to consider when the input strings have equal prefixes with the Jaro-Winkler metric.
    " } ], "returns" : { "type" : "xs:double", "description" : "The Monge-Elkan similarity coefficient between the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "soft-cosine-tokens-edit-distance", "qname" : "simh:soft-cosine-tokens-edit-distance", "signature" : "($s1 as xs:string, $s2 as xs:string, $r as xs:string, $t as xs:integer) as xs:double", "description" : "

    Returns the cosine similarity coefficient between sets of tokens extracted from two strings.

    \n

    The tokens from each string are weighted according to their occurence frequency (i.e., weighted according to the\n term-frequency heuristic from Information Retrieval).

    \n

    The Edit Distance similarity function is used to discover token identity, and tokens having an edit distance\n bellow a given threshold are considered as matching tokens.

    \n

    \n

    Example usage :

     soft-cosine-tokens-edit-distance(\"The FLWOR Foundation\", \"FLWOR Found.\", \" +\", 0 ) 

    \n

    \n

    The function invocation in the example above returns :

     0.408248290463863 

    \n", "summary" : "

    Returns the cosine similarity coefficient between sets of tokens extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "r", "type" : "xs:string", "occurrence" : null, "description" : "
    A regular expression forming the delimiter character(s) which mark the boundaries between adjacent tokens.
    " }, { "name" : "t", "type" : "xs:integer", "occurrence" : null, "description" : "
    A threshold for the similarity function used to discover token identity.
    " } ], "returns" : { "type" : "xs:double", "description" : "The cosine similarity coefficient between the sets tokens extracted from the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 6, "name" : "soft-cosine-tokens-jaro-winkler", "qname" : "simh:soft-cosine-tokens-jaro-winkler", "signature" : "($s1 as xs:string, $s2 as xs:string, $r as xs:string, $t as xs:double, $prefix as xs:integer?, $fact as xs:double?) as xs:double", "description" : "

    Returns the cosine similarity coefficient between sets of tokens extracted from two strings.

    \n

    The tokens from each string are weighted according to their occurence frequency (i.e., weighted according to the\n term-frequency heuristic from Information Retrieval).

    \n

    The Jaro-Winkler similarity function is used to discover token identity, and tokens having a Jaro-Winkler\n similarity above a given threshold are considered as matching tokens.

    \n

    \n

    Example usage :

     soft-cosine-tokens-jaro-winkler(\"The FLWOR Foundation\", \"FLWOR Found.\", \" +\", 1, 4, 0.1 ) 

    \n

    \n

    The function invocation in the example above returns :

     0.45 

    \n", "summary" : "

    Returns the cosine similarity coefficient between sets of tokens extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "r", "type" : "xs:string", "occurrence" : null, "description" : "
    A regular expression forming the delimiter character(s) which mark the boundaries between adjacent tokens.
    " }, { "name" : "t", "type" : "xs:double", "occurrence" : null, "description" : "
    A threshold for the similarity function used to discover token identity.
    " }, { "name" : "prefix", "type" : "xs:integer", "occurrence" : "?", "description" : "
    The number of characters to consider when testing for equal prefixes with the Jaro-Winkler metric.
    " }, { "name" : "fact", "type" : "xs:double", "occurrence" : "?", "description" : "
    The weighting factor to consider when the input strings have equal prefixes with the Jaro-Winkler metric.
    " } ], "returns" : { "type" : "xs:double", "description" : "The cosine similarity coefficient between the sets tokens extracted from the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "soft-cosine-tokens-jaro", "qname" : "simh:soft-cosine-tokens-jaro", "signature" : "($s1 as xs:string, $s2 as xs:string, $r as xs:string, $t as xs:double) as xs:double", "description" : "

    Returns the cosine similarity coefficient between sets of tokens extracted from two strings.

    \n

    The tokens from each string are weighted according to their occurence frequency (i.e., weighted according to the\n term-frequency heuristic from Information Retrieval).

    \n

    The Jaro similarity function is used to discover token identity, and tokens having a Jaro similarity above\n a given threshold are considered as matching tokens.

    \n

    \n

    Example usage :

     soft-cosine-tokens-jaro(\"The FLWOR Foundation\", \"FLWOR Found.\", \" +\", 1 ) 

    \n

    \n

    The function invocation in the example above returns :

     0.5 

    \n", "summary" : "

    Returns the cosine similarity coefficient between sets of tokens extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "r", "type" : "xs:string", "occurrence" : null, "description" : "
    A regular expression forming the delimiter character(s) which mark the boundaries between adjacent tokens.
    " }, { "name" : "t", "type" : "xs:double", "occurrence" : null, "description" : "
    A threshold for the similarity function used to discover token identity.
    " } ], "returns" : { "type" : "xs:double", "description" : "The cosine similarity coefficient between the sets tokens extracted from the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "soft-cosine-tokens-metaphone", "qname" : "simh:soft-cosine-tokens-metaphone", "signature" : "($s1 as xs:string, $s2 as xs:string, $r as xs:string) as xs:double", "description" : "

    Returns the cosine similarity coefficient between sets of tokens extracted from two strings.

    \n

    The tokens from each string are weighted according to their occurence frequency (i.e., weighted according to the\n term-frequency heuristic from Information Retrieval).

    \n

    The Metaphone phonetic similarity function is used to discover token identity, which is equivalent to saying that\n this function returns the cosine similarity coefficient between sets of Metaphone keys.

    \n

    \n

    Example usage :

     soft-cosine-tokens-metaphone(\"ALEKSANDER SMITH\", \"ALEXANDER SMYTH\", \" +\" ) 

    \n

    \n

    The function invocation in the example above returns :

     1.0 

    \n", "summary" : "

    Returns the cosine similarity coefficient between sets of tokens extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "r", "type" : "xs:string", "occurrence" : null, "description" : "
    A regular expression forming the delimiter character(s) which mark the boundaries between adjacent tokens.
    " } ], "returns" : { "type" : "xs:double", "description" : "The cosine similarity coefficient between the sets Metaphone keys extracted from the two strings." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "soft-cosine-tokens-soundex", "qname" : "simh:soft-cosine-tokens-soundex", "signature" : "($s1 as xs:string, $s2 as xs:string, $r as xs:string) as xs:double", "description" : "

    Returns the cosine similarity coefficient between sets of tokens extracted from two strings.

    \n

    \n

    The tokens from each string are weighted according to their occurence frequency (i.e., weighted according to the\n term-frequency heuristic from Information Retrieval).

    \n

    The Soundex phonetic similarity function is used to discover token identity, which is equivalent to saying that\n this function returns the cosine similarity coefficient between sets of Soundex keys.

    \n

    \n

    Example usage :

     soft-cosine-tokens-soundex(\"ALEKSANDER SMITH\", \"ALEXANDER SMYTH\", \" +\") 

    \n

    \n

    The function invocation in the example above returns :

     1.0 

    \n", "summary" : "

    Returns the cosine similarity coefficient between sets of tokens extracted from two strings.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : "xs:string", "occurrence" : null, "description" : "
    The first string.
    " }, { "name" : "s2", "type" : "xs:string", "occurrence" : null, "description" : "
    The second string.
    " }, { "name" : "r", "type" : "xs:string", "occurrence" : null, "description" : "
    A regular expression forming the delimiter character(s) which mark the boundaries between adjacent tokens.
    " } ], "returns" : { "type" : "xs:double", "description" : "The cosine similarity coefficient between the sets of Soundex keys extracted from the two strings." }, "errors" : [ ] } ], "variables" : [ ] }, "http://xbrl.io/modules/bizql/rules" : { "ns" : "http://xbrl.io/modules/bizql/rules", "description" : "

    This module provides functions for storing, retrieving, and modifying\n rules. Rules can be used in BizQL queries to:

    \n
      \n
    • Impute Facts that were not reported within an instance, yet can be\n derived from reported facts.
    • \n
    • Compute arbitrary new Facts (Ratios, Calculated Facts, Facts from different\n Datasources/Instances, etc.).
    • \n
    • Run validation and/or verification rules
    • \n
    \n

    A Rule is an object containing a BizQL fomula to execute if a condition is met.\n For example if a user queries for a certain concept and a rule exists for this\n concept then the rule is applied to get the fact.

    \n

    With this module, you can retrieve the rules associated with each report\n schema. You can also query for facts by making implicitly use of the mapping.

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://xbrl.io/modules/bizql/archives", "prefix" : "archives" }, { "uri" : "http://xbrl.io/modules/bizql/facts", "prefix" : "facts" }, { "uri" : "http://xbrl.io/modules/bizql/networks", "prefix" : "networks" }, { "uri" : "http://xbrl.io/modules/bizql/report-schemas", "prefix" : "report-schemas" }, { "uri" : "http://xbrl.io/modules/bizql/rules", "prefix" : "rules" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 7, "name" : "create-computed-fact", "qname" : "rules:create-computed-fact", "signature" : "($template-fact as object(), $concept-name-or-aspects as item(), $value as item(), $rule as object(), $audit-trail-message as string, $source-facts as object()*, $options as object()?) as object()", "description" : "

    Helper function to create a new fact within a rule.

    \n", "summary" : "

    Helper function to create a new fact within a rule.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "template-fact", "type" : "object()", "occurrence" : null, "description" : "
    a fact object that will be used as a template for the newly created fact
    " }, { "name" : "concept-name-or-aspects", "type" : "item()", "occurrence" : null, "description" : "
    either a name of the concept for the newly created fact or a complete aspects object to be used in the new fact.
    " }, { "name" : "value", "type" : "item()", "occurrence" : null, "description" : "
    a value for the newly created fact
    " }, { "name" : "rule", "type" : "object()", "occurrence" : null, "description" : "
    the rule in which this fact has been created
    " }, { "name" : "audit-trail-message", "type" : "string", "occurrence" : null, "description" : "
    a verbose string message explaining how and why this fact has been created
    " }, { "name" : "source-facts", "type" : "object()", "occurrence" : "*", "description" : "
    sequence of facts that have been used to compute the new fact (this will only be added to the AuditTrails if the audit-trail option is set to \"debug\")
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "object()", "description" : "the decimal value of the fact or 0." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "fact-trail", "qname" : "rules:fact-trail", "signature" : "($fact as object()?) as string", "description" : "

    Serializes a fact to a simple string format that can be used in\n audit trail messages to trail the value of the fact.

    \n

    The returned string follows the pattern: fact-concept-name[fact-value]

    \n", "summary" : "

    Serializes a fact to a simple string format that can be used in\n audit trail messages to trail the value of the fact.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "fact", "type" : "object()", "occurrence" : "?", "description" : "
    a single fact to serialize to a simple informative string
    " } ], "returns" : { "type" : "string", "description" : "the string with key information about the fact." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "fact-trail", "qname" : "rules:fact-trail", "signature" : "($fact as object()?, $name as string) as string", "description" : "

    Serializes a fact to a simple string format that can be used in\n audit trail messages to trail the value of the fact.

    \n

    The returned string follows the pattern: fact-concept-name[fact-value]

    \n", "summary" : "

    Serializes a fact to a simple string format that can be used in\n audit trail messages to trail the value of the fact.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "fact", "type" : "object()", "occurrence" : "?", "description" : "
    an empty-sequence or a single fact to serialize to a simple informative string
    " }, { "name" : "name", "type" : "string", "occurrence" : null, "description" : "
    an alternative name to use if the $fact is an empty-sequence otherwise the name will be taken from the fact
    " } ], "returns" : { "type" : "string", "description" : "the string with key information about the fact." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "rules", "qname" : "rules:rules", "signature" : "() as object()*", "description" : "

    Retrieves all rules from all report schemas.

    \n", "summary" : "

    Retrieves all rules from all report schemas.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()*", "description" : "all rules." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "rules", "qname" : "rules:rules", "signature" : "($report-schemas-or-ids as item()*) as object()*", "description" : "

    Return the rules from the given report schemas.

    \n", "summary" : "

    Return the rules from the given report schemas.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "report-schemas-or-ids", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "object()*", "description" : "the rules from the report schemas." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/lock" : { "ns" : "http://www.28msec.com/modules/lock", "description" : " Sausalito provides a an application level locking mechanism that can be\n used e.g. to ensure exclusive access to data.\n As the store ensures atomicity of of single document updates, atomic\n updates to multiple documents are implemented using this mechanism.\n Locks can be acquired and re-acquired at any time during a request and\n are released at the end of the request.\n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/lock", "prefix" : "lock" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "try-acquire", "qname" : "lock:try-acquire", "signature" : "($lock-name as xs:string) as xs:boolean external", "description" : " Tries to acquire a lock.\n This operation is non-blocking if the lock cannot be acquired immediately.\n To check and modify the stock of a product wihtout interference from\n concurrent requests a lock could be used like this:\n
    \n if (lock:try-acquire(\"stock-update\"))\n then\n   if (stock:check($product-id))\n   then\n     {\n       order:finalize($order-id);\n       stock:decrement($product-id);\n     }\n   else\n     order:hold($order-id);\n else\n   ...\n 
    \n", "summary" : "

    Tries to acquire a lock.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "lock-name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the lock.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the lock could be acquired, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "try-acquire", "qname" : "lock:try-acquire", "signature" : "($lock-name as xs:string, $reason as xs:string) as xs:boolean external", "description" : " tries to acquire a lock\n", "summary" : "

    tries to acquire a lock\n

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "lock-name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the lock.
    " }, { "name" : "reason", "type" : "xs:string", "occurrence" : null, "description" : "
    a reason for the acquisition of the lock that can be used for
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the lock could be acquired, false otherwise." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/xqdoc/html" : { "ns" : "http://www.zorba-xquery.com/modules/xqdoc/html", "description" : " Convert an XQDoc document into an HTML document.\n This module contains a single convert() function\n that transform an XQDoc document into an HTML document.\n Usage:\n
    \n let $xqdoc := xqdoc:xqdoc(\"http://expath.org/ns/file\")\n return html:convert($xqdoc)\n 
    \n", "sees" : [ ], "authors" : [ "William Candillon wcandillon at gmail dot com" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.zorba-xquery.com/modules/xqdoc/html", "prefix" : "html" }, { "uri" : "http://www.w3.org/2010/xslt-xquery-serialization", "prefix" : "o" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://www.xqdoc.org/1.0", "prefix" : "xq" } ], "functions" : [ { "isDocumented" : false, "arity" : 1, "name" : "convert", "qname" : "html:convert", "signature" : "($xqdoc as element(xq:xqdoc)) as element(div)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "xqdoc", "type" : "element(xq:xqdoc)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "element(div)", "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://api.28.io/model" : { "ns" : "http://api.28.io/model", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://zorba.io/modules/store/static/collections/ddl", "prefix" : "cddl" }, { "uri" : "http://zorba.io/modules/store/static/collections/dml", "prefix" : "cdml" }, { "uri" : "http://zorba.io/modules/store/static/indexes/ddl", "prefix" : "iddl" }, { "uri" : "http://zorba.io/modules/store/static/indexes/dml", "prefix" : "idml" }, { "uri" : "http://api.28.io/model", "prefix" : "model" }, { "uri" : "http://www.zorba-xquery.com/schemas/pul", "prefix" : "pul" }, { "uri" : "http://zorba.io/modules/reference", "prefix" : "ref" }, { "uri" : "http://www.zorba-xquery.com/schemas/xdm", "prefix" : "xdm" } ], "functions" : [ { "isDocumented" : false, "arity" : 1, "name" : "applyPUL", "qname" : "model:applyPUL", "signature" : "($pul as schema-element(pul:pending-update-list))", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "pul", "type" : "schema-element(pul:pending-update-list)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "applyPULOp", "qname" : "model:applyPULOp", "signature" : "($pul)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "pul", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "build-nodes", "qname" : "model:build-nodes", "signature" : "($definition)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "definition", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "collection-qname", "qname" : "model:collection-qname", "signature" : "($name as xs:string) as xs:QName", "description" : " Returns the QName for a collection. Returns the empty sequence if no collection with the given name exists.\n", "summary" : "

    Returns the QName for a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection as string
    " } ], "returns" : { "type" : "xs:QName", "description" : "the QName for the collection or the empty sequence" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "delete-node-collection", "qname" : "model:delete-node-collection", "signature" : "($collection as xs:QName, $noderef as xs:anyURI?)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "collection", "type" : "xs:QName", "occurrence" : null, "description" : "" }, { "name" : "noderef", "type" : "xs:anyURI", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "delete-node", "qname" : "model:delete-node", "signature" : "($noderef as xs:anyURI)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "noderef", "type" : "xs:anyURI", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "element-node", "qname" : "model:element-node", "signature" : "($definition as schema-element(xdm:element))", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "definition", "type" : "schema-element(xdm:element)", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "find-keys", "qname" : "model:find-keys", "signature" : "($collection)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "collection", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "get-collection-names", "qname" : "model:get-collection-names", "signature" : "() as xs:string*", "description" : " Returns all collection names\n", "summary" : "

    Returns all collection names\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string*", "description" : "collection names as a sequence of strings" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "get-collection-size", "qname" : "model:get-collection-size", "signature" : "($name as xs:string) as xs:integer", "description" : " Returns the size of a collection\n", "summary" : "

    Returns the size of a collection\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection as string
    " } ], "returns" : { "type" : "xs:integer", "description" : "the size of the collection" }, "errors" : [ "if the collection chosen by $name does not exist" ] }, { "isDocumented" : true, "arity" : 1, "name" : "get-collection", "qname" : "model:get-collection", "signature" : "($name as xs:string) as node()*", "description" : " Returns the whole collection with a given name\n", "summary" : "

    Returns the whole collection with a given name\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    name of collection to return
    " } ], "returns" : { "type" : "node()*", "description" : "sequence of nodes of the collection" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "get-collection", "qname" : "model:get-collection", "signature" : "($name as xs:string, $first-noderef as xs:anyURI?, $offset as xs:integer?, $limit as xs:integer)", "description" : " Returns \"a page\" of the collection (a part)\n", "summary" : "

    Returns \"a page\" of the collection (a part)\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the collection as string
    " }, { "name" : "first-noderef", "type" : "xs:anyURI", "occurrence" : "?", "description" : "" }, { "name" : "offset", "type" : "xs:integer", "occurrence" : "?", "description" : "" }, { "name" : "limit", "type" : "xs:integer", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "a sequence of nodes from the collection" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 4, "name" : "get-column-id", "qname" : "model:get-column-id", "signature" : "($basepath as xs:string?, $name as xs:string, $isattribute as xs:boolean, $columns) as xs:integer", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "basepath", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "isattribute", "type" : "xs:boolean", "occurrence" : null, "description" : "" }, { "name" : "columns", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:integer", "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "get-index-names", "qname" : "model:get-index-names", "signature" : "() as xs:string*", "description" : " Returns all index names\n", "summary" : "

    Returns all index names\n

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string*", "description" : "index names as a sequence of strings" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "get-index-point", "qname" : "model:get-index-point", "signature" : "($index-name as xs:string, $index-key)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "index-name", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "index-key", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "get-node-group", "qname" : "model:get-node-group", "signature" : "($noderef as xs:anyURI)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "noderef", "type" : "xs:anyURI", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "get-node-path", "qname" : "model:get-node-path", "signature" : "($node)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "get-node", "qname" : "model:get-node", "signature" : "($noderef as xs:anyURI)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "noderef", "type" : "xs:anyURI", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "index-qname", "qname" : "model:index-qname", "signature" : "($name as xs:string) as xs:QName", "description" : " Returns the QName for an index. Returns the empty sequence if no index with the given name exists.\n", "summary" : "

    Returns the QName for an index.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the index as string
    " } ], "returns" : { "type" : "xs:QName", "description" : "the QName for the index or the empty sequence" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "insert-attribute", "qname" : "model:insert-attribute", "signature" : "($noderef as xs:anyURI, $attribute as xs:string, $value)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "noderef", "type" : "xs:anyURI", "occurrence" : null, "description" : "" }, { "name" : "attribute", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "value", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 4, "name" : "insert-node-collection-ordered", "qname" : "model:insert-node-collection-ordered", "signature" : "($collection as xs:QName, $noderef as xs:anyURI?, $position as xs:string, $nodes)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "collection", "type" : "xs:QName", "occurrence" : null, "description" : "" }, { "name" : "noderef", "type" : "xs:anyURI", "occurrence" : "?", "description" : "" }, { "name" : "position", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 4, "name" : "insert-node-collection", "qname" : "model:insert-node-collection", "signature" : "($collection as xs:QName, $noderef as xs:anyURI?, $position as xs:string, $nodes)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "collection", "type" : "xs:QName", "occurrence" : null, "description" : "" }, { "name" : "noderef", "type" : "xs:anyURI", "occurrence" : "?", "description" : "" }, { "name" : "position", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 5, "name" : "insert-node-collection", "qname" : "model:insert-node-collection", "signature" : "($collection as xs:QName, $noderef as xs:anyURI?, $position as xs:string, $nodes, $validate as xs:boolean)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "collection", "type" : "xs:QName", "occurrence" : null, "description" : "" }, { "name" : "noderef", "type" : "xs:anyURI", "occurrence" : "?", "description" : "" }, { "name" : "position", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "validate", "type" : "xs:boolean", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "insert-node", "qname" : "model:insert-node", "signature" : "($noderef as xs:anyURI, $position as xs:string, $newnodes)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "noderef", "type" : "xs:anyURI", "occurrence" : null, "description" : "" }, { "name" : "position", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "newnodes", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 4, "name" : "make-table-row", "qname" : "model:make-table-row", "signature" : "($idx, $node, $columns, $namespaces)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "idx", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "node", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "columns", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 5, "name" : "make-table-row", "qname" : "model:make-table-row", "signature" : "($node, $path as xs:string?, $row, $columns, $namespaces)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "node", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "path", "type" : "xs:string", "occurrence" : "?", "description" : "" }, { "name" : "row", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "columns", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "make-table", "qname" : "model:make-table", "signature" : "($nodes, $namespaces)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "node-name", "qname" : "model:node-name", "signature" : "($node as element(*), $namespaces) as xs:string", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "element(*)", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "node-path-index", "qname" : "model:node-path-index", "signature" : "($node as node(), $parent as node()) as xs:integer?", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : null, "description" : "" }, { "name" : "parent", "type" : "node()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:integer?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "node-prefix", "qname" : "model:node-prefix", "signature" : "($node as element(*), $namespaces) as xs:string?", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "element(*)", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "node-reference", "qname" : "model:node-reference", "signature" : "($node) as xs:string", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "node", "qname" : "model:node", "signature" : "($definition)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "definition", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "rename-node", "qname" : "model:rename-node", "signature" : "($noderef as xs:anyURI, $name as xs:QName)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "noderef", "type" : "xs:anyURI", "occurrence" : null, "description" : "" }, { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "replace-node", "qname" : "model:replace-node", "signature" : "($noderef as xs:anyURI, $nodes)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "noderef", "type" : "xs:anyURI", "occurrence" : null, "description" : "" }, { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "replace-value", "qname" : "model:replace-value", "signature" : "($noderef as xs:anyURI, $value)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "noderef", "type" : "xs:anyURI", "occurrence" : null, "description" : "" }, { "name" : "value", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "resolve-qname", "qname" : "model:resolve-qname", "signature" : "($name as xs:QName, $namespaces) as xs:string", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "type-save", "qname" : "model:type-save", "signature" : "($val) as xs:string", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "val", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "type", "qname" : "model:type", "signature" : "($val as xs:anyAtomicType?) as xs:string", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "val", "type" : "xs:anyAtomicType", "occurrence" : "?", "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "unused-prefix", "qname" : "model:unused-prefix", "signature" : "($namespaces) as xs:string", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://api.28.io/validation" : { "ns" : "http://api.28.io/validation", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "http://zorba.io/modules/reflection", "prefix" : "reflection" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "resp" }, { "uri" : "http://api.28.io/validation", "prefix" : "validate" } ], "functions" : [ { "isDocumented" : false, "arity" : 3, "name" : "by-schema-array", "qname" : "validate:by-schema-array", "signature" : "($obj, $schema as array(), $path as xs:string)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "obj", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "schema", "type" : "array()", "occurrence" : null, "description" : "" }, { "name" : "path", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "by-schema-obj", "qname" : "validate:by-schema-obj", "signature" : "($obj as object(), $schema as object(), $path as xs:string)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "obj", "type" : "object()", "occurrence" : null, "description" : "" }, { "name" : "schema", "type" : "object()", "occurrence" : null, "description" : "" }, { "name" : "path", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "by-schema-primitive", "qname" : "validate:by-schema-primitive", "signature" : "($obj, $schema-type as xs:string, $path)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "obj", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "schema-type", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "path", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "by-schema", "qname" : "validate:by-schema", "signature" : "($obj as object(), $schema as object())", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "obj", "type" : "object()", "occurrence" : null, "description" : "" }, { "name" : "schema", "type" : "object()", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "expression", "qname" : "validate:expression", "signature" : "($expression as xs:string, $is-domain-expr as xs:boolean) as xs:boolean", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "expression", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "is-domain-expr", "type" : "xs:boolean", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "type", "qname" : "validate:type", "signature" : "($type as xs:string) as xs:boolean", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://api.28.io/sandbox" : { "ns" : "http://api.28.io/sandbox", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "http://zorba.io/modules/reference", "prefix" : "ref" }, { "uri" : "http://zorba.io/modules/reflection", "prefix" : "reflection" }, { "uri" : "http://api.28.io/sandbox", "prefix" : "sandbox" } ], "functions" : [ { "isDocumented" : false, "arity" : 3, "name" : "filter", "qname" : "sandbox:filter", "signature" : "($nodes, $xpath as xs:string, $namespaces)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "xpath", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "get-names", "qname" : "sandbox:get-names", "signature" : "($nodes, $path as xs:string, $namespaces)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "path", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "get-values", "qname" : "sandbox:get-values", "signature" : "($nodes, $path as xs:string, $namespaces)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "path", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "key-constraint", "qname" : "sandbox:key-constraint", "signature" : "($nodes, $condition as xs:string, $namespaces)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "condition", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "ns-declarations", "qname" : "sandbox:ns-declarations", "signature" : "($namespaces) as xs:string", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 4, "name" : "order", "qname" : "sandbox:order", "signature" : "($nodes, $path as xs:string, $descending as xs:boolean, $namespaces)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "path", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "descending", "type" : "xs:boolean", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 3, "name" : "tuple-constraint", "qname" : "sandbox:tuple-constraint", "signature" : "($nodes, $condition as xs:string, $namespaces)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "condition", "type" : "xs:string", "occurrence" : null, "description" : "" }, { "name" : "namespaces", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/store/static/collections/dml" : { "ns" : "http://zorba.io/modules/store/static/collections/dml", "description" : " This modules provides a set of functions to modify a collection\n and retrieve the items contained in a particular collection.\n

    \n This module is part of\n Zorba's XQuery Data Definition Facility.\n All the collections managed by this module have to be pre-declared in the\n prolog of a module.\n Please refer to the\n general documentation\n for more information and examples.\n", "sees" : [ "Data Lifecycle", "XQuery Data Definition Facility", "http://zorba.io/modules/store/static/collections/ddl", "http://zorba.io/modules/store/static/indexes/ddl", "http://zorba.io/modules/store/static/indexes/dml", "http://zorba.io/modules/store/static/integrity-constraints/ddl", "http://zorba.io/modules/store/static/integrity-constraints/dml", "http://zorba.io/errors" ], "authors" : [ "Nicolae Brinza, Matthias Brantner, David Graf, Till Westmann, Markos Zaharioudakis" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://zorba.io/modules/store/static/collections/dml", "prefix" : "cdml" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 3, "name" : "apply-insert-after", "qname" : "cdml:apply-insert-after", "signature" : "($name as xs:QName, $pos as item(), $content as item()*) as item()* external", "description" : " This function does the same thing as the insert-after()\n function except it immediately applies the resulting pending updates and\n returns the items that have been inserted.\n", "summary" : "

    This function does the same thing as the insert-after() \n function except it immediately applies the resulting pending updates and\n returns the items that have been inserted.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to insert into.
    " }, { "name" : "pos", "type" : "item()", "occurrence" : null, "description" : "" }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequence of items whose copies to insert.
    " } ], "returns" : { "type" : "item()*", "description" : "The sequence of items that have been inserted." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection is const, append-only, or queue.", "zerr:ZDDY0012 if the collection is unordered.", "zerr:ZDTY0001 if $content does not match the expected type as specified in the collection declaration according to the rules for SequenceType Matching.", "zerr:ZDDY0011 if $target is not in the collection." ] }, { "isDocumented" : true, "arity" : 3, "name" : "apply-insert-before", "qname" : "cdml:apply-insert-before", "signature" : "($name as xs:QName, $target as item(), $content as item()*) as item()* external", "description" : " This function does the same thing as insert-before() except it\n immediately applies the resulting pending updates and returns the items that\n have been inserted.\n", "summary" : "

    This function does the same thing as insert-before() except it\n immediately applies the resulting pending updates and returns the items that\n have been inserted.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to insert into.
    " }, { "name" : "target", "type" : "item()", "occurrence" : null, "description" : "
    The item in the collection before which $content will be inserted.
    " }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequence of items whose copies to insert.
    " } ], "returns" : { "type" : "item()*", "description" : "The sequence of items that have been inserted." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection $name is const, append-only, or queue.", "zerr:ZDDY0012 if the collection is unordered.", "zerr:ZDTY0001 if $content does not match the expected type as specified in the collection declaration according to the rules for SequenceType Matching.", "zerr:ZDDY0011 if $target is not an item that is contained in the collection." ] }, { "isDocumented" : true, "arity" : 2, "name" : "apply-insert-first", "qname" : "cdml:apply-insert-first", "signature" : "($name as xs:QName, $content as item()*) as item()* external", "description" : " This function does the same thing as insert-first() except it\n immediately applies the resulting pending updates and returns the items that\n have been inserted.\n", "summary" : "

    This function does the same thing as insert-first() except it\n immediately applies the resulting pending updates and returns the items that\n have been inserted.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to insert into.
    " }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequence of items whose copies to insert.
    " } ], "returns" : { "type" : "item()*", "description" : "The Sequence of items that have been inserted." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection $name is append-only, const, or queue.", "zerr:ZDDY0012 if the collection is unordered.", "zerr:ZDTY0001 if $content does not match the expected type as specified in the collection declaration according to the rules for SequenceType Matching." ] }, { "isDocumented" : true, "arity" : 2, "name" : "apply-insert-last", "qname" : "cdml:apply-insert-last", "signature" : "($name as xs:QName, $content as item()*) as item()* external", "description" : " This function does the same thing as insert-last() except it\n immediately applies the resulting pending updates and returns the items that\n have been inserted.\n", "summary" : "

    This function does the same thing as insert-last() except it\n immediately applies the resulting pending updates and returns the items that\n have been inserted.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to insert into.
    " }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequence of items whose copies to insert.
    " } ], "returns" : { "type" : "item()*", "description" : "The sequence of items that have been inserted." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection is const.", "zerr:ZDDY0012 if the collection is unordered.", "zerr:ZDTY0001 if $content does not match the expected type as specified in the collection declaration according to the rules for SequenceType Matching." ] }, { "isDocumented" : true, "arity" : 2, "name" : "apply-insert", "qname" : "cdml:apply-insert", "signature" : "($name as xs:QName, $content as item()*) as item()* external", "description" : " This function does the same thing as insert() except it\n immediately applies the resulting pending updates and returns the items that\n have been inserted.\n", "summary" : "

    This function does the same thing as insert() except it\n immediately applies the resulting pending updates and returns the items that\n have been inserted.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to insert into.
    " }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequence of items whose copies to insert.
    " } ], "returns" : { "type" : "item()*", "description" : "The sequence of items that have been inserted." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection is append-only, const, or queue.", "zerr:ZDTY0001 if $content does not match the expected type as specified in the collection declaration according to the rules for SequenceType Matching." ] }, { "isDocumented" : true, "arity" : 1, "name" : "collection-name", "qname" : "cdml:collection-name", "signature" : "($item as item()) as xs:QName external", "description" : " Gets the name of the collection the given item (node or JSON item) belongs\n to.\n", "summary" : "

    Gets the name of the collection the given item (node or JSON item) belongs\n to.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "item", "type" : "item()", "occurrence" : null, "description" : "
    The item for which to get the name of its collection.
    " } ], "returns" : { "type" : "xs:QName", "description" : "The name of the collection to which the given item belongs." }, "errors" : [ "zerr:ZDDY0011 if $item does not belong to a collection." ] }, { "isDocumented" : true, "arity" : 1, "name" : "collection", "qname" : "cdml:collection", "signature" : "($name as xs:QName) as item()* external", "description" : " Gets the sequence of nodes or JSON items from a collection.\n", "summary" : "

    Gets the sequence of nodes or JSON items from a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection.
    " } ], "returns" : { "type" : "item()*", "description" : "The seqnence of items from the collection." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available." ] }, { "isDocumented" : true, "arity" : 2, "name" : "collection", "qname" : "cdml:collection", "signature" : "($name as xs:QName, $skip as xs:integer) as item()* external", "description" : " Gets the sequence of nodes or JSON items from a collection.\n", "summary" : "

    Gets the sequence of nodes or JSON items from a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection.
    " }, { "name" : "skip", "type" : "xs:integer", "occurrence" : null, "description" : "
    The initial number of items to skip.
    " } ], "returns" : { "type" : "item()*", "description" : "The (sub)sequence of items from the collection." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available." ] }, { "isDocumented" : true, "arity" : 3, "name" : "collection", "qname" : "cdml:collection", "signature" : "($name as xs:QName, $start as xs:anyURI, $skip as xs:integer) as item()* external", "description" : " Gets the sequence of items (nodes or JSON items) from a collection.\n The parameters $start and $skip can be used to\n skip over some items at the beginning of the collection.\n If both are given, both are applied:\n first $start to skip to the referenced item\n and then $skip to skip that additional number of items.\n", "summary" : "

    Gets the sequence of items (nodes or JSON items) from a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection.
    " }, { "name" : "start", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The reference to the first item to return.
    " }, { "name" : "skip", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of additional items to skip.
    " } ], "returns" : { "type" : "item()*", "description" : "The sub-sequence from the collection." }, "errors" : [ "zerr:ZAPI0028 If the given URI is not a valid node position computed by the np:node-position function.", "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZSTR0066 if $start does not reference a node from the collection." ] }, { "isDocumented" : true, "arity" : 1, "name" : "delete-first", "qname" : "cdml:delete-first", "signature" : "($name as xs:QName) external", "description" : " Deletes the first item from a collection.\n", "summary" : "

    Deletes the first item from a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to delete from.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, deletes the first item from the collection." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection is const or append-only.", "zerr:ZDDY0012 if the collection is unordered.", "zerr:ZDDY0011 if the collection is empty." ] }, { "isDocumented" : true, "arity" : 2, "name" : "delete-first", "qname" : "cdml:delete-first", "signature" : "($name as xs:QName, $number as xs:integer) external", "description" : " Deletes the first N items from a collection.\n", "summary" : "

    Deletes the first N items from a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to delete from.
    " }, { "name" : "number", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of items to delete.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, deletes the items from the collection." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection is const or append-only.", "zerr:ZDDY0012 if the collection is unordered.", "zerr:ZDDY0011 if the collection contains less than $number items." ] }, { "isDocumented" : true, "arity" : 1, "name" : "delete-last", "qname" : "cdml:delete-last", "signature" : "($name as xs:QName) external", "description" : " Deletes the last item from a collection.\n", "summary" : "

    Deletes the last item from a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to delete from.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, deletes the last item from the collection." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection is const, append-only, or queue.", "zerr:ZDDY0012 if the collection is unordered.", "zerr:ZDDY0011 if the collection is empty." ] }, { "isDocumented" : true, "arity" : 2, "name" : "delete-last", "qname" : "cdml:delete-last", "signature" : "($name as xs:QName, $number as xs:integer) external", "description" : " Deletes the last N items from a collection.\n", "summary" : "

    Deletes the last N items from a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to delete from.
    " }, { "name" : "number", "type" : "xs:integer", "occurrence" : null, "description" : "
    The number of items to delete.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, deletes the items." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0012 if the collection is unordered.", "zerr:ZDDY0011 if the collection contains less than $number items." ] }, { "isDocumented" : true, "arity" : 1, "name" : "delete", "qname" : "cdml:delete", "signature" : "($items as item()*) external", "description" : " Deletes items (nodes or JSON items) from a collection.\n", "summary" : "

    Deletes items (nodes or JSON items) from a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "items", "type" : "item()", "occurrence" : "*", "description" : "
    The items in the collection to delete.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, deletes the items from their collections." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection is const, append-only, or queue.", "zerr:ZDDY0011 if any item in $items is not a member of a collection or not all items belong to the same collection." ] }, { "isDocumented" : true, "arity" : 2, "name" : "edit", "qname" : "cdml:edit", "signature" : "($target as item(), $content as item()) external", "description" : " Edits the first supplied item so as to make it look exactly like a copy of\n the second supplied item while retaining its original identity.\n", "summary" : "

    Edits the first supplied item so as to make it look exactly like a copy of\n the second supplied item while retaining its original identity.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "target", "type" : "item()", "occurrence" : null, "description" : "
    The target item to be edited.
    " }, { "name" : "content", "type" : "item()", "occurrence" : null, "description" : "
    The item that serves as an edit goal.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, performs the edit." }, "errors" : [ "zerr:ZDDY0001 if the collection to which $target belongs is not declared.", "zerr:ZDDY0003 if the collection to which $target belongs is not available.", "zerr:ZDDY0006 if the collection to which $target belongs is append-only, const, or queue.", "zerr:ZDDY0017 if $target is not a member of a collection.", "zerr:ZDDY0037 if the collection is append-only.", "zerr:ZDDY0038 if the collection is a queue.", "zerr:ZDDY0039 if $target is not a root.", "zerr:ZDDY0040 if $target cannot be updated to match the content (for example, because the target is a node and the content is an object).", "zerr:ZDTY0001 if $content does not match the expected type (as specified in the collection declaration) according to the rules for SequenceType Matching." ] }, { "isDocumented" : true, "arity" : 1, "name" : "index-of", "qname" : "cdml:index-of", "signature" : "($item as item()) as xs:integer external", "description" : " Gets the position of the given item (node or JSON item) within its\n collection.\n", "summary" : "

    Gets the position of the given item (node or JSON item) within its\n collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "item", "type" : "item()", "occurrence" : null, "description" : "
    The item to get the index of.
    " } ], "returns" : { "type" : "xs:integer", "description" : "The position of $item in its collection." }, "errors" : [ "zerr:ZDDY0011 if $item does not belong to a collection.", "zerr:ZDDY0012 if the collection is unordered." ] }, { "isDocumented" : true, "arity" : 3, "name" : "insert-after", "qname" : "cdml:insert-after", "signature" : "($name as xs:QName, $target as item(), $content as item()*) external", "description" : " The insert-after function is an updating function that inserts copies of the\n given items (nodes or JSON items) into a collection at the position\n directly following the given target item.\n", "summary" : "

    The insert-after function is an updating function that inserts copies of the\n given items (nodes or JSON items) into a collection at the position\n directly following the given target item.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to insert into.
    " }, { "name" : "target", "type" : "item()", "occurrence" : null, "description" : "
    The item in the collection after which $content will be inserted.
    " }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequence of items whose copies to insert.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, inserts the items into the collection." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection is const, append-only, or queue.", "zerr:ZDDY0012 if the collection is unordered.", "zerr:ZDTY0001 if $content does not match the expected type as specified in the collection declaration according to the rules for SequenceType Matching.", "zerr:ZDDY0011 if $target is not a node that is contained in the collection." ] }, { "isDocumented" : true, "arity" : 3, "name" : "insert-before", "qname" : "cdml:insert-before", "signature" : "($name as xs:QName, $target as item(), $content as item()*) external", "description" : " Inserts copies of the given items (nodes or JSON items) into a collection at\n the position directly preceding the given target item.\n", "summary" : "

    Inserts copies of the given items (nodes or JSON items) into a collection at\n the position directly preceding the given target item.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to insert into.
    " }, { "name" : "target", "type" : "item()", "occurrence" : null, "description" : "
    The item in the collection before which $content will be inserted.
    " }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequence of items whose copies to insert.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, inserts the items into the collection." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection is const, append-only, or queue.", "zerr:ZDDY0012 if the collection is unordered.", "zerr:ZDTY0001 if $content does not match the expected type as specified in the collection declaration according to the rules for SequenceType Matching.", "zerr:ZDDY0011 if $target is not an item that is contained in the collection." ] }, { "isDocumented" : true, "arity" : 2, "name" : "insert-first", "qname" : "cdml:insert-first", "signature" : "($name as xs:QName, $content as item()*) external", "description" : " Inserts copies of the given items (nodes or JSON items) at the beginning of\n a collection.\n", "summary" : "

    Inserts copies of the given items (nodes or JSON items) at the beginning of\n a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to insert into.
    " }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequence of items whose copies to insert.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, inserts the items into the collection." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection is append-only, const, or queue.", "zerr:ZDDY0012 if the collection is unordered.", "zerr:ZDTY0001 if $content does not match the expected type as specified in the collection declaration according to the rules for SequenceType Matching." ] }, { "isDocumented" : true, "arity" : 2, "name" : "insert-last", "qname" : "cdml:insert-last", "signature" : "($name as xs:QName, $content as item()*) external", "description" : " Inserts copies of the given items (nodes or JSON items) at the end of a\n collection.\n", "summary" : "

    Inserts copies of the given items (nodes or JSON items) at the end of a\n collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to insert into.
    " }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequence of itemss whose copies to insert.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, inserts the items into the collection." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection is const.", "zerr:ZDDY0012 if the collection is unordered.", "zerr:ZDTY0001 if $content does not match the expected type as specified in the collection declaration according to the rules for SequenceType Matching." ] }, { "isDocumented" : true, "arity" : 2, "name" : "insert", "qname" : "cdml:insert", "signature" : "($name as xs:QName, $content as item()*) external", "description" : " Inserts copies of the given items (nodes or JSON items) into a collection.\n Note that the insertion position of the items in the collection is not\n defined.\n", "summary" : "

    Inserts copies of the given items (nodes or JSON items) into a collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection to insert into.
    " }, { "name" : "content", "type" : "item()", "occurrence" : "*", "description" : "
    The sequence of items whose copies to insert.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, inserts the items into the collection." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available.", "zerr:ZDDY0006 if the collection is append-only, const, or queue.", "zerr:ZDTY0001 if $content does not match the expected type as specified in the collection declaration according to the rules for SequenceType Matching." ] }, { "isDocumented" : true, "arity" : 1, "name" : "truncate", "qname" : "cdml:truncate", "signature" : "($name as xs:QName) external", "description" : " Deletes the entire contents of collection.\n Please note that applying this function can not be undone in case\n an error happens during the application of the containing PUL.\n", "summary" : "

    Deletes the entire contents of collection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : true, "parameters" : [ { "name" : "name", "type" : "xs:QName", "occurrence" : null, "description" : "
    The name of the collection whose content to delete.
    " } ], "returns" : { "type" : null, "description" : "An empty XDM instance and a pending update list that, once applied, deletes the nodes." }, "errors" : [ "zerr:ZDDY0001 if the collection is not declared.", "zerr:ZDDY0003 if the collection is not available." ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/http-request" : { "ns" : "http://www.28msec.com/modules/http-request", "description" : " The request module provides functions for accessing\n information contained in the HTTP request used to evaluate the current\n query. For example, the param-names function can be used to\n retrieve all the names of the parameters contained in a request.\n", "sees" : [ ], "authors" : [ "Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://www.28msec.com/modules/http/request#2.0", "prefix" : "req" }, { "uri" : "http://www.28msec.com/modules/http-request", "prefix" : "request" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "binary-content", "qname" : "request:binary-content", "signature" : "() as xs:base64Binary", "description" : "

    Returns the content of the request as base64Binary.

    \n", "summary" : "

    Returns the content of the request as base64Binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:base64Binary", "description" : "The content of the request as base64Binary." }, "errors" : [ "request:no-binary-content if the content contained in the body of the request cannot be treated as binary because it is a request with multipart or url-encoded content." ] }, { "isDocumented" : true, "arity" : 1, "name" : "binary-part", "qname" : "request:binary-part", "signature" : "($ref as xs:string) as xs:base64Binary", "description" : "

    Returns the value of a part as base64Binary.

    \n

    A part is identified by a reference that is the value of a\n src field returned by the request:parts function.

    \n", "summary" : "

    Returns the value of a part as base64Binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "ref", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the part
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the value of the part as base64Binary" }, "errors" : [ "request:invalid-part if the part with the given name ($ref) does not exist", "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 0, "name" : "content-length", "qname" : "request:content-length", "signature" : "() as xs:integer?", "description" : "

    Returns the length of the content in bytes.

    \n

    The value returned corresponds to the value of the HTTP\n content-length header. The function returns an empty sequence\n if this header does not exist in the request or its value\n could not be converted to item of type xs:integer

    .\n", "summary" : "

    Returns the length of the content in bytes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:integer?", "description" : "The content-length in bytes of the content sent with this request or the empty sequence if the content-length header does not exist in the request." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "content-type", "qname" : "request:content-type", "signature" : "() as xs:string?", "description" : "

    Returns the content-type of the data sent with this request.

    \n

    Note that the content-type is only set for PUT and POST requests.

    \n", "summary" : "

    Returns the content-type of the data sent with this request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string?", "description" : "The content-type of the request if it is a PUT or POST request. Otherwise, it returns the empty sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "header-accept", "qname" : "request:header-accept", "signature" : "() as object()*", "description" : "

    Returns the values of the HTTP ACCEPT header.

    \n

    The data is returned as a sequence of objects\n as shown in the following example.

    \n
    \n {\n   \"type\" : \"text\",\n   \"subtype\" : \"html\",\n   \"quality\" : 1\n }\n 
    \n", "summary" : "

    Returns the values of the HTTP ACCEPT header.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()*", "description" : "The header values of the header ACCEPT or the empty sequence if the header is not contained in the request. The order of the returned objects reflects the order of the components in the header." }, "errors" : [ "request:invalid-header if the accept header cannot be parsed" ] }, { "isDocumented" : true, "arity" : 0, "name" : "header-names", "qname" : "request:header-names", "signature" : "() as xs:string*", "description" : "

    Returns the names of all the HTTP headers in this request.

    \n

    Header fields are colon-separated name-value pairs, terminated\n by a carriage return (CR) and line feed (LF) character sequence. The\n names and values of each header are allowed to consist of US-ASCII\n characters only.

    \n

    The names of the headers are returned using upper-case letters.\n If a header with the same name is contained multiple times in a request,\n its name is only returned once. The order of the names in the resulting\n sequence does not reflect the order of the headers in the request. If\n a header does not have a value, it is as if the header does not exist\n in the request.

    \n

    Note that the header names user-agent and content-type are not\n returned by this function. They are returned by the corresponding\n functions of this module module\n (e.g. user-agent).

    \n", "summary" : "

    Returns the names of all the HTTP headers in this request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string*", "description" : "The names of the headers of this request or the empty sequence if no headers are contained in the request." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "header-value", "qname" : "request:header-value", "signature" : "($name as xs:string) as xs:string?", "description" : "

    Returns the value of the HTTP header with the given name.

    \n

    Header fields are colon-separated name-value pairs, terminated\n by a carriage return (CR) and line feed (LF) character sequence. The\n names and values of each header are allowed to consist of US-ASCII\n characters only.

    \n

    Please note that header names are considered case-insensitive.\n Also note, that only one value is returned if multiple headers with the\n same names exist in the request. This value is a comma-separated list\n of the values of the headers in the order in which the headers appeared\n in the request.

    \n

    All headers having a name that starts with SAUSALITO_ are reserved\n and will not be returned by this function.

    \n", "summary" : "

    Returns the value of the HTTP header with the given name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The header name for which the value should be returned.
    " } ], "returns" : { "type" : "xs:string?", "description" : "The header value of the header with the $name argument or the empty sequence if no header with that name is contained in the request." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "headers", "qname" : "request:headers", "signature" : "() as object()", "description" : "

    Returns an object containing the request's HTTP header names and\n values.

    \n

    Header fields are colon-separated name-value pairs, terminated\n by a carriage return (CR) and line feed (LF) character sequence. The\n names and values of each header are allowed to consist of US-ASCII\n characters only.

    \n

    The structure of the object is as shown in the following example:\n

    \n 
    \n

    \n

    All headers having a name that starts with SAUSALITO_ are reserved\n and will not be returned by this function.

    \n", "summary" : "

    Returns an object containing the request's HTTP header names and\n values.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "The header value of the header with the $name argument or the empty sequence if no header with that name is contained in the request." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method-delete", "qname" : "request:method-delete", "signature" : "() as xs:boolean", "description" : " Returns true if the HTTP method of this request is DELETE.\n", "summary" : "

    Returns true if the HTTP method of this request is DELETE.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "true if the HTTP method of this request is DELETE, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method-get", "qname" : "request:method-get", "signature" : "() as xs:boolean", "description" : " Returns true if the HTTP method of this request is GET.\n", "summary" : "

    Returns true if the HTTP method of this request is GET.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "true if the HTTP method of this request is GET, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method-head", "qname" : "request:method-head", "signature" : "() as xs:boolean", "description" : " Returns true if the HTTP method of this request is HEAD.\n", "summary" : "

    Returns true if the HTTP method of this request is HEAD.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "true if the HTTP method of this request is HEAD, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method-options", "qname" : "request:method-options", "signature" : "() as xs:boolean", "description" : " Returns true if the HTTP method of this request is OPTION.\n", "summary" : "

    Returns true if the HTTP method of this request is OPTION.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "true if the HTTP method of this request is OPTION, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method-post", "qname" : "request:method-post", "signature" : "() as xs:boolean", "description" : " Returns true if the HTTP method of this request is POST.\n", "summary" : "

    Returns true if the HTTP method of this request is POST.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "true if the HTTP method of this request is POST, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method-put", "qname" : "request:method-put", "signature" : "() as xs:boolean", "description" : " Returns true if the HTTP method of this request is PUT.\n", "summary" : "

    Returns true if the HTTP method of this request is PUT.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "true if the HTTP method of this request is PUT, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "method", "qname" : "request:method", "signature" : "() as xs:string", "description" : "

    Returns the name of the HTTP method used to make this request.

    \n", "summary" : "

    Returns the name of the HTTP method used to make this request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The request method used to make this request (i.e. GET, POST, PUT, DELETE or HEAD)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "param-names", "qname" : "request:param-names", "signature" : "() as xs:string*", "description" : "

    Returns the names of the parameters contained in the current request.

    \n

    Parameters are name-value pairs contained in the query string of the URL\n used to make this request. As defined in RFC 1738, the query string of a\n URL starts with a \"?\" character and ends with the character (if any).\n Additionally, such name-value pairs may be part of the request's body if\n it is a PUT or POST request and the content-type of the request is\n \"application/x-www-form-urlencoded\". Name-value pairs are separated\n using either the \"&\" or the \";\" character.

    \n

    In general, the names and the values are precent-encoded. This function\n does the decoding of the parameters, i.e. it returns the values being\n not percent-encoded.

    \n

    Also, the names of each parameter (after being precent-decoded) are\n treated as UTF-8. Please see the http:param-names#1 function\n for retrieving parameter names submitted using a encoding other than UTF-8.\n

    \n", "summary" : "

    Returns the names of the parameters contained in the current request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string*", "description" : "The names of all parameters in this request. The empty sequence is returned if there are none." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "param-names", "qname" : "request:param-names", "signature" : "($encoding as xs:string) as xs:string*", "description" : "

    Returns the names of the parameters contained in the current request.

    \n

    This function is similar to the request:param-names#0 function.\n However, the names are treated (after precent-decoding) using the\n given encoding supplied as parameter. For example, parameters might\n be encoded using the ISO-8859-1 encoding.

    \n", "summary" : "

    Returns the names of the parameters contained in the current request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "
    The encoding of the parameters in the request (e.g. ISO-8859-1).
    " } ], "returns" : { "type" : "xs:string*", "description" : "The names of all parameters in this request. The empty sequence is returned if there are none." }, "errors" : [ "request:invalid-encoding if the given encoding is invalid or not supported." ] }, { "isDocumented" : true, "arity" : 1, "name" : "param-values", "qname" : "request:param-values", "signature" : "($name as xs:string) as xs:string*", "description" : "

    Returns a sequence of parameter values for the given parameter name\n which are contained in the URL's query string or the body of a POST or PUT\n request.

    \n

    Parameters are name-value pairs contained in the query string of the URL\n used to make this request. As defined in RFC 1738, the query string of a\n URL starts with a \"?\" character and ends with the character (if any).\n Additionally, such name-value pairs may be part of the request's body if\n it is a PUT or POST request and the content-type of the request is\n \"application/x-www-form-urlencoded\". Name-value pairs are separated\n using either the \"&\" or the \";\" character.

    \n

    In general, the names and the values are precent-encoded. This function\n does the decoding of the parameters, i.e. it returns the values being\n not percent-encoded.

    \n

    Also, the names and the values of each parameter (after being precent-decoded)\n are treated as UTF-8. Please see the http:param-values#3 function\n for retrieving parameters submitted using a encoding other than UTF-8.

    \n

    This function returns the empty-sequence if no parameter with the\n given name exists in this request. If you want the function to return\n a default value other than the empty sequence, use the\n http:param-values#2 function.

    \n

    A URL could contain the following query string:\n name1=value1&name2=value2;name1=value3&name3.\n name1=value1&name2=value2&name1=value3&name3.\n The name value pairs in this query string are\n

      \n
    • name: name1; values: value1 and value3
    • \n
    • name: name2; value: value2
    • \n
    • name: name3; value:
    • \n
    \n

    \n", "summary" : "

    Returns a sequence of parameter values for the given parameter name\n which are contained in the URL's query string or the body of a POST or PUT\n request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the parameter whose value(s) should be returned.
    " } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of values for the parameter with the given name. The empty sequence is returned if no parameter exists with the given name." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "param-values", "qname" : "request:param-values", "signature" : "($name as xs:string, $default-values as xs:string*) as xs:string*", "description" : "

    Returns a sequence of parameter values for the given parameter name\n which are contained in the URL's query string or the body of a POST or PUT\n request.

    \n

    This function is similar to the request:param-values#1 function.\n However, instead of returning the empty-sequence as a default value it returns\n the given default-values sequence if no parameter with the given name is found\n in this request.

    \n", "summary" : "

    Returns a sequence of parameter values for the given parameter name\n which are contained in the URL's query string or the body of a POST or PUT\n request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the parameter whose value(s) should be returned.
    " }, { "name" : "default-values", "type" : "xs:string", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of values for the parameter with the given name. The sequence given as $default-values parameter is returned if no parameter exists with the given name." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 3, "name" : "param-values", "qname" : "request:param-values", "signature" : "($name as xs:string, $default-values as xs:string*, $encoding as xs:string) as xs:string*", "description" : "

    Returns a sequence of parameter values for the given parameter name\n which are contained in the URL's query string or the body of a POST or PUT\n request.

    \n

    This function is similar to the request:param-values#2 function.\n However, the names and values are treated (after precent-decoding) using the\n given encoding supplied as third parameter. For example, parameters might\n be encoded using the ISO-8859-1 encoding.

    \n", "summary" : "

    Returns a sequence of parameter values for the given parameter name\n which are contained in the URL's query string or the body of a POST or PUT\n request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of the parameter whose value(s) should be returned.
    " }, { "name" : "default-values", "type" : "xs:string", "occurrence" : "*", "description" : "" }, { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "
    The encoding of the parameters in the request (e.g. ISO-8859-1)
    " } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of values for the parameter with the given name. The sequence given as $default-values parameter is returned if no parameter exists with the given name." }, "errors" : [ "request:invalid-encoding if the given encoding is invalid or not supported." ] }, { "isDocumented" : true, "arity" : 0, "name" : "params", "qname" : "request:params", "signature" : "() as object()", "description" : "

    Returns an object containg the parameter names and values contained\n in the URL's query string or the body of a POST or PUT\n request.

    \n

    The structure of the object for the query string\n \"param1=value1;param2&param2=value2\"\n

    \n {\n   \"param1\" : \"value1\",\n   \"param2\" : [ \"\", \"value2\" ]\n }\n 
    \n

    \n

    Parameters are name-value pairs contained in the query string of the URL\n used to make this request. As defined in RFC 1738, the query string of a\n URL starts with a \"?\" character and ends with the character (if any).\n Additionally, such name-value pairs may be part of the request's body if\n it is a PUT or POST request and the content-type of the request is\n \"application/x-www-form-urlencoded\". Name-value pairs are separated\n using either the \"&\" or the \";\" character.

    \n

    In general, the names and the values are precent-encoded. This function\n does the decoding of the parameters, i.e. it returns the values being\n not percent-encoded.

    \n

    Also, the names and the values of each parameter (after being precent-decoded)\n are treated as UTF-8. Please see the http:params#1 function\n for retrieving parameters submitted using a encoding other than UTF-8.

    \n", "summary" : "

    Returns an object containg the parameter names and values contained\n in the URL's query string or the body of a POST or PUT\n request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "An object containing all the parameter names and values. An empty object is returned if the request doesn't contain any parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "params", "qname" : "request:params", "signature" : "($encoding as xs:string) as object()", "description" : "

    Returns an object containg the parameter names and values contained\n in the URL's query string or the body of a POST or PUT\n request.

    \n

    The structure of the object for the query string\n \"param1=value1;param2&param2=value2\"\n

    \n {\n   \"param1\" : \"value1\",\n   \"param2\" : [ \"\", \"value2\" ]\n }\n 
    \n

    \n

    Parameters are name-value pairs contained in the query string of the URL\n used to make this request. As defined in RFC 1738, the query string of a\n URL starts with a \"?\" character and ends with the character (if any).\n Additionally, such name-value pairs may be part of the request's body if\n it is a PUT or POST request and the content-type of the request is\n \"application/x-www-form-urlencoded\". Name-value pairs are separated\n using either the \"&\" or the \";\" character.

    \n

    In general, the names and the values are precent-encoded. This function\n does the decoding of the parameters, i.e. it returns the values being\n not percent-encoded.

    \n

    The name and value of each parameter (after being percent-decoded) are treated\n in the encoding given by the $encoding paramter.

    \n", "summary" : "

    Returns an object containg the parameter names and values contained\n in the URL's query string or the body of a POST or PUT\n request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "
    The encoding of the parameters in the request (e.g. ISO-8859-1)
    " } ], "returns" : { "type" : "object()", "description" : "An object containing all the parameter names and values. An empty object is returned if the request doesn't contain any parameters." }, "errors" : [ "request:invalid-encoding if the given encoding is invalid or not supported." ] }, { "isDocumented" : true, "arity" : 0, "name" : "parts", "qname" : "request:parts", "signature" : "() as object()?", "description" : "

    Returns the metadata of all parts contained in a multipart request.

    \n

    The metadata is returned as an object\n as shown in the following example.

    \n
    \n {\n   \"media-type\" : \"multipart/form-data; boundary=----------------------------93298e7a66a4\",\n   \"parts\" : [ {\n     \"headers\" : {\n       \"Content-Disposition\" : \"form-data; name=\\\"upload\\\"; filename=\\\"tmp.txt\\\"\",\n       \"Content-Type\" : \"text/plain\"\n     },\n     \"filename\" : \"tmp.txt\",\n     \"name\" : \"upload\",\n     \"src\" : \"urn:uuid:09be48d1-da0e-42c1-a115-a697e1779c45\",\n     \"size\" : \"153\"\n   }, {\n     \"headers\" : {\n       \"Content-Disposition\" : \"form-data; name=\\\"press\\\"\"\n     },\n     \"name\" : \"press\",\n     \"src\" : \"urn:uuid:c80e0609-b703-4d47-9171-441eb397a562\",\n     \"size\" : \"2\"\n   } ]\n }\n 
    \n

    The media-type field describes the content-type as given in the\n request. Specifically, its value is equal to the value returned by\n request:header-values(\"Content-Type\")).

    \n

    Each of the array members of the parts field represents one\n part of the multipart request. Each such part contains a header field\n containing one field for each headers belonging to that part.\n The value of the src field can be used to retrieve the actual value\n of the part by passing it to the http:text-part or\n http:binary-part functions. The remaining fields represent a\n parameter of the Content-Disposition header as described in RFC 2183\n (e.g. filename, name, creation-date).

    \n

    Please note that recursive multipart content is not supported.

    \n", "summary" : "

    Returns the metadata of all parts contained in a multipart request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()?", "description" : "an object representing the metadata of the multipart content or an empty sequence if there is no content." }, "errors" : [ "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 0, "name" : "path", "qname" : "request:path", "signature" : "() as xs:string", "description" : " Return the path component of the request URI. The path starts after the\n host and ends before the query string starts.\n", "summary" : "

    Return the path component of the request URI.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The path component of the request URI" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "query", "qname" : "request:query", "signature" : "() as xs:string", "description" : "

    Returns the query string that was used to make this request.

    \n

    The query string contains the part of the request URL that\n starts with the '?' character to the end or the starting of the\n fragment (i.e. the '#' character).

    \n", "summary" : "

    Returns the query string that was used to make this request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The query string part of the request's URL" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "remote-addr", "qname" : "request:remote-addr", "signature" : "() as xs:string", "description" : "

    Returns the IP address of the client to which this request\n is connected.

    \n", "summary" : "

    Returns the IP address of the client to which this request\n is connected.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The IP address on the client side to which this request is connected." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "remote-port", "qname" : "request:remote-port", "signature" : "() as xs:int", "description" : "

    Returns the port of the client to which this request is connected.

    \n", "summary" : "

    Returns the port of the client to which this request is connected.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:int", "description" : "The port on the client side to which this request is connected." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "server-name", "qname" : "request:server-name", "signature" : "() as xs:string", "description" : "

    Returns the server name of the server running the application.

    \n

    The web server's hostname or IP address.

    \n", "summary" : "

    Returns the server name of the server running the application.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The name of the server that runs the application accepting this request." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "server-port", "qname" : "request:server-port", "signature" : "() as xs:int", "description" : "

    Returns the sever port to which the client making the current request\n is connected.

    \n", "summary" : "

    Returns the sever port to which the client making the current request\n is connected.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:int", "description" : "The server port to which the client is connected." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "text-content", "qname" : "request:text-content", "signature" : "() as xs:string", "description" : "

    Returns the content of the request as string.

    \n

    The function returns the content of the request only\n if the content-type refers to a type that can be treated\n as text (e.g. text/* or application/xml). The function raises\n an error if the content cannot be treated as text.

    \n

    The text content is interpreted using the encoding/charset\n that is specified in the Content-Type header of the request. If\n no charset is specified, the default ISO-8859-1 is used. If a encoding\n other than the specified or default one should be used, the\n request:text-content#1 function should be used.

    \n", "summary" : "

    Returns the content of the request as string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The content of the request as a string." }, "errors" : [ "request:invalid-encoding if the encoding specified in the Content-Type header is invalid or not supported.", "request:no-text-content if the content contained in the body of the request cannot be treated as text." ] }, { "isDocumented" : true, "arity" : 1, "name" : "text-content", "qname" : "request:text-content", "signature" : "($overwrite-encoding as xs:string) as xs:string", "description" : "

    Returns the content of the request as string interpreting\n it with the given encoding.

    \n

    The function returns the content of the request only\n if the content-type refers to a type that can be treated\n as text (e.g. text/* or application/xml). The function raises\n an error if the content cannot be treated as text.

    \n

    The text content is interpreted using the given encoding/charset.\n That is, the charset specified in the Content-Type header of the request\n is ignored. An error is raised if the given encoding is invalid\n or not supported.

    \n", "summary" : "

    Returns the content of the request as string interpreting\n it with the given encoding.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "overwrite-encoding", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "The content of the request as a string." }, "errors" : [ "request:invalid-encoding if the encoding specified in the Content-Type header or the $overwrite-encoding parameter is invalid or not supported.", "request:no-text-content if the content contained in the body of the request cannot be treated as text." ] }, { "isDocumented" : true, "arity" : 1, "name" : "text-part", "qname" : "request:text-part", "signature" : "($ref as xs:string) as xs:string", "description" : "

    Returns the value of a part as string

    \n

    A part is identified by a reference that is the value of a\n src field returned by the request:parts function.

    \n

    The value of the text part is interpreted using the encoding/charset\n given in the headers of the part. If no encoding is given, the default\n US-ASCII is assumed.

    \n", "summary" : "

    Returns the value of a part as string \n A part is identified by a reference that is the value of a\n src field returned by the request:parts function.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "ref", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the part
    " } ], "returns" : { "type" : "xs:string", "description" : "the value of the part as string" }, "errors" : [ "request:invalid-encoding if the encoding given in the headers of the part is invalid or not supported.", "request:no-text-content if the value of the part cannot be treated as text", "request:invalid-part if the part with the given name ($ref) does not exist", "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 2, "name" : "text-part", "qname" : "request:text-part", "signature" : "($ref as xs:string, $overwrite-encoding as xs:string) as xs:string", "description" : "

    Returns the value of a part as string interpreting\n it with the given encoding.

    \n

    A part is identified by a reference that is the value of a\n src field returned by the request:parts function.

    \n", "summary" : "

    Returns the value of a part as string interpreting\n it with the given encoding.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "ref", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the part
    " }, { "name" : "overwrite-encoding", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "the value of the part as string" }, "errors" : [ "request:invalid-encoding if the encoding given using the $overwrite-encoding parameter is invalid or not supported.", "request:no-text-content if the value of the part cannot be treated as text", "request:invalid-part if the part with the given name ($ref) does not exist", "request:non-multipart if the current request does not contain multipart content", "request:invalid-multipart if the multipart content is invalid (e.g. the boundary is missing)" ] }, { "isDocumented" : true, "arity" : 0, "name" : "uri", "qname" : "request:uri", "signature" : "() as xs:string", "description" : "

    Returns the URI that was used to make this request.

    \n

    The value returned contains the part of the URL starting\n from the path to the end or the starting of the fragment (i.e.\n the '#' character).

    \n", "summary" : "

    Returns the URI that was used to make this request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string", "description" : "The path and query string part of the request's URL" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "user-agent", "qname" : "request:user-agent", "signature" : "() as xs:string?", "description" : "

    Returns the user agent that made to perform the current request.

    \n

    This function returns the value of the User-Agent header\n contained in the current request.

    \n", "summary" : "

    Returns the user agent that made to perform the current request.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:string?", "description" : "The user agent used to perform this request of the empty sequence if there was no User-Agent header in the request." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/physical-reference" : { "ns" : "http://www.28msec.com/modules/physical-reference", "description" : " The module provides functions to compute an immutable and opaque reference\n for nodes, objects, or arrays and to retrieve such items given their\n identifier, respectively.\n The identifiers are immutable, i.e. a identifier does not change\n during the items lifetime and cannot be reused for another item after the\n original item gets deleted.\n Identifiers are unique, in that, two different items will never have the same\n identifier. A item, at any time during its lifetime, can be retrieved by its\n identifier. Identifiers can only be computed for items stored in a MongoDB\n collection.\n

    Please see the data lifecycle\n documentation about details on storing items.

    \n", "sees" : [ "Data Lifecycle" ], "authors" : [ "Federico Cavalieri" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.28msec.com/modules/physical-reference", "prefix" : "ref" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "dereference", "qname" : "ref:dereference", "signature" : "($arg as object()) as item()? external", "description" : "

    Returns the node, object, or array identified by the given reference.

    \n

    The function returns the empty sequence if the item\n that is referenced does not exist.

    \n", "summary" : "

    Returns the node, object, or array identified by the given reference.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "object()", "occurrence" : null, "description" : "
    the identifier of the item to retrieve.
    " } ], "returns" : { "type" : "item()?", "description" : "the item identified by the identifier passed as parameter or the empty-sequence if no item with that URI is found." }, "errors" : [ "ref::REFERENCE is if the given identifier is invalid." ] }, { "isDocumented" : true, "arity" : 1, "name" : "reference", "qname" : "ref:reference", "signature" : "($arg as item()) as object() external", "description" : "

    Returns an immutable and opaque reference (with type xs:anyURI) for\n a given node, object, or array.

    \n

    The generated identifier is immutable, i.e. a identifier does not\n change during the item's lifetime and cannot be reused for another node after\n the original item gets deleted.

    \n

    Identifiers are also unique, in that, two different items will never\n have the same identifier.

    \n A item, at any time during its lifetime, can be retrieved by its\n identifier, using the ref:dereference function.\n Please note that a reference can only be retrieved for a JSON object or JSON\n array if the item is a member of a collection.\n", "summary" : "

    Returns an immutable and opaque reference (with type xs:anyURI) for\n a given node, object, or array.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "arg", "type" : "item()", "occurrence" : null, "description" : "
    the node, object, or array for which the URI should be computed
    " } ], "returns" : { "type" : "object()", "description" : "the opaque URI of the item." }, "errors" : [ "ref::COLLECTION is raised if the object or array passed as argument is not a member of a collection." ] } ], "variables" : [ ] }, "http://zorba.io/modules/data-cleaning/conversion" : { "ns" : "http://zorba.io/modules/data-cleaning/conversion", "description" : "

    This library module provides data conversion functions for processing calendar dates,\n temporal values, currency values, units of measurement, location names and postal addresses.

    \n

    \n

    The logic contained in this module is not specific to any particular XQuery implementation.

    \n", "sees" : [ ], "authors" : [ "Bruno Martins and Diogo Simões" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://zorba.io/modules/data-cleaning/conversion", "prefix" : "conversion" }, { "uri" : "http://www.ecb.int/vocabulary/2002-08-01/eurofxref", "prefix" : "exref" }, { "uri" : "http://www.zorba-xquery.com/modules/http-client", "prefix" : "http" }, { "uri" : "http://zorba.io/modules/reflection", "prefix" : "reflection" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://api.whitepages.com/schema/", "prefix" : "wp" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "address-from-domain", "qname" : "conversion:address-from-domain", "signature" : "($domain as xs:string) as xs:string*", "description" : "

    Uses a whois service to discover information about a given domain name, returning a sequence of strings\n for the addresses associated to the name.

    \n", "summary" : "

    Uses a whois service to discover information about a given domain name, returning a sequence of strings\n for the addresses associated to the name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "domain", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of strings for the addresses associated to the domain name.

    Attention : This function is still not implemented.

    " }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "address-from-geocode", "qname" : "conversion:address-from-geocode", "signature" : "($lat as xs:double, $lon as xs:double) as xs:string*", "description" : "

    Geospatial coordinates to placename converter, acting as a wrapper over the Yahoo! reverse geocoder service.

    \n", "summary" : "

    Geospatial coordinates to placename converter, acting as a wrapper over the Yahoo! reverse geocoder service.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "lat", "type" : "xs:double", "occurrence" : null, "description" : "
    Geospatial latitude.
    " }, { "name" : "lon", "type" : "xs:double", "occurrence" : null, "description" : "
    Geospatial longitude.
    " } ], "returns" : { "type" : "xs:string*", "description" : "The sequence of strings corresponding to the different components (e.g., street, city, country, etc.) of the place name that corresponds to the input geospatial coordinates." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "address-from-phone", "qname" : "conversion:address-from-phone", "signature" : "($phone-number as xs:string) as xs:string*", "description" : "

    Uses a White-pages Web service to discover information about a given phone number,\n returning a string for the address associated to the phone number.

    \n", "summary" : "

    Uses a White-pages Web service to discover information about a given phone number,\n returning a string for the address associated to the phone number.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "phone-number", "type" : "xs:string", "occurrence" : null, "description" : "
    A string with 10 digits corresponding to the phone number.
    " } ], "returns" : { "type" : "xs:string*", "description" : "A string for the addresses associated to the phone number." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "address-from-user", "qname" : "conversion:address-from-user", "signature" : "($name as xs:string) as xs:string*", "description" : "

    Uses a White-pages Web service to discover information about a given name,\n returning a sequence of strings for the addresses associated to the name.

    \n", "summary" : "

    Uses a White-pages Web service to discover information about a given name,\n returning a sequence of strings for the addresses associated to the name.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of person or organization.
    " } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of strings for the addresses associated to the name." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "currency-convert", "qname" : "conversion:currency-convert", "signature" : "($v as xs:double, $m1 as xs:string, $m2 as xs:string, $date as xs:string) as xs:double", "description" : "

    Currency conversion function, acting as a wrapper over the WebService from the European Central Bank.

    \n

    \n

    WebService documentation at http://www.ecb.int/stats/exchange/eurofxref/html/index.en.html

    \n", "summary" : "

    Currency conversion function, acting as a wrapper over the WebService from the European Central Bank.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "v", "type" : "xs:double", "occurrence" : null, "description" : "
    The amount we wish to convert.
    " }, { "name" : "m1", "type" : "xs:string", "occurrence" : null, "description" : "
    The source currency (e.g., \"EUR\").
    " }, { "name" : "m2", "type" : "xs:string", "occurrence" : null, "description" : "
    The target currency (e.g., \"USD\").
    " }, { "name" : "date", "type" : "xs:string", "occurrence" : null, "description" : "
    The reference date.
    " } ], "returns" : { "type" : "xs:double", "description" : "The value resulting from the conversion." }, "errors" : [ "conversion:NOTSUPPORTED if the date, the source currency type or the target currency type are not known to the service." ] }, { "isDocumented" : true, "arity" : 1, "name" : "geocode-from-address", "qname" : "conversion:geocode-from-address", "signature" : "($q as xs:string*) as xs:double*", "description" : "

    Placename to geospatial coordinates converter, acting as a wrapper over the Yahoo! geocoder service.

    \n", "summary" : "

    Placename to geospatial coordinates converter, acting as a wrapper over the Yahoo! geocoder service.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "q", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings corresponding to the different components (e.g., street, city, country, etc.) of the place name.
    " } ], "returns" : { "type" : "xs:double*", "description" : "The pair of latitude and longitude coordinates associated with the input address." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "name-from-domain", "qname" : "conversion:name-from-domain", "signature" : "($domain as xs:string) as xs:string*", "description" : "

    Uses a whois service to discover information about a given domain name, returning a sequence of strings\n for the person or organization names associated to the name.

    \n", "summary" : "

    Uses a whois service to discover information about a given domain name, returning a sequence of strings\n for the person or organization names associated to the name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "domain", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of strings for the person or organization names associated to the domain name.

    Attention : This function is still not implemented.

    " }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "phone-from-address", "qname" : "conversion:phone-from-address", "signature" : "($address as xs:string) as xs:string*", "description" : "

    Uses a White-pages Web service to discover information about a given address,\n returning a sequence of strings for the phone number associated to the address.

    \n", "summary" : "

    Uses a White-pages Web service to discover information about a given address,\n returning a sequence of strings for the phone number associated to the address.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "address", "type" : "xs:string", "occurrence" : null, "description" : "
    A string corresponding to the address (ex: 5655 E Gaskill Rd, Willcox, AZ, US).
    " } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of strings for the phone number or organization's names associated to the address." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "phone-from-domain", "qname" : "conversion:phone-from-domain", "signature" : "($domain as xs:string) as xs:string*", "description" : "

    Uses a whois service to discover information about a given domain name, returning a sequence of strings\n for the phone numbers associated to the name.

    \n", "summary" : "

    Uses a whois service to discover information about a given domain name, returning a sequence of strings\n for the phone numbers associated to the name.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "domain", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of strings for the phone numbers associated to the domain name.

    Attention : This function is still not implemented.

    " }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "phone-from-user", "qname" : "conversion:phone-from-user", "signature" : "($name as xs:string) as xs:string*", "description" : "

    Uses a White-pages Web service to discover information about a given name,\n returning a sequence of strings for the phone numbers associated to the name.

    \n", "summary" : "

    Uses a White-pages Web service to discover information about a given name,\n returning a sequence of strings for the phone numbers associated to the name.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    The name of person or organization.
    " } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of strings for the phone numbers associated to the name." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 4, "name" : "unit-convert", "qname" : "conversion:unit-convert", "signature" : "($v as xs:double, $t as xs:string, $m1 as xs:string, $m2 as xs:string) as xs:double", "description" : "

    Conversion function for units of measurement, acting as a wrapper over the CuppaIT WebService.

    \n", "summary" : "

    Conversion function for units of measurement, acting as a wrapper over the CuppaIT WebService.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "v", "type" : "xs:double", "occurrence" : null, "description" : "
    The amount we wish to convert.
    " }, { "name" : "t", "type" : "xs:string", "occurrence" : null, "description" : "
    The type of metric (e.g., \"Distance\")
    " }, { "name" : "m1", "type" : "xs:string", "occurrence" : null, "description" : "
    The source measurement unit metric (e.g., \"meter\")
    " }, { "name" : "m2", "type" : "xs:string", "occurrence" : null, "description" : "
    The target measurement unit metric (e.g., \"mile\")
    " } ], "returns" : { "type" : "xs:double", "description" : "The value resulting from the conversion" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "user-from-address", "qname" : "conversion:user-from-address", "signature" : "($address as xs:string) as xs:string*", "description" : "

    Uses a White-pages Web service to discover information about a given address,\n returning a sequence of strings for the names associated to the address.

    \n", "summary" : "

    Uses a White-pages Web service to discover information about a given address,\n returning a sequence of strings for the names associated to the address.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "address", "type" : "xs:string", "occurrence" : null, "description" : "
    A string corresponding to the address (ex: 5655 E Gaskill Rd, Willcox, AZ, US).
    " } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of strings for the person or organization's names associated to the address." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "user-from-phone", "qname" : "conversion:user-from-phone", "signature" : "($phone-number as xs:string) as xs:string*", "description" : "

    Uses a White-pages Web service to discover information about a given phone number,\n returning a sequence of strings for the name associated to the phone number.

    \n", "summary" : "

    Uses a White-pages Web service to discover information about a given phone number,\n returning a sequence of strings for the name associated to the phone number.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "phone-number", "type" : "xs:string", "occurrence" : null, "description" : "
    A string with 10 digits corresponding to the phone number.
    " } ], "returns" : { "type" : "xs:string*", "description" : "A sequence of strings for the person or organization's name associated to the phone number." }, "errors" : [ ] } ], "variables" : [ { "name" : "conversion:key", "type" : "item()*", "description" : "

    The key to be used when accessing the White Pages Web service

    \n" } ] }, "http://www.28msec.com/modules/jdbc" : { "ns" : "http://www.28msec.com/modules/jdbc", "description" : " This module allows connecting, querying, and updating JDBC datasources.\n

    The results of a query are returned as a sequence of objects:\n { column: value } .\n The type of the value depends on the type of the column in the database:\n \n \n \n \n \n \n \n
    JDBC TypesJSONiq Type
    integer, bigint, smallint, tinyintinteger
    decimal, double, float, numeric, realdouble
    boolean, bitboolean
    char, blob, longvarchar, longnvarchar, nchar, nclob, nvarchar,\n varchar, sqlxml, date, time, timestampstring
    binary, blob, longvarbinary, varbinary, array, datalink,\n java_object, other, refbase64Binary
    \n

    \n

    \n If the value of a column is null, it is mapped to the JSONiq null value.\n

    \n

    Connecting to a JDBC source requires the following options:\n

      \n
    • url: the JDBC connection URI (mandatory)
    • \n
    • user: the user used for connecting (optional)
    • \n
    • password: the password used for connecting (optional)
    • \n

    \n

    Examples:\n

      \n
    • \n {\n   \"url\" : \"jdbc:mysql://localhost/testdb\",\n   \"user\" : \"root\",\n   \"password\" : \"\"\n }
    • \n
    • \n {\n   \"url\" : \"jdbc:sqlserver://192.168.1.1;databaseName=testdb\",\n   \"user\" : \"sa\",\n   \"password\" : \"\"\n }
    • \n
    • \n {\n   \"url\" : \"jdbc:postgresql://localhost/testdb\",\n   \"user\" : \"root\",\n   \"password\" : \"\"\n }
    • \n

    \n

    Currently, the 28.io platform supports connections to\n

      \n
    • MySQL using the mariadb-java-client.jar version 1.1.2,
    • \n
    • PostgreSQL using postgresql.jar version 9.2, and
    • \n
    • Microsoft SQL Server using sqljdbc4.jar version 4.0.
    • \n
    \n

    \n

    If you are interested in connecting to other JDBC datasources,\n please contact us at support@28.io.

    \n

    Important Notice Regarding Function Determinism

    \n

    The non side-effecting functions:\n

    \n are declared deterministic, which means that their results could be cached\n when invoked multiple times with the same arguments in the same query execution.

    \n

    To not use cached results you can use the following alternative functions:\n

    \n which have been declared as being non deterministic.

    \n", "sees" : [ ], "authors" : [ "Cristi Dumitru", "Federico Cavalieri" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://www.28msec.com/modules/jdbc", "prefix" : "jdbc" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://www.zorba-xquery.com/modules/jdbc", "prefix" : "zjdbc" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "affected-rows", "qname" : "jdbc:affected-rows", "signature" : "($dataset as anyURI) as integer", "description" : " Return the number of affected rows of an updating DataSet.\n", "summary" : "

    Return the number of affected rows of an updating DataSet.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "dataset", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the DataSet.
    " } ], "returns" : { "type" : "integer", "description" : "the number of affected rows." }, "errors" : [ "SQL008 DataSet doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "clear-params", "qname" : "jdbc:clear-params", "signature" : "($prepared-statement as anyURI) as empty-sequence()", "description" : " Clear all the parameters of the statement.\n", "summary" : "

    Clear all the parameters of the statement.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the prepared statement.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "an empty-sequence()" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "commit", "qname" : "jdbc:commit", "signature" : "($conn as anyURI) as empty-sequence()", "description" : " Commit current transaction from an active connection.\n", "summary" : "

    Commit current transaction from an active connection.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the connection with a transaction to be commited.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "an empty-sequence()" }, "errors" : [ "SQL08003 Connection doesn't exist", "SQL08000 Connection is closed", "SQL001 Descriptive error, see error in attached message" ] }, { "isDocumented" : true, "arity" : 0, "name" : "connect-nondeterministic", "qname" : "jdbc:connect-nondeterministic", "signature" : "() as anyURI", "description" : " Open a connection to a database using the default credentials.\n

    This function has the same semantics as\n connect#0,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Open a connection to a database using the default credentials.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "anyURI", "description" : "an identifier that represents the connection to the server." }, "errors" : [ "NOT-FOUND The default credentials not found.", "SQL28000 Authentication failed.", "SQL08001 Connection error.", "SQL40003 Isolation level not supported.", "SQL001 Descriptive error, see attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "connect-nondeterministic", "qname" : "jdbc:connect-nondeterministic", "signature" : "($connection-config as item()) as anyURI", "description" : " Open a connection to a database.\n

    This function has the same semantics as\n connect#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Open a connection to a database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-config", "type" : "item()", "occurrence" : null, "description" : "
    object containing the configuration information.
    " } ], "returns" : { "type" : "anyURI", "description" : "an identifier that represents the connection to the server." }, "errors" : [ "NOT-FOUND The specified credentials have not been found.", "NOT-VALID Invalid connection information.", "SQL28000 Authentication failed.", "SQL08001 Connection error.", "SQL40003 Isolation level not supported.", "SQL001 Descriptive error, see attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "connect-nondeterministic", "qname" : "jdbc:connect-nondeterministic", "signature" : "($connection-config as item(), $options as object()?) as anyURI", "description" : " Open a connection to a database.\n

    This function has the same semantics as\n connect#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Open a connection to a database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-config", "type" : "item()", "occurrence" : null, "description" : "
    object containing the configuration information.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    object to specify additional connection options.
    " } ], "returns" : { "type" : "anyURI", "description" : "an identifier that represents the connection to the server." }, "errors" : [ "NOT-FOUND The specified credentials have not been found.", "NOT-VALID Invalid connection information.", "SQL28000 Authentication failed.", "SQL08001 Connection error.", "SQL40003 Isolation level not supported.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 0, "name" : "connect", "qname" : "jdbc:connect", "signature" : "() as anyURI", "description" : " Open a connection to a database using the default credentials.\n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The function returns an opaque URI that can represents the connection.\n This URI has to be passed to other functions of this module that require\n the $conn parameter as a first argument.

    \n", "summary" : "

    Open a connection to a database using the default credentials.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "anyURI", "description" : "an identifier that represents the connection to the server." }, "errors" : [ "NOT-FOUND The default credentials not found.", "SQL28000 Authentication failed.", "SQL08001 Connection error.", "SQL40003 Isolation level not supported.", "SQL001 Descriptive error, see attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "connect", "qname" : "jdbc:connect", "signature" : "($connection-config as item()) as anyURI", "description" : " Open a connection to a database.\n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The input to the function contains the connection information.\n If a string is used, then the function will interpret it as credential name\n and will connect using the JDBC credentials with the specified name.\n If an object is used, then the function will open a connection using it.\n The object's required structure is described in the module's description.

    \n

    The function returns an opaque URI that can represents the connection.\n This URI has to be passed to other functions of this module that require\n the $conn parameter as a first argument.

    \n", "summary" : "

    Open a connection to a database.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection-config", "type" : "item()", "occurrence" : null, "description" : "
    object containing the configuration information.
    " } ], "returns" : { "type" : "anyURI", "description" : "an identifier that represents the connection to the server." }, "errors" : [ "NOT-FOUND The specified credentials have not been found.", "NOT-VALID Invalid connection information.", "SQL28000 Authentication failed.", "SQL08001 Connection error.", "SQL40003 Isolation level not supported.", "SQL001 Descriptive error, see attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "connect", "qname" : "jdbc:connect", "signature" : "($connection-config as item(), $options as object()?) as anyURI", "description" : " Open a connection to a database.\n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    The input to the function contains the connection information.\n If a string is used, then the function will interpret it as credential name\n and will connect using the JDBC credentials with the specified name.\n If an object is used, then the function will open a connection using it.\n The object's required structure is described in the module's description.

    \n

    In addition to the connection configuration, the function allows to\n specify several options:\n

      \n
    • autocommit: true/false turn on/off auto commit\n (default: true)
    • \n
    • readonly: true/false configure readonly/write on this\n connection (default: false)
    • \n
    • isolation-level: configure the isolation level for this connection\n
        \n
      • READ-COMMITTED: set the isolation level read-committed
      • \n
      • READ-UNCOMMITTED: set the isolation level read-uncommitted
      • \n
      • READ-REPEATABLE: set the isolation level repeatable-read
      • \n
      • SERIALIZABLE: set the isolation level serializable
      • \n
      \n If no isolation level is provided by the user the connection will be created\n with the default isolation level of the database.
    • \n

    \n

    The function returns an opaque URI that represents the connection.\n This URI has to be passed to other functions of this module that require\n the $conn parameter as a first argument.

    \n", "summary" : "

    Open a connection to a database.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection-config", "type" : "item()", "occurrence" : null, "description" : "
    object containing the configuration information.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    object to specify additional connection options.
    " } ], "returns" : { "type" : "anyURI", "description" : "an identifier that represents the connection to the server." }, "errors" : [ "NOT-FOUND The specified credentials have not been found.", "NOT-VALID Invalid connection information.", "SQL28000 Authentication failed.", "SQL08001 Connection error.", "SQL40003 Isolation level not supported.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "connection-options", "qname" : "jdbc:connection-options", "signature" : "($conn as anyURI) as object()", "description" : " Return a set with options for a specified connection.\n The returned options are equal to the options specified in function jdbc:connect.\n Consequently, the options are specified as follows:\n
      \n
    • autocommit: true/false shows auto commit
    • \n
    • readonly: true/false shows if the connection is readonly/write
    • \n
    • isolation-level: shows the isolation level for this connection\n
        \n
      • READ-COMMITTED: isolation level is read-committed
      • \n
      • READ-UNCOMMITTED: isolation level is read-uncommitted
      • \n
      • READ-REPEATABLE: isolation level is repeatable-read
      • \n
      • SERIALIZABLE: isolation level is serializable
      • \n
    • \n
    \n", "summary" : "

    Return a set with options for a specified connection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the connection.
    " } ], "returns" : { "type" : "object()", "description" : "an object with the connection options." }, "errors" : [ "SQL08003 Connection doesn't exist", "SQL08000 Connection is closed", "SQL001 Descriptive error, see error in attached message" ] }, { "isDocumented" : true, "arity" : 1, "name" : "execute-prepared", "qname" : "jdbc:execute-prepared", "signature" : "($prepared-statement as anyURI) as anyURI", "description" : " Execute SQL statements prepared with jdbc:prepare-statement,\n after setting the parameters values accordingly and returns an identifier to\n a Dataset.\n", "summary" : "

    Execute SQL statements prepared with jdbc:prepare-statement,\n after setting the parameters values accordingly and returns an identifier to\n a Dataset.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the prepared statement.
    " } ], "returns" : { "type" : "anyURI", "description" : "the identifier of a DataSet." }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "execute-query-nondeterministic", "qname" : "jdbc:execute-query-nondeterministic", "signature" : "($conn as anyURI, $sql as string) as object()*", "description" : " Execute non-updating SQL statements.\n

    This function has the same semantics as\n execute-query#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Execute non-updating SQL statements.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection.
    " }, { "name" : "sql", "type" : "string", "occurrence" : null, "description" : "
    The query string to be executed.
    " } ], "returns" : { "type" : "object()*", "description" : "an object with the result data rows from the query provided." }, "errors" : [ "SQL08003 Connection doesn't exist.", "SQL08000 Connection is closed.", "SQL005 The statement is Updating type.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "execute-query-prepared-nondeterministic", "qname" : "jdbc:execute-query-prepared-nondeterministic", "signature" : "($prepared-statement as anyURI) as object()*", "description" : " Execute non-updating SQL statements prepared with jdbc:prepare-statement,\n after setting the parameters values accordingly.\n

    This function has the same semantics as\n execute-query-prepared#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Execute non-updating SQL statements prepared with jdbc:prepare-statement,\n after setting the parameters values accordingly.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the prepared statement.
    " } ], "returns" : { "type" : "object()*", "description" : "an object with the result data rows from the query processed with the parameters provided." }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL005 The prepared statement is an updating query.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "execute-query-prepared", "qname" : "jdbc:execute-query-prepared", "signature" : "($prepared-statement as anyURI) as object()*", "description" : " Execute non-updating SQL statements prepared with jdbc:prepare-statement,\n after setting the parameters values accordingly.\n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Every row is represented by an object of column-value representation, as\n in the module description.

    \n", "summary" : "

    Execute non-updating SQL statements prepared with jdbc:prepare-statement,\n after setting the parameters values accordingly.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the prepared statement.
    " } ], "returns" : { "type" : "object()*", "description" : "an object with the result data rows from the query processed with the parameters provided." }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL005 The prepared statement is an updating query.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "execute-query", "qname" : "jdbc:execute-query", "signature" : "($conn as anyURI, $sql as string) as object()*", "description" : " Execute non-updating SQL statements.\n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Every row is represented by an object of column-value representation, as in\n the module description.

    \n", "summary" : "

    Execute non-updating SQL statements.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection.
    " }, { "name" : "sql", "type" : "string", "occurrence" : null, "description" : "
    The query string to be executed.
    " } ], "returns" : { "type" : "object()*", "description" : "an object with the result data rows from the query provided." }, "errors" : [ "SQL08003 Connection doesn't exist.", "SQL08000 Connection is closed.", "SQL005 The statement is Updating type.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "execute-update-prepared", "qname" : "jdbc:execute-update-prepared", "signature" : "($prepared-statement as anyURI) as integer", "description" : " Execute updating SQL statements prepared with jdbc:prepare-statement.\n", "summary" : "

    Execute updating SQL statements prepared with jdbc:prepare-statement.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the prepared statement.
    " } ], "returns" : { "type" : "integer", "description" : "the number of affected rows." }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL006 The prepared statement is a non-updating query.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "execute-update", "qname" : "jdbc:execute-update", "signature" : "($conn as anyURI, $sql as string) as integer", "description" : " Execute updating SQL statements.\n", "summary" : "

    Execute updating SQL statements.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection.
    " }, { "name" : "sql", "type" : "string", "occurrence" : null, "description" : "
    The query string to be executed.
    " } ], "returns" : { "type" : "integer", "description" : "the number of affected rows." }, "errors" : [ "SQL08003 Connection doesn't exist.", "SQL08000 Connection is closed.", "SQL005 The statement is Read-only type.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "execute", "qname" : "jdbc:execute", "signature" : "($conn as anyURI, $sql as string) as anyURI", "description" : " Execute any kind of SQL statement.\n", "summary" : "

    Execute any kind of SQL statement.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection.
    " }, { "name" : "sql", "type" : "string", "occurrence" : null, "description" : "
    The query string to be executed.
    " } ], "returns" : { "type" : "anyURI", "description" : "an identifier of a DataSet." }, "errors" : [ "SQL08003 Connection doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-connected", "qname" : "jdbc:is-connected", "signature" : "($conn as anyURI) as boolean", "description" : " Verify if a connection is still active.\n", "summary" : "

    Verify if a connection is still active.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the connection to be verified.
    " } ], "returns" : { "type" : "boolean", "description" : "true if connected, false otherwise" }, "errors" : [ "SQL08003 Connection doesn't exist", "SQL001 Descriptive error, see error in attached message" ] }, { "isDocumented" : true, "arity" : 1, "name" : "metadata", "qname" : "jdbc:metadata", "signature" : "($dataset as anyURI) as object()", "description" : " Return the metadata of the result of a DataSet.\n

    \n More in detail, it returns information about column names, types, and whether\n a column can contain a null value.\n The metadata information can only be returned for DataSets that have been\n executed explicitly using the jdbc:execute function.\n The metadata node returned has the following structure:\n

    {\n   \"columns\": [ {\n       \"name\": string,\n       \"type\": string,\n       \"autoincrement\"? = boolean,\n       \"nillable\"? = boolean } * ]\n }
    \n

    \n

    \n If the query is an updating query, then the result object will return the\n number of affected rows like:\n

    { \"affectedrows\": integer }
    \n

    \n", "summary" : "

    Return the metadata of the result of a DataSet.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "dataset", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the DataSet.
    " } ], "returns" : { "type" : "object()", "description" : "the metadata associated with an executed DataSet." }, "errors" : [ "SQL008 DataSet doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "parameter-metadata", "qname" : "jdbc:parameter-metadata", "signature" : "($prepared-statement as anyURI) as object()", "description" : " Retrieve the names and types of the prepared statement parameters.\n The metadata returned has the following structure:\n
      {\n     columns: [{\n       \"name\": string,\n       \"type\": string\n       }]\n   } 
    \n", "summary" : "

    Retrieve the names and types of the prepared statement parameters.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the prepared statement.
    " } ], "returns" : { "type" : "object()", "description" : "parameters metadata (name and type) associated with a prepared statement." }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "prepare-statement", "qname" : "jdbc:prepare-statement", "signature" : "($conn as anyURI, $sql as string) as anyURI", "description" : " Create a prepared statement for multiple executions with diferent parameters.\n Example:\n
    \n jdbc:prepare-statement($connection, \"SELECT * FROM users WHERE id=? AND age>?\")\n 
    \n", "summary" : "

    Create a prepared statement for multiple executions with diferent parameters.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the active connection.
    " }, { "name" : "sql", "type" : "string", "occurrence" : null, "description" : "
    The query string to be executed.
    " } ], "returns" : { "type" : "anyURI", "description" : "the identifier of the prepared statement." }, "errors" : [ "SQL08003 Connection doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "result-set", "qname" : "jdbc:result-set", "signature" : "($dataset as anyURI) as object()*", "description" : " Extract the data rows from a non-updating DataSet.\n Every row is represented by an object of column-value representation, as in\n the module description.\n", "summary" : "

    Extract the data rows from a non-updating DataSet.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "dataset", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the DataSet.
    " } ], "returns" : { "type" : "object()*", "description" : "an object with the result data rows from the DataSet provided." }, "errors" : [ "SQL008 DataSet doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "rollback", "qname" : "jdbc:rollback", "signature" : "($conn as anyURI) as empty-sequence()", "description" : " Rollback the current transaction of a connection.\n", "summary" : "

    Rollback the current transaction of a connection.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the connection with a transaction to be rollbacked.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "an empty-sequence()" }, "errors" : [ "SQL08003 Connection doesn't exist", "SQL08000 Connection is closed", "SQL001 Descriptive error, see error in attached message" ] }, { "isDocumented" : true, "arity" : 3, "name" : "set-boolean", "qname" : "jdbc:set-boolean", "signature" : "($prepared-statement as anyURI, $parameter-index as integer, $value as boolean) as empty-sequence()", "description" : " Set the value of the designated parameter with a boolean value.\n", "summary" : "

    Set the value of the designated parameter with a boolean value.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the prepared statement.
    " }, { "name" : "parameter-index", "type" : "integer", "occurrence" : null, "description" : "
    The index from the parameter to be set.
    " }, { "name" : "value", "type" : "boolean", "occurrence" : null, "description" : "
    The value to be set.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "an empty-sequence()" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL007 Parameter casting error.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "set-null", "qname" : "jdbc:set-null", "signature" : "($prepared-statement as anyURI, $parameter-index as integer) as empty-sequence()", "description" : " Set the value of the designated parameter with a NULL value.\n", "summary" : "

    Set the value of the designated parameter with a NULL value.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the prepared statement.
    " }, { "name" : "parameter-index", "type" : "integer", "occurrence" : null, "description" : "
    The index from the parameter to be set.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "an empty-sequence()" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL007 Parameter casting error.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 3, "name" : "set-numeric", "qname" : "jdbc:set-numeric", "signature" : "($prepared-statement as anyURI, $parameter-index as decimal, $value as anyAtomicType) as empty-sequence()", "description" : " Set the value of the designated parameter with a numeric value.\n", "summary" : "

    Set the value of the designated parameter with a numeric value.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the prepared statement.
    " }, { "name" : "parameter-index", "type" : "decimal", "occurrence" : null, "description" : "
    The index from the parameter to be set.
    " }, { "name" : "value", "type" : "anyAtomicType", "occurrence" : null, "description" : "
    The value to be set.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "an empty-sequence()" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL007 Parameter casting error.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 3, "name" : "set-string", "qname" : "jdbc:set-string", "signature" : "($prepared-statement as anyURI, $parameter-index as integer, $value as string) as empty-sequence()", "description" : " Set the value of the designated parameter with a string value.\n", "summary" : "

    Set the value of the designated parameter with a string value.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the prepared statement.
    " }, { "name" : "parameter-index", "type" : "integer", "occurrence" : null, "description" : "
    The index from the parameter to be set.
    " }, { "name" : "value", "type" : "string", "occurrence" : null, "description" : "
    The value to be set.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "an empty-sequence()" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL007 Parameter casting error.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 3, "name" : "set-value", "qname" : "jdbc:set-value", "signature" : "($prepared-statement as anyURI, $parameter-index as decimal, $value as anyAtomicType) as empty-sequence()", "description" : " Set the value of the designated parameter with the given value.\n The function will try to cast the value to the correct data type and assign\n it to the parameter.\n", "summary" : "

    Set the value of the designated parameter with the given value.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier of the prepared statement.
    " }, { "name" : "parameter-index", "type" : "decimal", "occurrence" : null, "description" : "
    The index from the parameter to be set.
    " }, { "name" : "value", "type" : "anyAtomicType", "occurrence" : null, "description" : "
    The value to be set.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "an empty-sequence()" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL007 Parameter casting error.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "tables-nondeterministic", "qname" : "jdbc:tables-nondeterministic", "signature" : "($conn as anyURI) as object()*", "description" : " Return the list of tables from a connection.\n

    This function has the same semantics as\n tables#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Return the list of tables from a connection.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier to a connection.
    " } ], "returns" : { "type" : "object()*", "description" : "Return an object with the result data rows from the query provided, the data rows are defined as follows: { column:value* }* Every row is represented by an object of column-value representation of the returned SQL result." }, "errors" : [ "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 4, "name" : "tables-nondeterministic", "qname" : "jdbc:tables-nondeterministic", "signature" : "($conn as anyURI, $catalog as string?, $schema as string?, $table as string?) as object()*", "description" : " Return the list of tables from a connection.\n

    This function has the same semantics as tables#4,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Return the list of tables from a connection.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier to a connection.
    " }, { "name" : "catalog", "type" : "string", "occurrence" : "?", "description" : "
    A filter of the catalog name of the tables. Send empty-sequence for all tables.
    " }, { "name" : "schema", "type" : "string", "occurrence" : "?", "description" : "
    A filter of the schema name of the tables. Send empty-sequence for all tables.
    " }, { "name" : "table", "type" : "string", "occurrence" : "?", "description" : "
    A filter of the name of the tables. Send empty-sequence for all tables.
    " } ], "returns" : { "type" : "object()*", "description" : "Return an object with the result data rows from the query provided, the data rows are defined as follows: { column:value* }* Every row is represented by an object of column-value representation of the returned SQL result." }, "errors" : [ "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "tables", "qname" : "jdbc:tables", "signature" : "($conn as anyURI) as object()*", "description" : " Return the list of tables from a connection.\n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Return the list of tables from a connection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier to a connection.
    " } ], "returns" : { "type" : "object()*", "description" : "Return an object with the result data rows from the query provided, the data rows are defined as follows: { column:value* }* Every row is represented by an object of column-value representation of the returned SQL result." }, "errors" : [ "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 4, "name" : "tables", "qname" : "jdbc:tables", "signature" : "($conn as anyURI, $catalog as string?, $schema as string?, $table as string?) as object()*", "description" : " Return the list of tables from a connection.\n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Return the list of tables from a connection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "conn", "type" : "anyURI", "occurrence" : null, "description" : "
    The identifier to a connection.
    " }, { "name" : "catalog", "type" : "string", "occurrence" : "?", "description" : "
    A filter of the catalog name of the tables. Send empty-sequence for all tables.
    " }, { "name" : "schema", "type" : "string", "occurrence" : "?", "description" : "
    A filter of the schema name of the tables. Send empty-sequence for all tables.
    " }, { "name" : "table", "type" : "string", "occurrence" : "?", "description" : "
    A filter of the name of the tables. Send empty-sequence for all tables.
    " } ], "returns" : { "type" : "object()*", "description" : "Return an object with the result data rows from the query provided, the data rows are defined as follows: { column:value* }* Every row is represented by an object of column-value representation of the returned SQL result." }, "errors" : [ "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] } ], "variables" : [ { "name" : "jdbc:READ-COMMITTED", "type" : "item()*", "description" : " This variable represents the READ-COMMITTED Isolation Level.\n" }, { "name" : "jdbc:READ-UNCOMMITTED", "type" : "item()*", "description" : " This variable represents the READ-UNCOMMITTED Isolation Level.\n" }, { "name" : "jdbc:REPEATABLE-READ", "type" : "item()*", "description" : " This variable represents the REPEATABLE-READ Isolation Levels.\n" }, { "name" : "jdbc:SERIALIZABLE", "type" : "item()*", "description" : " This variable represents the SERIALIZABLE Isolation Levels.\n" }, { "name" : "jdbc:CREDENTIALS-CATEGORY", "type" : "item()*", "description" : " This variable represents the category for the credentials used.\n" } ] }, "http://zorba.io/modules/full-text" : { "ns" : "http://zorba.io/modules/full-text", "description" : " This module provides an XQuery API to full-text functions.\n For general information about this implementation of the\n XQuery and XPath Full Text 1.0 specification\n as well as instructions for building an installing a thesaurus,\n see the Full Text Thesaurus documentation.\n

    Notes on languages

    \n To refer to particular human languages,\n uses either the\n ISO 639-1\n or\n ISO 639-2\n languages codes.\n Note that only a subset of the\n complete list of language codes\n are supported and not every function supports the same subset.\n

    \n Most functions in this module take a language as a parameter\n using the\n xs:language\n XML schema data type.\n

    Notes on stemming

    \n The stem() functions return the\n stem\n of a word.\n The stem of a word itself, however, is not guaranteed to be a word.\n It is best to consider a stem as an opaque byte sequence.\n All that is guaranteed about a stem is that,\n for a given word,\n the stem of that word will always be the same byte sequence.\n Hence,\n you should never compare the result of one of the stem()\n functions against a non-stemmed string,\n for example:\n
    \n  if ( ft:stem( \"apples\" ) eq \"apple\" )             ** WRONG **\n 
    \n Instead do:\n
    \n  if ( ft:stem( \"apples\" ) eq ft:stem( \"apple\" ) )  ** CORRECT **\n 
    \n

    Notes on the thesaurus

    \n The thesaurus-lookup() functions have \"levels\"\n and \"relationship\" parameters.\n The values for these are implementation-defined.\n The default implementation uses the\n WordNet lexical database,\n version 3.0.\n

    \n In WordNet,\n the number of \"levels\" that two phrases are apart\n are how many hierarchical meanings apart they are.\n For example,\n \"canary\" is 5 levels away from \"vertebrate\"\n (carary > finch > oscine > passerine > bird > vertebrate).\n

    \n When using the WordNet implementation,\n all of the relationships (and their abbreviations)\n specified by\n ISO 2788\n and\n ANSI/NISO Z39.19-2005\n with the exceptions of \"HN\" (history note)\n and \"X SN\" (see scope note for) are supported.\n These relationships are:\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    Rel.MeaningWordNet Rel.
    BTbroader termhypernym
    BTGbroader term generichypernym
    BTIbroader term instanceinstance hypernym
    BTPbroader term partitivepart meronym
    NTnarrower termhyponym
    NTGnarrower term generichyponym
    NTInarrower term instanceinstance hyponym
    NTPnarrower term partitivepart holonym
    RTrelated termalso see
    SNscope noten/a
    TTtop termhypernym
    UFnon-preferred termn/a
    USEpreferred termn/a
    \n Note that you can specify relationships\n either by their abbreviation\n or their meaning.\n Relationships are case-insensitive.\n In addition to the\n ISO 2788\n and\n ANSI/NISO Z39.19-2005\n relationships,\n All of the relationships offered by WordNet are also supported.\n These relationships are:\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    RelationshipMeaning
    also see\n A word that is related to another,\n e.g., for \"varnished\" (furniture)\n one should also see \"finished.\"\n
    antonym\n A word opposite in meaning to another,\n e.g., \"light\" is an antonym for \"heavy.\"\n
    attribute\n A noun for which adjectives express values,\n e.g., \"weight\" is an attribute\n for which the adjectives \"light\" and \"heavy\"\n express values.\n
    cause\n A verb that causes another,\n e.g., \"show\" is a cause of \"see.\"\n
    derivationally related form\n A word that is derived from a root word,\n e.g., \"metric\" is a derivationally related form of \"meter.\"\n
    derived from adjective\n An adverb that is derived from an adjective,\n e.g., \"correctly\" is derived from the adjective \"correct.\"\n
    entailment\n A verb that presupposes another,\n e.g., \"snoring\" entails \"sleeping.\"\n
    hypernym\n A word with a broad meaning that more specific words fall under,\n e.g., \"meal\" is a hypernym of \"breakfast.\"\n
    hyponym\n A word of more specific meaning than a general term applicable to it,\n e.g., \"breakfast\" is a hyponym of \"meal.\"\n
    instance hypernym\n A word that denotes a category of some specific instance,\n e.g., \"author\" is an instance hypernym of \"Asimov.\"\n
    instance hyponym\n A term that donotes a specific instance of some general category,\n e.g., \"Asimov\" is an instance hyponym of \"author.\"\n
    member holonym\n A word that denotes a collection of individuals,\n e.g., \"faculty\" is a member holonym of \"professor.\"\n
    member meronym\n A word that denotes a member of a larger group,\n e.g., a \"person\" is a member meronym of a \"crowd.\"\n
    part holonym\n A word that denotes a larger whole comprised of some part,\n e.g., \"car\" is a part holonym of \"engine.\"\n
    part meronym\n A word that denotes a part of a larger whole,\n e.g., an \"engine\" is part meronym of a \"car.\"\n
    participle of verb\n An adjective that is the participle of some verb,\n e.g., \"breaking\" is the participle of the verb \"break.\"\n
    pertainym\n An adjective that classifies its noun,\n e.g., \"musical\" is a pertainym in \"musical instrument.\"\n
    similar to\n Similar, though not necessarily interchangeable, adjectives.\n For example, \"shiny\" is similar to \"bright\",\n but they have subtle differences.\n
    substance holonym\n A word that denotes a larger whole containing some constituent\n substance, e.g., \"bread\" is a substance holonym of \"flour.\"\n
    substance meronym\n A word that denotes a constituant substance of some larger whole,\n e.g., \"flour\" is a substance meronym of \"bread.\"\n
    verb group\n A verb that is a member of a group of similar verbs,\n e.g., \"live\" is in the verb group\n of \"dwell\", \"live\", \"inhabit\", etc.\n
    \n

    Notes on tokenization

    \n For general information about the implementation of tokenization,\n including what constitutes a token,\n see the Full Text Tokenizer documentation.\n", "sees" : [ ], "authors" : [ "Paul J. Lucas" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://zorba.io/modules/full-text", "prefix" : "ft" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" }, { "uri" : "http://zorba.io/errors", "prefix" : "zerr" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "current-compare-options", "qname" : "ft:current-compare-options", "signature" : "() as object() external", "description" : " Gets the current compare options.\n", "summary" : "

    Gets the current compare options.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "said compare options." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "current-lang", "qname" : "ft:current-lang", "signature" : "() as xs:language external", "description" : " Gets the current\n language:\n either the language specified by the\n declare ft-option using\n language\n statement (if any)\n or the one returned by ft:host-lang() (if none).\n", "summary" : "

    Gets the current\n language :\n either the language specified by the\n declare ft-option using \n language \n statement (if any)\n or the one returned by ft:host-lang() (if none).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:language", "description" : "said language." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "host-lang", "qname" : "ft:host-lang", "signature" : "() as xs:language external", "description" : " Gets the host's current\n language.\n The \"host\" is the computer on which the software is running.\n The host's current language is obtained as follows:\n
      \n
    • \n For *nix systems:\n
        \n
      1. \n If setlocale(3) returns non-null,\n the language corresponding to that locale is used.\n
      2. \n
      3. \n Else, if the LANG environment variable is set,\n that language is ued.\n
      4. \n
      5. \n Otherwise, there is no default language.\n
      6. \n
      \n
    • \n
    • \n For Windows systems,\n the language corresponding to the locale returned by the\n GetLocaleInfo()\n function is used.\n
    • \n
    \n", "summary" : "

    Gets the host's current\n language .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:language", "description" : "said language." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-stem-lang-supported", "qname" : "ft:is-stem-lang-supported", "signature" : "($lang as xs:language) as xs:boolean external", "description" : " Checks whether the given\n language\n is supported for stemming.\n", "summary" : "

    Checks whether the given\n language \n is supported for stemming.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The language to check.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true only if the language is supported." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-stop-word-lang-supported", "qname" : "ft:is-stop-word-lang-supported", "signature" : "($lang as xs:language) as xs:boolean external", "description" : " Checks whether the given\n language\n is supported for stop words.\n", "summary" : "

    Checks whether the given\n language \n is supported for stop words.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The language to check.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true only if the language is supported." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-stop-word", "qname" : "ft:is-stop-word", "signature" : "($word as xs:string) as xs:boolean external", "description" : " Checks whether the given word is a stop-word.\n", "summary" : "

    Checks whether the given word is a stop-word.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "word", "type" : "xs:string", "occurrence" : null, "description" : "
    The word to check. The word's language is assumed to be the one returned by ft:current-lang().
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true only if $word is a stop-word." }, "errors" : [ "err:FTST0009 if ft:current-lang() is not supported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "is-stop-word", "qname" : "ft:is-stop-word", "signature" : "($word as xs:string, $lang as xs:language) as xs:boolean external", "description" : " Checks whether the given word is a stop-word.\n", "summary" : "

    Checks whether the given word is a stop-word.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "word", "type" : "xs:string", "occurrence" : null, "description" : "
    The word to check.
    " }, { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The language of $word.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true only if $word is a stop-word." }, "errors" : [ "err:FTST0009 if $lang is not supported." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-thesaurus-lang-supported", "qname" : "ft:is-thesaurus-lang-supported", "signature" : "($lang as xs:language) as xs:boolean external", "description" : " Checks whether the given\n language\n is supported for look-up using the default thesaurus.\n", "summary" : "

    Checks whether the given\n language \n is supported for look-up using the default thesaurus.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The language to check.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true only if the language is supported." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "is-thesaurus-lang-supported", "qname" : "ft:is-thesaurus-lang-supported", "signature" : "($uri as xs:string, $lang as xs:language) as xs:boolean external", "description" : " Checks whether the given\n language\n is supported for look-up using the thesaurus specified by the given URI.\n", "summary" : "

    Checks whether the given\n language \n is supported for look-up using the thesaurus specified by the given URI.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    The URI specifying the thesaurus to use.
    " }, { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The language to check.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true only if the language is supported." }, "errors" : [ "err:FTST0018 if $uri refers to a thesaurus that is not found in the statically known thesauri." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-tokenizer-lang-supported", "qname" : "ft:is-tokenizer-lang-supported", "signature" : "($lang as xs:language) as xs:boolean external", "description" : " Checks whether the given\n language\n is supported for tokenization.\n", "summary" : "

    Checks whether the given\n language \n is supported for tokenization.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The language to check.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true only if the language is supported." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "stem", "qname" : "ft:stem", "signature" : "($word as xs:string) as xs:string external", "description" : " Stems the given word.\n", "summary" : "

    Stems the given word.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "word", "type" : "xs:string", "occurrence" : null, "description" : "
    The word to stem. The word's language is assumed to be the one returned by ft:current-lang().
    " } ], "returns" : { "type" : "xs:string", "description" : "the stem of $word." }, "errors" : [ "err:FTST0009 if ft:current-lang() is not supported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "stem", "qname" : "ft:stem", "signature" : "($word as xs:string, $lang as xs:language) as xs:string external", "description" : " Stems the given word.\n", "summary" : "

    Stems the given word.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "word", "type" : "xs:string", "occurrence" : null, "description" : "
    The word to stem.
    " }, { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The language of $word.
    " } ], "returns" : { "type" : "xs:string", "description" : "the stem of $word." }, "errors" : [ "err:FTST0009 if $lang is not supported." ] }, { "isDocumented" : true, "arity" : 1, "name" : "strip-diacritics", "qname" : "ft:strip-diacritics", "signature" : "($string as xs:string) as xs:string external", "description" : " Strips all diacritical marks from all characters.\n", "summary" : "

    Strips all diacritical marks from all characters.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "string", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to strip diacritical marks from.
    " } ], "returns" : { "type" : "xs:string", "description" : "$string with diacritical marks stripped." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "thesaurus-lookup", "qname" : "ft:thesaurus-lookup", "signature" : "($phrase as xs:string) as xs:string* external", "description" : " Looks-up the given phrase in the default thesaurus.\n", "summary" : "

    Looks-up the given phrase in the default thesaurus.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "phrase", "type" : "xs:string", "occurrence" : null, "description" : "
    The phrase to look up. The phrase's language is assumed to be the one returned by ft:current-lang().
    " } ], "returns" : { "type" : "xs:string*", "description" : "the related phrases if $phrase is found in the thesaurus or the empty sequence if not." }, "errors" : [ "err:FTST0009 if ft:current-lang() is not supported.", "zerr:ZXQP8401 if the thesaurus data file's version is not supported by the currently running version of the software.", "zerr:ZXQP8402 if the thesaurus data file's endianness does not match that of the CPU on which the software is currently running.", "zerr:ZXQP8403 if there was an error reading the thesaurus data." ] }, { "isDocumented" : true, "arity" : 2, "name" : "thesaurus-lookup", "qname" : "ft:thesaurus-lookup", "signature" : "($uri as xs:string, $phrase as xs:string) as xs:string* external", "description" : " Looks-up the given phrase in a thesaurus.\n", "summary" : "

    Looks-up the given phrase in a thesaurus.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    The URI specifying the thesaurus to use.
    " }, { "name" : "phrase", "type" : "xs:string", "occurrence" : null, "description" : "
    The phrase to look up. The phrase's language is assumed to be the one the one returned by ft:current-lang().
    " } ], "returns" : { "type" : "xs:string*", "description" : "the related phrases if $phrase is found in the thesaurus or the empty sequence if not." }, "errors" : [ "err:FTST0009 if ft:current-lang() is unsupported.", "err:FTST0018 if $uri refers to a thesaurus that is not found in the statically known thesauri.", "zerr:ZOSE0001 if the thesaurus data file could not be found.", "zerr:ZOSE0002 if the thesaurus data file is not a plain file.", "zerr:ZXQP8401 if the thesaurus data file's version is not supported by the currently running version of the software.", "zerr:ZXQP8402 if the thesaurus data file's endianness does not match that of the CPU on which the software is currently running.", "zerr:ZXQP8403 if there was an error reading the thesaurus data file." ] }, { "isDocumented" : true, "arity" : 3, "name" : "thesaurus-lookup", "qname" : "ft:thesaurus-lookup", "signature" : "($uri as xs:string, $phrase as xs:string, $lang as xs:language) as xs:string* external", "description" : " Looks-up the given phrase in the thesaurus specified by the given URI.\n", "summary" : "

    Looks-up the given phrase in the thesaurus specified by the given URI.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    The URI specifying the thesaurus to use.
    " }, { "name" : "phrase", "type" : "xs:string", "occurrence" : null, "description" : "
    The phrase to look up.
    " }, { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The language of $phrase.
    " } ], "returns" : { "type" : "xs:string*", "description" : "the related phrases if $phrase is found in the thesaurus or the empty sequence if not." }, "errors" : [ "err:FTST0009 if $lang is not supported.", "err:FTST0018 if $uri refers to a thesaurus that is not found in the statically known thesauri.", "zerr:ZOSE0001 if the thesaurus data file could not be found.", "zerr:ZOSE0002 if the thesaurus data file is not a plain file.", "zerr:ZXQP8401 if the thesaurus data file's version is not supported by the currently running version of the software.", "zerr:ZXQP8402 if the thesaurus data file's endianness does not match that of the CPU on which the software is currently running.", "zerr:ZXQP8403 if there was an error reading the thesaurus data file." ] }, { "isDocumented" : true, "arity" : 4, "name" : "thesaurus-lookup", "qname" : "ft:thesaurus-lookup", "signature" : "($uri as xs:string, $phrase as xs:string, $lang as xs:language, $relationship as xs:string) as xs:string* external", "description" : " Looks-up the given phrase in a thesaurus.\n", "summary" : "

    Looks-up the given phrase in a thesaurus.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    The URI specifying the thesaurus to use.
    " }, { "name" : "phrase", "type" : "xs:string", "occurrence" : null, "description" : "
    The phrase to look up.
    " }, { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The language of $phrase.
    " }, { "name" : "relationship", "type" : "xs:string", "occurrence" : null, "description" : "
    The relationship the results are to have to $phrase.
    " } ], "returns" : { "type" : "xs:string*", "description" : "the related phrases if $phrase is found in the thesaurus or the empty sequence if not." }, "errors" : [ "err:FTST0018 if $uri refers to a thesaurus that is not found in the statically known thesauri.", "err:FTST0009 if $lang is not supported.", "zerr:ZOSE0001 if the thesaurus data file could not be found.", "zerr:ZOSE0002 if the thesaurus data file is not a plain file.", "zerr:ZXQP8401 if the thesaurus data file's version is not supported by the currently running version of the software.", "zerr:ZXQP8402 if the thesaurus data file's endianness does not match that of the CPU on which the software is currently running.", "zerr:ZXQP8403 if there was an error reading the thesaurus data file." ] }, { "isDocumented" : true, "arity" : 6, "name" : "thesaurus-lookup", "qname" : "ft:thesaurus-lookup", "signature" : "($uri as xs:string, $phrase as xs:string, $lang as xs:language, $relationship as xs:string, $level-least as xs:integer, $level-most as xs:integer) as xs:string* external", "description" : " Looks-up the given phrase in a thesaurus.\n", "summary" : "

    Looks-up the given phrase in a thesaurus.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "uri", "type" : "xs:string", "occurrence" : null, "description" : "
    The URI specifying the thesaurus to use.
    " }, { "name" : "phrase", "type" : "xs:string", "occurrence" : null, "description" : "
    The phrase to look up.
    " }, { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The language of $phrase.
    " }, { "name" : "relationship", "type" : "xs:string", "occurrence" : null, "description" : "
    The relationship the results are to have to $phrase.
    " }, { "name" : "level-least", "type" : "xs:integer", "occurrence" : null, "description" : "
    The minimum number of levels within the thesaurus to be traversed.
    " }, { "name" : "level-most", "type" : "xs:integer", "occurrence" : null, "description" : "
    The maximum number of levels within the thesaurus to be traversed.
    " } ], "returns" : { "type" : "xs:string*", "description" : "the related phrases if $phrase is found in the thesaurus or the empty sequence if not." }, "errors" : [ "err:FOCA0003 if either $level-least or $level-most is either negative or too large.", "err:FTST0018 if $uri refers to a thesaurus that is not found in the statically known thesauri.", "err:FTST0009 if $lang is not supported.", "zerr:ZOSE0001 if the thesaurus data file could not be found.", "zerr:ZOSE0002 if the thesaurus data file is not a plain file.", "zerr:ZXQP8401 if the thesaurus data file's version is not supported by the currently running version of the software.", "zerr:ZXQP8402 if the thesaurus data file's endianness does not match that of the CPU on which the software is currently running.", "zerr:ZXQP8403 if there was an error reading the thesaurus data file." ] }, { "isDocumented" : true, "arity" : 1, "name" : "tokenize-node", "qname" : "ft:tokenize-node", "signature" : "($node as node()) as object()* external", "description" : " Tokenizes the given node and all of its descendants.\n", "summary" : "

    Tokenizes the given node and all of its descendants.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : null, "description" : "
    The node to tokenize. The node's default language is assumed to be the one returned by ft:current-lang().
    " } ], "returns" : { "type" : "object()*", "description" : "a (possibly empty) sequence of tokens." }, "errors" : [ "err:FTST0009 if ft:current-lang() is not supported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "tokenize-node", "qname" : "ft:tokenize-node", "signature" : "($node as node(), $lang as xs:language) as object()* external", "description" : " Tokenizes the given node and all of its decendants.\n", "summary" : "

    Tokenizes the given node and all of its decendants.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : null, "description" : "
    The node to tokenize.
    " }, { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The default language of $node.
    " } ], "returns" : { "type" : "object()*", "description" : "a (possibly empty) sequence of tokens." }, "errors" : [ "err:FTST0009 if $lang is not supported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "tokenize-nodes", "qname" : "ft:tokenize-nodes", "signature" : "($includes as node()+, $excludes as node()*) as object()* external", "description" : " Tokenizes the set of nodes comprising $includes (and all of its\n descendants) but excluding $excludes (and all of its\n descendants), if any.\n", "summary" : "

    Tokenizes the set of nodes comprising $includes (and all of its\n descendants) but excluding $excludes (and all of its\n descendants), if any.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "includes", "type" : "node()", "occurrence" : "+", "description" : "
    The set of nodes (and its descendants) to include. The default language is assumed to be the one returned by ft:current-lang().
    " }, { "name" : "excludes", "type" : "node()", "occurrence" : "*", "description" : "
    The set of nodes (and its descendants) to exclude.
    " } ], "returns" : { "type" : "object()*", "description" : "a (possibly empty) sequence of tokens." }, "errors" : [ "err:FTST0009 if ft:current-lang() is not supported." ] }, { "isDocumented" : true, "arity" : 3, "name" : "tokenize-nodes", "qname" : "ft:tokenize-nodes", "signature" : "($includes as node()+, $excludes as node()*, $lang as xs:language) as object()* external", "description" : " Tokenizes the set of nodes comprising $includes (and all of its\n descendants) but excluding $excludes (and all of its\n descendants), if any.\n", "summary" : "

    Tokenizes the set of nodes comprising $includes (and all of its\n descendants) but excluding $excludes (and all of its\n descendants), if any.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "includes", "type" : "node()", "occurrence" : "+", "description" : "
    The set of nodes (and its descendants) to include.
    " }, { "name" : "excludes", "type" : "node()", "occurrence" : "*", "description" : "
    The set of nodes (and its descendants) to exclude.
    " }, { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The default language for nodes.
    " } ], "returns" : { "type" : "object()*", "description" : "a (possibly empty) sequence of tokens." }, "errors" : [ "err:FTST0009 if $lang is not supported." ] }, { "isDocumented" : true, "arity" : 1, "name" : "tokenize-string", "qname" : "ft:tokenize-string", "signature" : "($string as xs:string) as xs:string* external", "description" : " Tokenizes the given string.\n", "summary" : "

    Tokenizes the given string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "string", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to tokenize. The string's language is assumed to be the one returned by ft:current-lang().
    " } ], "returns" : { "type" : "xs:string*", "description" : "a (possibly empty) sequence of tokens." }, "errors" : [ "err:FTST0009 if ft:current-lang() is not supported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "tokenize-string", "qname" : "ft:tokenize-string", "signature" : "($string as xs:string, $lang as xs:language) as xs:string* external", "description" : " Tokenizes the given string.\n", "summary" : "

    Tokenizes the given string.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "string", "type" : "xs:string", "occurrence" : null, "description" : "
    The string to tokenize.
    " }, { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The language of $string.
    " } ], "returns" : { "type" : "xs:string*", "description" : "a (possibly empty) sequence of tokens." }, "errors" : [ "err:FTST0009 if $lang is not supported." ] }, { "isDocumented" : true, "arity" : 0, "name" : "tokenizer-properties", "qname" : "ft:tokenizer-properties", "signature" : "() as object() external", "description" : " Gets properties of the tokenizer for the\n language\n returned by ft:current-lang().\n", "summary" : "

    Gets properties of the tokenizer for the\n language \n returned by ft:current-lang() .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "said properties." }, "errors" : [ "err:FTST0009 if ft:current-lang() is not supported." ] }, { "isDocumented" : true, "arity" : 1, "name" : "tokenizer-properties", "qname" : "ft:tokenizer-properties", "signature" : "($lang as xs:language) as object() external", "description" : " Gets properties of the tokenizer for the given\n language.\n", "summary" : "

    Gets properties of the tokenizer for the given\n language .

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "lang", "type" : "xs:language", "occurrence" : null, "description" : "
    The language of the tokenizer to get the properties of.
    " } ], "returns" : { "type" : "object()", "description" : "said properties." }, "errors" : [ "err:FTST0009 if $lang is not supported. tokenization specifically." ] } ], "variables" : [ { "name" : "ft:LANG-DA", "type" : "xs:language", "description" : " Predeclared constant for the Danish\n xs:language.\n" }, { "name" : "ft:LANG-DE", "type" : "xs:language", "description" : " Predeclared constant for the German\n xs:language.\n" }, { "name" : "ft:LANG-EN", "type" : "xs:language", "description" : " Predeclared constant for the English\n xs:language.\n" }, { "name" : "ft:LANG-ES", "type" : "xs:language", "description" : " Predeclared constant for the Spanish\n xs:language.\n" }, { "name" : "ft:LANG-FI", "type" : "xs:language", "description" : " Predeclared constant for the Finnish\n xs:language.\n" }, { "name" : "ft:LANG-FR", "type" : "xs:language", "description" : " Predeclared constant for the French\n xs:language.\n" }, { "name" : "ft:LANG-HU", "type" : "xs:language", "description" : " Predeclared constant for the Hungarian\n xs:language.\n" }, { "name" : "ft:LANG-IT", "type" : "xs:language", "description" : " Predeclared constant for the Italian\n xs:language.\n" }, { "name" : "ft:LANG-NL", "type" : "xs:language", "description" : " Predeclared constant for the Dutch\n xs:language.\n" }, { "name" : "ft:LANG-NO", "type" : "xs:language", "description" : " Predeclared constant for the Norwegian\n xs:language.\n" }, { "name" : "ft:LANG-PT", "type" : "xs:language", "description" : " Predeclared constant for the Portuguese\n xs:language.\n" }, { "name" : "ft:LANG-RO", "type" : "xs:language", "description" : " Predeclared constant for the Romanian\n xs:language.\n" }, { "name" : "ft:LANG-RU", "type" : "xs:language", "description" : " Predeclared constant for the Russian\n xs:language.\n" }, { "name" : "ft:LANG-SV", "type" : "xs:language", "description" : " Predeclared constant for the Swedish\n xs:language.\n" }, { "name" : "ft:LANG-TR", "type" : "xs:language", "description" : " Predeclared constant for the Turkish\n xs:language.\n" } ] }, "http://www.zorba-xquery.com/modules/jdbc" : { "ns" : "http://www.zorba-xquery.com/modules/jdbc", "description" : " This module contains functions to connect to any JDBC datasource\n using jvm-util module to handle Java interaction.\n

    Important Notice Regarding Function Determinism

    \n

    The non side-effecting functions:\n

    \n are declared deterministic, which means that their results could be cached\n when invoked multiple times with the same arguments in the same query execution.

    \n

    To not use cached results you can use the following alternative functions:\n

    \n which have been declared as being non deterministic.

    \n", "sees" : [ ], "authors" : [ "Rodolfo Ochoa", "Federico Cavalieri" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://www.zorba-xquery.com/modules/jdbc", "prefix" : "jdbc" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "affected-rows", "qname" : "jdbc:affected-rows", "signature" : "($dataset-id as xs:anyURI) as xs:integer external", "description" : " Return the number of affected rows of a particular DataSet.\n", "summary" : "

    Return the number of affected rows of a particular DataSet.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "dataset-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a DataSet.
    " } ], "returns" : { "type" : "xs:integer", "description" : "Returns an xs:integer with the number of affected rows." }, "errors" : [ "SQL008 DataSet doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "clear-params", "qname" : "jdbc:clear-params", "signature" : "($prepared-statement as xs:anyURI) as empty-sequence() external", "description" : " Clears the current parameter values immediately.\n", "summary" : "

    Clears the current parameter values immediately.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a prepared statement.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "This function returns an empty-sequence()" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "close-dataset", "qname" : "jdbc:close-dataset", "signature" : "($dataset-id as xs:anyURI) as empty-sequence() external", "description" : " Closes and free resources from a particular DataSet.\n", "summary" : "

    Closes and free resources from a particular DataSet.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "dataset-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a DataSet.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "This function returns an empty-sequence()" }, "errors" : [ "SQL008 DataSet doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "close-prepared", "qname" : "jdbc:close-prepared", "signature" : "($prepared-statement as xs:anyURI) as empty-sequence() external", "description" : " Closes and frees from memory any prepared SQL statement created with jdbc:prepare-statement\n", "summary" : "

    Closes and frees from memory any prepared SQL statement created with jdbc:prepare-statement\n

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a prepared statement.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "This function returns an empty-sequence()" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "commit", "qname" : "jdbc:commit", "signature" : "($connection-id as xs:anyURI) as empty-sequence() external", "description" : " Commit current transaction from an active connection.\n", "summary" : "

    Commit current transaction from an active connection.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to the connection to be commited.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "This function returns an empty-sequence()" }, "errors" : [ "SQL08003 Connection doesn't exist", "SQL08000 Connection is closed", "SQL001 Descriptive error, see error in attached message" ] }, { "isDocumented" : true, "arity" : 1, "name" : "connect-nondeterministic", "qname" : "jdbc:connect-nondeterministic", "signature" : "($connection-config as object()) as xs:anyURI external", "description" : " Opens a connection to a database.\n

    This function has the same semantics as connect#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Opens a connection to a database.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-config", "type" : "object()", "occurrence" : null, "description" : "
    json object that has the host and user informations.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "Return an identifier that represents the connection to the server." }, "errors" : [ "SQL28000 Authentication failed.", "SQL08001 Connection error.", "SQL40003 Isolation level not supported.", "SQL001 Descriptive error, see attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "connect-nondeterministic", "qname" : "jdbc:connect-nondeterministic", "signature" : "($connection-config as object(), $options as object()?) as xs:anyURI external", "description" : " Opens a connection to a database with specified options.\n

    This function has the same semantics as connect#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Opens a connection to a database with specified options.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-config", "type" : "object()", "occurrence" : null, "description" : "
    json object that has the host and user informations.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    json object that specifies the connection options.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "Return an identifier that represents the connection to the server." }, "errors" : [ "SQL28000 Authentication failed.", "SQL08001 Connection error.", "SQL40003 Isolation level not supported.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "connect", "qname" : "jdbc:connect", "signature" : "($connection-config as object()) as xs:anyURI external", "description" : " Opens a connection to a database.\n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Returns a URI identifying the connection that has been opened. The\n implementing code determines from the $connection-config either explicitly\n (interpreting the driver attribute) or implicitly (using the type attribute)\n which driver it has to load.

    \n", "summary" : "

    Opens a connection to a database.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection-config", "type" : "object()", "occurrence" : null, "description" : "
    json object that has the host and user informations.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "Return an identifier that represents the connection to the server. Connection coonfiguration example: { \"url\" : \"jdbc:mysql://localhost/\", \"user\" : \"root\", \"password\" : \"\" }" }, "errors" : [ "SQL28000 Authentication failed.", "SQL08001 Connection error.", "SQL40003 Isolation level not supported.", "SQL001 Descriptive error, see attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "connect", "qname" : "jdbc:connect", "signature" : "($connection-config as object(), $options as object()?) as xs:anyURI external", "description" : " Opens a connection to a database with specified options.\n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n

    Returns a URI identifying the connection that has been opened. The\n implementing code determines from the $connection-config either explicitly\n (interpreting the driver attribute) or implicitly (using the type attribute)\n which driver it has to load.

    \n", "summary" : "

    Opens a connection to a database with specified options.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection-config", "type" : "object()", "occurrence" : null, "description" : "
    json object that has the host and user informations.
    " }, { "name" : "options", "type" : "object()", "occurrence" : "?", "description" : "
    json object that specifies the connection options.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "Return an identifier that represents the connection to the server. Connection options example: { \"autocommit\" : false, \"readonly\"? : true, \"isolation-level\"? : $jdbc:READ-COMMITTED }" }, "errors" : [ "SQL28000 Authentication failed.", "SQL08001 Connection error.", "SQL40003 Isolation level not supported.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "connection-options", "qname" : "jdbc:connection-options", "signature" : "($connection-id as xs:anyURI) as object() external", "description" : " Returns a set with options for a specified connection.\n", "summary" : "

    Returns a set with options for a specified connection.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to the connection to be verify.
    " } ], "returns" : { "type" : "object()", "description" : "Returns and object with the connection options. The returned options are equal to the options specified in function jdbc:connect. Consequently, the options are specified as follows: { \"autocommit\" : xs:boolean, \"readonly\" : xs:boolean, \"isolation-level\" : xs:string }" }, "errors" : [ "SQL08003 Connection doesn't exist", "SQL08000 Connection is closed", "SQL001 Descriptive error, see error in attached message" ] }, { "isDocumented" : true, "arity" : 1, "name" : "execute-prepared", "qname" : "jdbc:execute-prepared", "signature" : "($prepared-statement as xs:anyURI) as xs:anyURI external", "description" : " Executes SQL statements prepared with 5.1 jsql:prepare-statement with values set\n and returns an identifier to a Dataset.\n", "summary" : "

    Executes SQL statements prepared with 5.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a prepared statement.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "Return an identifier that represents a DataSet." }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "execute-query-nondeterministic", "qname" : "jdbc:execute-query-nondeterministic", "signature" : "($connection-id as xs:anyURI, $sql as xs:string) as object()* external", "description" : " Executes non-updating SQL statements.\n

    This function has the same semantics as\n execute-query#2,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Executes non-updating SQL statements.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to an active connection.
    " }, { "name" : "sql", "type" : "xs:string", "occurrence" : null, "description" : "
    The query string to be executed.
    " } ], "returns" : { "type" : "object()*", "description" : "Return an object with the result data rows from the query provided, the data rows are defined as follows: { column:value* }* Every row is represented by an object of column-value representation of the returned SQL result." }, "errors" : [ "SQL08003 Connection doesn't exist.", "SQL08000 Connection is closed.", "SQL005 The statement is Updating type.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "execute-query-prepared-nondeterministic", "qname" : "jdbc:execute-query-prepared-nondeterministic", "signature" : "($prepared-statement as xs:anyURI) as object()* external", "description" : " Executes a non-updating SQL statement prepared with 5.1 jsql:prepare-statement.\n

    This function has the same semantics as\n execute-query-prepared#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Executes a non-updating SQL statement prepared with 5.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a prepared statement.
    " } ], "returns" : { "type" : "object()*", "description" : "Return an object with the result data rows from the query processed with the parameter values provided, the data rows are defined as follows: { column:value* }* Every row is represented by an object of column-value representation of the returned SQL result." }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL005 The prepared statement is an updating query.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "execute-query-prepared", "qname" : "jdbc:execute-query-prepared", "signature" : "($prepared-statement as xs:anyURI) as object()* external", "description" : " Executes a non-updating SQL statement prepared with 5.1 jsql:prepare-statement.\n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Executes a non-updating SQL statement prepared with 5.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a prepared statement.
    " } ], "returns" : { "type" : "object()*", "description" : "Return an object with the result data rows from the query processed with the parameter values provided, the data rows are defined as follows: { column:value* }* Every row is represented by an object of column-value representation of the returned SQL result." }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL005 The prepared statement is an updating query.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "execute-query", "qname" : "jdbc:execute-query", "signature" : "($connection-id as xs:anyURI, $sql as xs:string) as object()* external", "description" : " Executes non-updating SQL statements.\n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Executes non-updating SQL statements.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to an active connection.
    " }, { "name" : "sql", "type" : "xs:string", "occurrence" : null, "description" : "
    The query string to be executed.
    " } ], "returns" : { "type" : "object()*", "description" : "Return an object with the result data rows from the query provided, the data rows are defined as follows: { column:value* }* Every row is represented by an object of column-value representation of the returned SQL result." }, "errors" : [ "SQL08003 Connection doesn't exist.", "SQL08000 Connection is closed.", "SQL005 The statement is Updating type.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "execute-update-prepared", "qname" : "jdbc:execute-update-prepared", "signature" : "($prepared-statement as xs:anyURI) as xs:integer external", "description" : " Executes an updating SQL statement prepared with 5.1 jsql:prepare-statement.\n", "summary" : "

    Executes an updating SQL statement prepared with 5.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a prepared statement.
    " } ], "returns" : { "type" : "xs:integer", "description" : "Returns an xs:integer with the number of affected rows." }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL006 The prepared statement is a non-updating query.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "execute-update", "qname" : "jdbc:execute-update", "signature" : "($connection-id as xs:anyURI, $sql as xs:string) as xs:integer external", "description" : " Executes updating SQL statements.\n", "summary" : "

    Executes updating SQL statements.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to an active connection.
    " }, { "name" : "sql", "type" : "xs:string", "occurrence" : null, "description" : "
    The query string to be executed.
    " } ], "returns" : { "type" : "xs:integer", "description" : "Returns an xs:integer with the number of affected rows." }, "errors" : [ "SQL08003 Connection doesn't exist.", "SQL08000 Connection is closed.", "SQL005 The statement is Read-only type.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "execute", "qname" : "jdbc:execute", "signature" : "($connection-id as xs:anyURI, $sql as xs:string) as xs:anyURI external", "description" : " Executes any kind of SQL statement.\n", "summary" : "

    Executes any kind of SQL statement.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to an active connection.
    " }, { "name" : "sql", "type" : "xs:string", "occurrence" : null, "description" : "
    The query string to be executed.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "Return an identifier that represents a DataSet." }, "errors" : [ "SQL08003 Connection doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "is-connected", "qname" : "jdbc:is-connected", "signature" : "($connection-id as xs:anyURI) as xs:boolean external", "description" : " Verify if a connection is still active.\n", "summary" : "

    Verify if a connection is still active.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to the connection to be verify.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "Returns true if connected." }, "errors" : [ "SQL08003 Connection doesn't exist", "SQL001 Descriptive error, see error in attached message" ] }, { "isDocumented" : true, "arity" : 1, "name" : "metadata", "qname" : "jdbc:metadata", "signature" : "($dataset-id as xs:anyURI) as object() external", "description" : " Return the metadata of the result of a particular DataSet.\n", "summary" : "

    Return the metadata of the result of a particular DataSet.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "dataset-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a DataSet.
    " } ], "returns" : { "type" : "object()", "description" : "This function returns the metadata associated with an executed DataSet. More in detail, it returns information about column names, types, and whether a column can contain a null value. The metadata information can only be returned for DataSets that have been executed explicitly using the jsql:execute function. The metadata node returned by this function is defined as follows: { \"columns\": [ { \"name\": xs:string, \"type\": xs:string, \"autoincrement\"? = xs:boolean, \"nillable\"? = xs:boolean } * ] }" }, "errors" : [ "SQL008 DataSet doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "parameter-metadata", "qname" : "jdbc:parameter-metadata", "signature" : "($prepared-statement as xs:anyURI) as object() external", "description" : " Retrieves the number, types and properties of the prepared statement parameters.\n", "summary" : "

    Retrieves the number, types and properties of the prepared statement parameters.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a prepared statement.
    " } ], "returns" : { "type" : "object()", "description" : "This function returns the parameters metadata associated with a prepared statement. In other words, it returns information about the column name associated with the parameter, the type, etc. The metadata node returned by this function is defined as follows: { columns: [{ \"name\": xs:string, \"type\": xs:string }] }" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "prepare-statement", "qname" : "jdbc:prepare-statement", "signature" : "($connection-id as xs:anyURI, $sql as xs:string) as xs:anyURI external", "description" : " Creates a prepared statement for multiple executions with diferent values.\n", "summary" : "

    Creates a prepared statement for multiple executions with diferent values.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to an active connection.
    " }, { "name" : "sql", "type" : "xs:string", "occurrence" : null, "description" : "
    The query string to be executed.
    " } ], "returns" : { "type" : "xs:anyURI", "description" : "Return an identifier that represents the prepared statement. Example: jsql:prepare-statement($connection, \"SELECT * FROM users WHERE id=? AND age>?\")" }, "errors" : [ "SQL08003 Connection doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "result-set", "qname" : "jdbc:result-set", "signature" : "($dataset-id as xs:anyURI) as object()* external", "description" : " This function returns a sequence of objects representing the rows of data from a non-updating query.\n", "summary" : "

    This function returns a sequence of objects representing the rows of data from a non-updating query.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "dataset-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a DataSet.
    " } ], "returns" : { "type" : "object()*", "description" : "Return an object with the result data rows from the DataSet provided, the data rows are defined as follows: { column:value* }* Every row is represented by an object of column-value representation of the returned SQL result." }, "errors" : [ "SQL008 DataSet doesn't exist.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "rollback", "qname" : "jdbc:rollback", "signature" : "($connection-id as xs:anyURI) as empty-sequence() external", "description" : " Rollback the current transaction of a connection.\n", "summary" : "

    Rollback the current transaction of a connection.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to the connection to be rollbacked.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "This function returns an empty-sequence()" }, "errors" : [ "SQL08003 Connection doesn't exist", "SQL08000 Connection is closed", "SQL001 Descriptive error, see error in attached message" ] }, { "isDocumented" : true, "arity" : 3, "name" : "set-boolean", "qname" : "jdbc:set-boolean", "signature" : "($prepared-statement as xs:anyURI, $parameter-index as xs:integer, $value as xs:boolean) as empty-sequence() external", "description" : " Set the value of the designated parameter with the given value, this function will assign only boolean values.\n", "summary" : "

    Set the value of the designated parameter with the given value, this function will assign only boolean values.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a prepared statement.
    " }, { "name" : "parameter-index", "type" : "xs:integer", "occurrence" : null, "description" : "
    The index from the parameter to be set.
    " }, { "name" : "value", "type" : "xs:boolean", "occurrence" : null, "description" : "
    The value to be set.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "This function returns an empty-sequence()" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL007 Parameter casting error.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 2, "name" : "set-null", "qname" : "jdbc:set-null", "signature" : "($prepared-statement as xs:anyURI, $parameter-index as xs:integer) as empty-sequence() external", "description" : " Set the value of the designated parameter with the given value, this function\n will assign only null values if possible.\n", "summary" : "

    Set the value of the designated parameter with the given value, this function\n will assign only null values if possible.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a prepared statement.
    " }, { "name" : "parameter-index", "type" : "xs:integer", "occurrence" : null, "description" : "
    The index from the parameter to be set.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "This function returns an empty-sequence()" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL007 Parameter casting error.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 3, "name" : "set-numeric", "qname" : "jdbc:set-numeric", "signature" : "($prepared-statement as xs:anyURI, $parameter-index as xs:decimal, $value as xs:anyAtomicType) as empty-sequence() external", "description" : " Set the value of the designated parameter with the given value, this function will assign only numeric values.\n", "summary" : "

    Set the value of the designated parameter with the given value, this function will assign only numeric values.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a prepared statement.
    " }, { "name" : "parameter-index", "type" : "xs:decimal", "occurrence" : null, "description" : "
    The index from the parameter to be set.
    " }, { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The value to be set.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "This function returns an empty-sequence()" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL007 Parameter casting error.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 3, "name" : "set-string", "qname" : "jdbc:set-string", "signature" : "($prepared-statement as xs:anyURI, $parameter-index as xs:integer, $value as xs:string) as empty-sequence() external", "description" : " Set the value of the designated parameter with the given value, this function will assign only string values.\n", "summary" : "

    Set the value of the designated parameter with the given value, this function will assign only string values.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a prepared statement.
    " }, { "name" : "parameter-index", "type" : "xs:integer", "occurrence" : null, "description" : "
    The index from the parameter to be set.
    " }, { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    The value to be set.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "This function returns an empty-sequence()" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL007 Parameter casting error.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 3, "name" : "set-value", "qname" : "jdbc:set-value", "signature" : "($prepared-statement as xs:anyURI, $parameter-index as xs:decimal, $value as xs:anyAtomicType) as empty-sequence() external", "description" : " Set the value of the designated parameter with the given value,\n this function will assign any value you send\n and it will try to cast to the correct type.\n", "summary" : "

    Set the value of the designated parameter with the given value,\n this function will assign any value you send\n and it will try to cast to the correct type.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "prepared-statement", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a prepared statement.
    " }, { "name" : "parameter-index", "type" : "xs:decimal", "occurrence" : null, "description" : "
    The index from the parameter to be set.
    " }, { "name" : "value", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    The value to be set.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "This function returns an empty-sequence()" }, "errors" : [ "SQL003 Prepared statement doesn't exist.", "SQL007 Parameter casting error.", "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "tables-nondeterministic", "qname" : "jdbc:tables-nondeterministic", "signature" : "($connection-id as xs:anyURI) as object()*", "description" : " Return the list of tables from a connection\n

    This function has the same semantics as tables#1,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Return the list of tables from a connection\n This function has the same semantics as tables#1 ,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a connection.
    " } ], "returns" : { "type" : "object()*", "description" : "Return an object with the result data rows from the query provided, the data rows are defined as follows: { column:value* }* Every row is represented by an object of column-value representation of the returned SQL result." }, "errors" : [ "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 4, "name" : "tables-nondeterministic", "qname" : "jdbc:tables-nondeterministic", "signature" : "($connection-id as xs:anyURI, $catalog as xs:string?, $schema as xs:string?, $table as xs:string?) as object()* external", "description" : " Return the list of tables from a connection.\n

    This function has the same semantics as tables#4,\n but is declared as being non deterministic and thus should only be used when\n result caching is not desired.

    \n", "summary" : "

    Return the list of tables from a connection.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "connection-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a connection.
    " }, { "name" : "catalog", "type" : "xs:string", "occurrence" : "?", "description" : "
    A filter of the catalog name of the tables. Send empty-sequence for all tables.
    " }, { "name" : "schema", "type" : "xs:string", "occurrence" : "?", "description" : "
    A filter of the schema name of the tables. Send empty-sequence for all tables.
    " }, { "name" : "table", "type" : "xs:string", "occurrence" : "?", "description" : "
    A filter of the name of the tables. Send empty-sequence for all tables.
    " } ], "returns" : { "type" : "object()*", "description" : "Return an object with the result data rows from the query provided, the data rows are defined as follows: { column:value* }* Every row is represented by an object of column-value representation of the returned SQL result." }, "errors" : [ "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 1, "name" : "tables", "qname" : "jdbc:tables", "signature" : "($connection-id as xs:anyURI) as object()*", "description" : " Return the list of tables from a connection\n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Return the list of tables from a connection\n This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a connection.
    " } ], "returns" : { "type" : "object()*", "description" : "Return an object with the result data rows from the query provided, the data rows are defined as follows: { column:value* }* Every row is represented by an object of column-value representation of the returned SQL result." }, "errors" : [ "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] }, { "isDocumented" : true, "arity" : 4, "name" : "tables", "qname" : "jdbc:tables", "signature" : "($connection-id as xs:anyURI, $catalog as xs:string?, $schema as xs:string?, $table as xs:string?) as object()* external", "description" : " Return the list of tables from a connection\n

    This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    \n", "summary" : "

    Return the list of tables from a connection\n This function is declared as deterministic and should be used whenever result\n caching is acceptable.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "connection-id", "type" : "xs:anyURI", "occurrence" : null, "description" : "
    The identifier to a connection.
    " }, { "name" : "catalog", "type" : "xs:string", "occurrence" : "?", "description" : "
    A filter of the catalog name of the tables. Send empty-sequence for all tables.
    " }, { "name" : "schema", "type" : "xs:string", "occurrence" : "?", "description" : "
    A filter of the schema name of the tables. Send empty-sequence for all tables.
    " }, { "name" : "table", "type" : "xs:string", "occurrence" : "?", "description" : "
    A filter of the name of the tables. Send empty-sequence for all tables.
    " } ], "returns" : { "type" : "object()*", "description" : "Return an object with the result data rows from the query provided, the data rows are defined as follows: { column:value* }* Every row is represented by an object of column-value representation of the returned SQL result." }, "errors" : [ "SQL08000 Connection is closed.", "SQL001 Descriptive error, see error in attached message." ] } ], "variables" : [ { "name" : "jdbc:NOT-SUPPORTED", "type" : "item()*", "description" : " This variable represents the NOT-SUPPORTED level for Isolation Levels in $options for 2.2 connect function.\n" }, { "name" : "jdbc:READ-COMMITTED", "type" : "item()*", "description" : " This variable represents the READ-COMMITTED level for Isolation Levels in $options for 2.2 connect function.\n" }, { "name" : "jdbc:READ-UNCOMMITTED", "type" : "item()*", "description" : " This variable represents the READ-UNCOMMITTED level for Isolation Levels in $options for 2.2 connect function.\n" }, { "name" : "jdbc:REPEATABLE-READ", "type" : "item()*", "description" : " This variable represents the REPEATABLE-READ level for Isolation Levels in $options for 2.2 connect function.\n" }, { "name" : "jdbc:SERIALIZABLE", "type" : "item()*", "description" : " This variable represents the SERIALIZABLE level for Isolation Levels in $options for 2.2 connect function.\n" } ] }, "http://www.28msec.com/modules/http-response" : { "ns" : "http://www.28msec.com/modules/http-response", "description" : " The response module can be used to modify the HTTP response\n that will be send as a result. For example, the\n content-type function can be used to set the\n Content-Type header and determine the encoding of data in the\n response.\n", "sees" : [ ], "authors" : [ "Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/http-response", "prefix" : "http" }, { "uri" : "http://www.w3.org/2010/xslt-xquery-serialization", "prefix" : "output" }, { "uri" : "http://www.28msec.com/modules/http/response#2.0", "prefix" : "res" }, { "uri" : "http://www.28msec.com/modules/http-response", "prefix" : "resp" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "code-for-status", "qname" : "resp:code-for-status", "signature" : "($status as xs:string) as xs:integer", "description" : " Convert between the name of the HTTP status code and\n the integer value of that status code.\n", "summary" : "

    Convert between the name of the HTTP status code and\n the integer value of that status code.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "status", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:integer", "description" : "the integer value of the given status code." }, "errors" : [ "http:invalid-status if the given name does not represent a valid http status code" ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-binary", "qname" : "resp:content-type-binary", "signature" : "($type as xs:string) as xs:boolean", "description" : "

    Test if a given content-type is a binary content-type. A\n content-type is considered to be binary if it's not a text\n content-type.

    \n", "summary" : "

    Test if a given content-type is a binary content-type.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is a binary content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-html", "qname" : "resp:content-type-html", "signature" : "($type as xs:string) as xs:boolean", "description" : "

    Test if a given content-type is a HTML content-type, i.e.\n the content-type is the string \"text/html\".

    \n", "summary" : "

    Test if a given content-type is a HTML content-type, i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is the HTML content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-json", "qname" : "resp:content-type-json", "signature" : "($type as xs:string) as xs:boolean", "description" : "

    Test if a given content-type is a JSON content-type, i.e.\n the content-type is the string \"application/json\".

    \n", "summary" : "

    Test if a given content-type is a JSON content-type, i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is the JSON content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-mixed-json-xml", "qname" : "resp:content-type-mixed-json-xml", "signature" : "($type as xs:string) as xs:boolean", "description" : "

    Test if a given content-type is a mixed JSON-XML content-type, i.e.\n the content-type is the string \"application/mixed-json-xml\".

    \n", "summary" : "

    Test if a given content-type is a mixed JSON-XML content-type, i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is a mixed JSON-XML content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-text", "qname" : "resp:content-type-text", "signature" : "($type as xs:string) as xs:boolean", "description" : "

    Test if a given content-type is a text content-type.

    \n

    A text content-type starts with \"text/\" or contains either of\n the strings \"xml\" or \"json\".

    \n", "summary" : "

    Test if a given content-type is a text content-type.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is a text content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-xhtml", "qname" : "resp:content-type-xhtml", "signature" : "($type as xs:string) as xs:boolean", "description" : "

    Test if a given content-type is a XHTML content-type, i.e.\n the content-type is the string \"application/xhtml+xml\".

    \n", "summary" : "

    Test if a given content-type is a XHTML content-type, i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is the XHTML content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type-xml", "qname" : "resp:content-type-xml", "signature" : "($type as xs:string) as xs:boolean", "description" : "

    Test if a given content-type is a XML content-type

    \n

    A XML content-type is a content-type that is \"application/xml\"\n or ends : with the string \"+xml\".

    \n", "summary" : "

    Test if a given content-type is a XML content-type \n A XML content-type is a content-type that is \"application/xml\"\n or ends : with the string \"+xml\".

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to test.
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given content-type is a XML content-type, false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "content-type", "qname" : "resp:content-type", "signature" : "($type as xs:string) as empty-sequence()", "description" : "

    Sets the Content-Type header for the response.

    \n

    \n For example,\n resp:content-type(\"text/plain\") will cause the\n header\n Content-Type: text/plain to be added for the response.

    \n

    In addtion to setting the Content-Type header, the function also\n sets the serialization parameters to the default values for serialization\n method for the given content-type. For example, if the content-type is set to\n text/plain, the default serialization parameters for the text\n serialization method will be used.

    \n

    The functions resp:content-type-text/xml/html/xhtml/binary may be used\n to figure out which serialization method will be used for a specific\n content-type.

    \n

    If the given content-type contains a charset declaration (e.g.\n resp:content-type(\"text/plain;charset=ISO-8859-1\")), the\n content of the response will be transcoded to the given encoding.

    \n

    The default serialization parameters set by this function can\n be overwritten using the resp:serialization-parameters() function.

    \n", "summary" : "

    Sets the Content-Type header for the response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to be set
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and returns the empty sequence" }, "errors" : [ "http:invalid-encoding if the given encoding is invalid or not supported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "content-type", "qname" : "resp:content-type", "signature" : "($type as xs:string, $params as object()) as empty-sequence()", "description" : "

    Sets the Content-Type header for the response.

    \n

    For example,\n resp:content-type(\"text/plain\") will cause the\n header\n Content-Type: text/plain to be added for the response.

    \n

    In addition to the content-type, the function also allows to\n specify the serialization method and parameters that will be used\n for serializing the result. For details about this parameter, please\n refer to resp:serialization-parameters#1.

    \n

    If the content-type suggest using a binary serialization,\n resp:decode-binary#1 will be called and set to true except if\n the serialization method is specified at the same time. In this\n case, the serialization method will be used as specified.

    \n

    If the given content-type contains a charset declaration (e.g.\n resp:content-type(\"text/plain;charset=ISO-8859-1\")), the\n content of the response will be transcoded to the given encoding.\n If the serialization parameters also contain a charset declaration,\n the charset contained in the content-type will be used. to transcode\n the result.

    \n", "summary" : "

    Sets the Content-Type header for the response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "type", "type" : "xs:string", "occurrence" : null, "description" : "
    the content-type to be set
    " }, { "name" : "params", "type" : "object()", "occurrence" : null, "description" : "
    the serialization parameters that will be used for serialization the result.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and returns the empty sequence" }, "errors" : [ "http:invalid-encoding if the given encoding is invalid or not supported." ] }, { "isDocumented" : true, "arity" : 0, "name" : "decode-binary", "qname" : "resp:decode-binary", "signature" : "() as xs:boolean", "description" : "

    Returns the boolean indiciating whether base64Binary returned by\n this request will be decoded.

    \n

    The default if not modified using resp:decode-binary is false.

    \n", "summary" : "

    Returns the boolean indiciating whether base64Binary returned by\n this request will be decoded.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:boolean", "description" : "the said boolean value" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "decode-binary", "qname" : "resp:decode-binary", "signature" : "($decode as xs:boolean) as empty-sequence()", "description" : "

    If this function is invoked with true, the result of the request\n will not be serialized. Instead, the result will be the binary values\n of any item that is of type base64Binary. The values of all other\n items will not be part of the result.

    \n

    Please note that all serialization parameters which have been set using\n resp:serialization-parameters will be ignored. Also, the output encoding\n is ignored for binaries.

    \n", "summary" : "

    If this function is invoked with true, the result of the request\n will not be serialized.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "decode", "type" : "xs:boolean", "occurrence" : null, "description" : "
    boolean value indicating whether base64Binary should be decoded.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and returns the empty sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "encoding", "qname" : "resp:encoding", "signature" : "($encoding as xs:string) as empty-sequence()", "description" : "

    The function sets the output encoding that will be\n used for the payload of the response.

    \n

    For example,\n resp:encoding(\"ISO-8859-1\") will cause the\n content in the response to be encoded using ISO-8859-1.

    \n

    Please note that the encoding only applies to textual data.\n It is not used if the function decode-binary()\n was invoked passing true as parameter.

    \n", "summary" : "

    The function sets the output encoding that will be\n used for the payload of the response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "
    the encoding to be used for the payload of the response.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and returns the empty sequence" }, "errors" : [ "http:invalid-encoding if the given encoding is invalid or not supported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "header", "qname" : "resp:header", "signature" : "($name as xs:string, $value as xs:string) as xs:string?", "description" : "

    Set a HTTP header in the response.

    \n

    If a header with the same name was already set, the\n value is overwritten and the function returns the old value. As defined\n in the HTTP specification, multiple headers with the same name\n can be combined into one header whose value is a comma-separated\n list of the values.

    \n

    The following headers must not be set using this function.\n Instead, other functions of this module should be used in order\n to implemented the required semantics:\n

      \n
    • Status: use status() instead
    • \n
    • Content-Type: use content-type() instead
    • \n
    \n

    \n", "summary" : "

    Set a HTTP header in the response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "name", "type" : "xs:string", "occurrence" : null, "description" : "
    the name of the header to set
    " }, { "name" : "value", "type" : "xs:string", "occurrence" : null, "description" : "
    the value of the header to set `
    " } ], "returns" : { "type" : "xs:string?", "description" : "the value of the header previously set or the empty sequence if no header has been set with the same name." }, "errors" : [ "resp:invalid-header-name if an invalid name is used for the header." ] }, { "isDocumented" : true, "arity" : 1, "name" : "message-for-status", "qname" : "resp:message-for-status", "signature" : "($status as xs:string) as xs:string", "description" : " Convert between the HTTP status code as string and\n the name/message of that status code.\n", "summary" : "

    Convert between the HTTP status code as string and\n the name/message of that status code.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "status", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "the message for the given name" }, "errors" : [ "http:invalid-status if the given name does not represent a valid http status code" ] }, { "isDocumented" : true, "arity" : 1, "name" : "redirect", "qname" : "resp:redirect", "signature" : "($url as xs:string) as empty-sequence()", "description" : " This function sets the HTTP 302 redirect status code in the response. As\n a result, a redirect to the URL given as parameter will be made.\n", "summary" : "

    This function sets the HTTP 302 redirect status code in the response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "url", "type" : "xs:string", "occurrence" : null, "description" : "
    The URL to which the redirect will be made.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The empty-sequence is returned." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "serialization-parameters", "qname" : "resp:serialization-parameters", "signature" : "() as object()", "description" : "

    Returns the serialization parameters that are currently\n active, i.e. the ones that will be used to serialize the result\n of this request.

    \n

    This will either be the default, the defaults set when\n calling resp:content-type(), or the ones set by\n resp:serialization-parameters().

    \n", "summary" : "

    Returns the serialization parameters that are currently\n active, i.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "the said serialization parameters" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "serialization-parameters", "qname" : "resp:serialization-parameters", "signature" : "($params as object()) as empty-sequence()", "description" : "

    Set the serialization parameters used for serializing the result\n of the request.

    \n

    The following example shows how to set several options\n for the JSON serialization method.\n

    \n {\n   \"method\" : \"json\",\n   \"indent\" : false,\n   \"encoding\" : \"UTF-16\"\n }\n 
    \n

    \n

    Please note that serialization options set by this function can\n be overwritten by a subsequent call to resp:content-type. In this\n case, the options will be reset to the default for the given\n content-type. Also note, that the output encoding can be overwritten\n by subsequently calling the resp:encoding function.

    \n", "summary" : "

    Set the serialization parameters used for serializing the result\n of the request.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "params", "type" : "object()", "occurrence" : null, "description" : "
    the serialization parameters that will be used to serialize the result of the request
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the function is sequential and, on success, returns the empty sequence." }, "errors" : [ "err:XQDY0027 if the input is not valid", "http:invalid-encoding if the encoding specified in the serialization options is invalid or not supported." ] }, { "isDocumented" : true, "arity" : 0, "name" : "serializer-defaults-html", "qname" : "resp:serializer-defaults-html", "signature" : "() as object()", "description" : "

    Returns an object that can be used to specify the\n settings of serialization parameters for the HTML serialization\n method.

    \n

    The defaults are\n

    \n {\n   \"encoding\" : \"UTF-8\",\n   \"indent\" : true,\n   \"method\" : \"html\",\n   \"version\" : \"4.01\",\n   \"doctype-system\" : \"http://www.w3.org/TR/html4/loose.dtd\",\n   \"doctype-public\" : \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n }\n 
    \n

    \n

    For example, those defaults are used when setting\n the content-type to some HTML content-type (i.e. text/html).

    \n", "summary" : "

    Returns an object that can be used to specify the\n settings of serialization parameters for the HTML serialization\n method.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "an object that can be used to specify the above serialization parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "serializer-defaults-json-xml-hybrid", "qname" : "resp:serializer-defaults-json-xml-hybrid", "signature" : "() as object()", "description" : "

    Returns an object that can be used to specify the\n settings of serialization parameters for the json\n serialization method.

    \n

    The defaults are\n

    \n {\n   \"encoding\" : \"UTF-8\",\n   \"indent\" : \"yes\",\n   \"method\" : \"json\"\n }\n 
    \n

    \n

    For example, those defaults are used when setting\n the content-type to some XML content-type (e.g. application/atom+xml).

    \n", "summary" : "

    Returns an object that can be used to specify the\n settings of serialization parameters for the json\n serialization method.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "an object that can be used to specify the above serialization parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "serializer-defaults-json", "qname" : "resp:serializer-defaults-json", "signature" : "() as object()", "description" : "

    Returns an object that can be used to specify the\n settings of serialization parameters for the json-xml hybrid\n serialization method.

    \n

    The defaults are\n

    \n {\n   \"encoding\" : \"UTF-8\",\n   \"indent\" : \"yes\",\n   \"method\" : \"json\"\n }\n 
    \n

    \n

    For example, those defaults are used when setting\n the content-type to application/mixed-json-xml.

    \n", "summary" : "

    Returns an object that can be used to specify the\n settings of serialization parameters for the json-xml hybrid\n serialization method.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "an object that can be used to specify the above serialization parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "serializer-defaults-text", "qname" : "resp:serializer-defaults-text", "signature" : "() as object()", "description" : "

    Returns an object that can be used to specify the\n settings of serialization parameters for the text serialization\n method.

    \n

    The only default used is\n

    \n {\n  \"method\" : \"text\",\n  \"encoding\" : \"UTF-8\",\n }\n 
    \n

    \n

    For example, this default is used when setting\n the content-type to some text content-type (e.g. text/plain).

    \n", "summary" : "

    Returns an object that can be used to specify the\n settings of serialization parameters for the text serialization\n method.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "an object that can be used to specify the above serialization parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "serializer-defaults-xhtml", "qname" : "resp:serializer-defaults-xhtml", "signature" : "() as object()", "description" : "

    Returns an object that can be used to specify the\n settings of serialization parameters for the XHTML serialization\n method.

    \n

    The defaults are\n

    \n {\n   \"encoding\" : \"UTF-8\",\n   \"indent\" : true,\n   \"method\" : \"xhtml\",\n   \"omit-xml-declaration\" : true,\n   \"version\" : \"1.0\",\n   \"doctype-system\" : \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\",\n   \"doctype-public\" : \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n }\n 
    \n

    \n

    For example, those defaults are used when setting\n the content-type to some XHTML content-type (i.e. application/xhtml+xml).

    \n", "summary" : "

    Returns an object that can be used to specify the\n settings of serialization parameters for the XHTML serialization\n method.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "an object that can be used to specify the above serialization parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "serializer-defaults-xml", "qname" : "resp:serializer-defaults-xml", "signature" : "() as object()", "description" : "

    Returns an object that can be used to specify the\n settings of serialization parameters for the XML serialization\n method.

    \n

    The defaults are\n

    \n {\n  \"method\" : \"xml\",\n  \"encoding\" : \"UTF-8\",\n  \"indent\" : true,\n  \"omit-xml-declaration\" : true,\n  \"version\" : \"1.0\"\n }\n 
    \n

    \n

    For example, those defaults are used when setting\n the content-type to some XML content-type (e.g. application/atom+xml).

    \n", "summary" : "

    Returns an object that can be used to specify the\n settings of serialization parameters for the XML serialization\n method.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()", "description" : "an object that can be used to specify the above serialization parameters." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "status-code", "qname" : "resp:status-code", "signature" : "($status as xs:integer) as empty-sequence()", "description" : "

    Sets the status code of the HTTP response to the integer given as\n parameter.

    \n For example,\n resp:status(204)\n will result in \"HTTP/1.1 204 No Content\".\n", "summary" : "

    Sets the status code of the HTTP response to the integer given as\n parameter.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "status", "type" : "xs:integer", "occurrence" : null, "description" : "
    The status code of the HTTP response as integer.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "On success, the empty-sequence is returned" }, "errors" : [ "http:invalid-status-code if the given integer does not reflect a valid HTTP status code" ] }, { "isDocumented" : true, "arity" : 1, "name" : "status", "qname" : "resp:status", "signature" : "($status as xs:string) as empty-sequence()", "description" : "

    Sets the status code of the HTTP response to code associated\n with the given string.

    \n

    For example,\n resp:status($http:no-content)\n will result in \"HTTP/1.1 204 No Content\".

    \n", "summary" : "

    Sets the status code of the HTTP response to code associated\n with the given string.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "status", "type" : "xs:string", "occurrence" : null, "description" : "
    The status code of the HTTP response as a string (e.g. $http:no-content)
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "On success, the empty-sequence is returned" }, "errors" : [ "http:invalid-status if the given string does not represent a valid HTTP status code;" ] }, { "isDocumented" : true, "arity" : 1, "name" : "valid-status", "qname" : "resp:valid-status", "signature" : "($status as xs:string) as xs:boolean", "description" : " Test whether the given name refers to a valid HTTP status code.\n", "summary" : "

    Test whether the given name refers to a valid HTTP status code.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "status", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:boolean", "description" : "true if the given name refers to a valid HTTP status code, false otherwise." }, "errors" : [ ] } ], "variables" : [ { "name" : "http:precondition-required", "type" : "item()*", "description" : " A string representing the HTTP Status Code 428 Precondition Required (RFC 6585)\n" }, { "name" : "http:gone", "type" : "item()*", "description" : " A string representing the HTTP Status Code 410 GONE\n" }, { "name" : "http:length-required", "type" : "item()*", "description" : " A string representing the HTTP Status Code 411 Length Required\n" }, { "name" : "http:precondition-failed", "type" : "item()*", "description" : " A string representing the HTTP Status Code 412 Precondition Failed\n" }, { "name" : "http:request-entity-too-large", "type" : "item()*", "description" : " A string representing the HTTP Status Code 413 Request Entity Too Large\n" }, { "name" : "http:request-entity-too-long", "type" : "item()*", "description" : " A string representing the HTTP Status Code 414 Request Entity Too Long\n" }, { "name" : "http:unsupported-media-type", "type" : "item()*", "description" : " A string representing the HTTP Status Code 415 Unsupported Media Type\n" }, { "name" : "http:request-range-not-satisfiable", "type" : "item()*", "description" : " A string representing the HTTP Status Code 416 Request Range Not Satisfiable\n" }, { "name" : "http:expectation-failed", "type" : "item()*", "description" : " A string representing the HTTP Status Code 417 Expectation Failed\n" }, { "name" : "http:im-a-teapot", "type" : "item()*", "description" : " A string representing the HTTP Status Code 418 I'm a teapot (RFC 2324)\n" }, { "name" : "http:enhance-your-calm", "type" : "item()*", "description" : " A string representing the HTTP Status Code 420 Enhance Your Calm\n" }, { "name" : "http:unprocessable-entity", "type" : "item()*", "description" : " A string representing the HTTP Status Code 422 Unprocessable Entity (WebDAV; RFC 4918)\n" }, { "name" : "http:locked", "type" : "item()*", "description" : " A string representing the HTTP Status Code 423 Locked (WebDAV; RFC 4918)\n" }, { "name" : "http:failed-dependency", "type" : "item()*", "description" : " A string representing the HTTP Status Code 424 Failed Dependency (WebDAV; RFC 4918)\n" }, { "name" : "http:unordered-collection", "type" : "item()*", "description" : " A string representing the HTTP Status Code 425 Unordered Collection\n" }, { "name" : "http:upgrade-required", "type" : "item()*", "description" : " A string representing the HTTP Status Code 426 Upgrade Required\n" }, { "name" : "http:conflict", "type" : "item()*", "description" : " A string representing the HTTP Status Code 409 Conflict\n" }, { "name" : "http:too-many-requests", "type" : "item()*", "description" : " A string representing the HTTP Status Code 429 Too Many Requests (RFC 6585)\n" }, { "name" : "http:request-header-fields-too-large", "type" : "item()*", "description" : " A string representing the HTTP Status Code 431 Request Header Fields Too Large (RFC 6585)\n" }, { "name" : "http:internal-server-error", "type" : "item()*", "description" : " A string representing the HTTP Status Code 500 Internal Server Error\n" }, { "name" : "http:not-implemented", "type" : "item()*", "description" : " A string representing the HTTP Status Code 501 Not Implemented\n" }, { "name" : "http:bad-gateway", "type" : "item()*", "description" : " A string representing the HTTP Status Code 502 Bad Gateway\n" }, { "name" : "http:service-unavailable", "type" : "item()*", "description" : " A string representing the HTTP Status Code 503 Service Unavailable\n" }, { "name" : "http:gateway-timeout", "type" : "item()*", "description" : " A string representing the HTTP Status Code 504 Gateway Timeout\n" }, { "name" : "http:http-version-not-supported", "type" : "item()*", "description" : " A string representing the HTTP Status Code 505 HTTP Version Not Supported\n" }, { "name" : "http:variant-also-negotiates", "type" : "item()*", "description" : " A string representing the HTTP Status Code 506 Variant Also Negotiates (RFC 2295)\n" }, { "name" : "http:insufficient-storage", "type" : "item()*", "description" : " A string representing the HTTP Status Code 507 Insufficient Storage (WebDAV; RFC 4918)\n" }, { "name" : "http:loop-detected", "type" : "item()*", "description" : " A string representing the HTTP status code 508 Loop Detected (webdav; rfc 5842)\n" }, { "name" : "http:not-extended", "type" : "item()*", "description" : " A string representing the HTTP status code 510 Not Extended (RFC 2774)\n" }, { "name" : "http:network-authentication-required", "type" : "item()*", "description" : " A string representing the HTTP status code 511 Network Authentication Required (RFC 6585)\n" }, { "name" : "resp:status-info", "type" : "object()", "description" : " Variable containing a description for all the HTTP Status Codes\n" }, { "name" : "http:see-other", "type" : "item()*", "description" : " A string representing the HTTP Status Code 303 See Other\n" }, { "name" : "http:switching-protocols", "type" : "item()*", "description" : " A string representing the HTTP Status Code 101 Switching Protocols\n" }, { "name" : "http:processing", "type" : "item()*", "description" : " A string representing the HTTP Status Code 102 Processing (Web; RFC 2518)\n" }, { "name" : "http:ok", "type" : "item()*", "description" : " A string representing the HTTP Status Code 200 OK\n" }, { "name" : "http:created", "type" : "item()*", "description" : " A string representing the HTTP Status Code 201 Created\n" }, { "name" : "http:accepted", "type" : "item()*", "description" : " A string representing the HTTP Status Code 202 Accepted\n" }, { "name" : "http:non-authoritative", "type" : "item()*", "description" : " A string representing the HTTP Status Code 203 Non-Authoritative\n" }, { "name" : "http:no-content", "type" : "item()*", "description" : " A string representing the HTTP Status Code 204 No Content\n" }, { "name" : "http:reset-content", "type" : "item()*", "description" : " A string representing the HTTP Status Code 205 Reset Content\n" }, { "name" : "http:partial-content", "type" : "item()*", "description" : " A string representing the HTTP Status Code 206 Partial Content\n" }, { "name" : "http:multi-status", "type" : "item()*", "description" : " A string representing the HTTP Status Code 207 Multi-Status (WebDAV; RFC 5842)\n" }, { "name" : "http:already-reported", "type" : "item()*", "description" : " A string representing the HTTP Status Code 208 Already Reported (WebDAV; RFC 5842)\n" }, { "name" : "http:im-used", "type" : "item()*", "description" : " A string representing the HTTP Status Code 226 IM Used (RFC 3229)\n" }, { "name" : "http:multiple-choices", "type" : "item()*", "description" : " A string representing the HTTP Status Code 300 Multiple Choices\n" }, { "name" : "http:moved-permanently", "type" : "item()*", "description" : " A string representing the HTTP Status Code 301 Moved Permantently\n" }, { "name" : "http:found", "type" : "item()*", "description" : " A string representing the HTTP Status Code 302 Found\n" }, { "name" : "http:continue", "type" : "item()*", "description" : " A string representing the HTTP Status Code 100 Continue\n" }, { "name" : "http:not-modified", "type" : "item()*", "description" : " A string representing the HTTP Status Code 304 Not Modified\n" }, { "name" : "http:use-proxy", "type" : "item()*", "description" : " A string representing the HTTP Status Code 305 Use Proxy\n" }, { "name" : "http:switch-proxy", "type" : "item()*", "description" : " A string representing the HTTP Status Code 306 Switch Proxy\n" }, { "name" : "http:temporary-redirect", "type" : "item()*", "description" : " A string representing the HTTP Status Code 307 Temporary Redirect\n" }, { "name" : "http:permanent-redirect", "type" : "item()*", "description" : " A string representing the HTTP Status Code 308 Permanent Redirect (http://tools.ietf.org/html/draft-reschke-http-status-308-07)\n" }, { "name" : "http:bad-request", "type" : "item()*", "description" : " A string representing the HTTP Status Code 400 Bad Request\n" }, { "name" : "http:unauthorized", "type" : "item()*", "description" : " A string representing the HTTP Status Code 401 Unauthorized\n" }, { "name" : "http:payment-required", "type" : "item()*", "description" : " A string representing the HTTP Status Code 402 Payment Required\n" }, { "name" : "http:forbidden", "type" : "item()*", "description" : " A string representing the HTTP Status Code 403 Forbidden\n" }, { "name" : "http:not-found", "type" : "item()*", "description" : " A string representing the HTTP Status Code 404 Not Found\n" }, { "name" : "http:not-allowed", "type" : "item()*", "description" : " A string representing the HTTP Status Code 405 Not Allowed\n" }, { "name" : "http:not-acceptable", "type" : "item()*", "description" : " A string representing the HTTP Status Code 406 Not Acceptable\n" }, { "name" : "http:proxy-authentication-required", "type" : "item()*", "description" : " A string representing the HTTP Status Code 407 Proxy Authentication Required\n" }, { "name" : "http:request-timeout", "type" : "item()*", "description" : " A string representing the HTTP Status Code 408 Request Timeout\n" } ] }, "http://www.zorba-xquery.com/modules/email/smtp" : { "ns" : "http://www.zorba-xquery.com/modules/email/smtp", "description" : " This module can be used for sending emails.\n The SMTP module contains only one public function that receives two parameters.\n The SMTP server access information passed as an hostInfo element\n and the email message representation as a message element.\n For a quick start see the examples associates with the send(...)\n function. For a complete specification read, the description and the\n documentation associated with this function.\n", "sees" : [ "c-client Library part of UW IMAP toolkit" ], "authors" : [ "Sorin Nasoi, Daniel Thomas" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.zorba-xquery.com/modules/email", "prefix" : "email" }, { "uri" : "http://www.zorba-xquery.com/modules/email/smtp", "prefix" : "smtp" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "send", "qname" : "smtp:send", "signature" : "($host-info as element(email:hostInfo), $message as element(email:message)) as empty-sequence()", "description" : " This function sends an email message from the specified account.\n The hostName child element of $host-info must have the form:\n remote_system_name [\":\" port] [flags]. This syntax is part of the\n Remote names\n syntax defined in the UW IMAP toolkit. The remote_system_name and\n flags fragments are explained in the section III of this document.\n For example the hostName could look like:\n
      \n
    • <hostName>smtp.gmail.com:587/tls/novalidate-cert<hostName>
    • \n
    • <hostName>[209.85.129.111]:587/tls/novalidate-cert<hostName>
    • \n
    \n The $host-info parameter could then look like this:\n
    \n <hostInfo>\n   <hostName>smtp.gmail.com:587/tls/novalidate-cert</hostName>\n   <userName>username</userName>\n   <password>password</password>\n </hostInfo>\n 
    \n For a complete of the structure of an email message, see the imported email\n schema: http://www.zorba-xquery.com/modules/email\n All the data passed to this function does not need to be validated.\n The only requirement is that they have a valid format and are in the\n correct namespace according to the schema:\n http://www.zorba-xquery.com/modules/email.\n", "summary" : "

    This function sends an email message from the specified account.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "host-info", "type" : "element(email:hostInfo)", "occurrence" : null, "description" : "
    The SMTP host, user name, and password.
    " }, { "name" : "message", "type" : "element(email:message)", "occurrence" : null, "description" : "
    The message to send as defined in the email XML schema.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "The function is declared as sequential and has side-effects. It returns the empty sequence." }, "errors" : [ "smtp:SMTP0001 The message format is invalid.", "smtp:SMTP0002 The message has no recipient.", "smtp:SMTP0003 The message could not be sent.", "smtp:SMTP9999 If any other error occurs.", "err:XQDY0027 If the values of the arguments are not not valid according to the email schema: http://www.zorba-xquery.com/modules/email" ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/project" : { "ns" : "http://www.28msec.com/modules/project", "description" : " This module contains functions to introspect a project.\n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://zorba.io/modules/base64", "prefix" : "base64" }, { "uri" : "http://zorba.io/modules/hmac", "prefix" : "hmac" }, { "uri" : "http://www.28msec.com/modules/project", "prefix" : "project" }, { "uri" : "http://zorba.io/modules/random", "prefix" : "random" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "create-seed", "qname" : "project:create-seed", "signature" : "() as string", "description" : " Creates and return new random project seed.\n", "summary" : "

    Creates and return new random project seed.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "string", "description" : "the project seed" }, "errors" : [ "project:SEED-EXISTS the project already has a seed file", "project:SEED-FILE error writing the seed file", "project:SEED the specified seed is not at least 8 characters long" ] }, { "isDocumented" : true, "arity" : 1, "name" : "create-seed", "qname" : "project:create-seed", "signature" : "($seed as string) as empty-sequence()", "description" : " Creates a new project seed.\n The specified seed must be at least 8 characters long.\n", "summary" : "

    Creates a new project seed.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "seed", "type" : "string", "occurrence" : null, "description" : "
    The new project seed.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the empty sequence" }, "errors" : [ "project:SEED-EXISTS the project already has a seed file", "project:SEED-FILE error writing the seed file" ] }, { "isDocumented" : true, "arity" : 0, "name" : "has-seed", "qname" : "project:has-seed", "signature" : "() as boolean external", "description" : " Checks if the project has a seed file.\n", "summary" : "

    Checks if the project has a seed file.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "boolean", "description" : "whether the project has a seed file or not" }, "errors" : [ "project:SEED-FILE error accessing the seed file" ] }, { "isDocumented" : true, "arity" : 0, "name" : "name", "qname" : "project:name", "signature" : "() as string external", "description" : " Returns the name of the project.\n", "summary" : "

    Returns the name of the project.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "string", "description" : "the said name" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "read-or-create-seed", "qname" : "project:read-or-create-seed", "signature" : "() as string", "description" : " Returns the project seed. If the project has no seed a new random one is created.\n", "summary" : "

    Returns the project seed.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "string", "description" : "the project seed" }, "errors" : [ "project:SEED-FILE error reading or writing the seed file" ] }, { "isDocumented" : true, "arity" : 0, "name" : "scheduler-host", "qname" : "project:scheduler-host", "signature" : "() as string external", "description" : " Returns the host of the scheduler.\n", "summary" : "

    Returns the host of the scheduler.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "string", "description" : "the scheduler host." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 0, "name" : "seed", "qname" : "project:seed", "signature" : "() as string external", "description" : " Returns the project seed.\n", "summary" : "

    Returns the project seed.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "string", "description" : "the project seed" }, "errors" : [ "project:NO-SEED the project seed file cannot be found", "project:SEED-FILE error reading the seed file" ] }, { "isDocumented" : true, "arity" : 0, "name" : "set-seed", "qname" : "project:set-seed", "signature" : "() as string", "description" : " Sets a new random project seed.\n", "summary" : "

    Sets a new random project seed.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "string", "description" : "the project seed" }, "errors" : [ "project:SEED-FILE error reading or writing the seed file" ] }, { "isDocumented" : true, "arity" : 1, "name" : "set-seed", "qname" : "project:set-seed", "signature" : "($seed as string) as empty-sequence()", "description" : " Sets the project seed.\n The specified seed must be at least 8 characters long.\n", "summary" : "

    Sets the project seed.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "seed", "type" : "string", "occurrence" : null, "description" : "
    The new project seed.
    " } ], "returns" : { "type" : "empty-sequence()", "description" : "the project seed" }, "errors" : [ "project:SEED-FILE error reading or writing the seed file", "project:SEED the specified seed is not at least 8 characters long" ] }, { "isDocumented" : true, "arity" : 0, "name" : "token", "qname" : "project:token", "signature" : "() as xs:base64Binary", "description" : " Creates a new project token, that expires after 12 hours.\n", "summary" : "

    Creates a new project token, that expires after 12 hours.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "xs:base64Binary", "description" : "the project token" }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "token", "qname" : "project:token", "signature" : "($expiration as xs:anyAtomicType) as xs:base64Binary", "description" : " Creates a new project token, that expires at the desired date.\n The input to the function contains the expiration information.\n If a duration is used, then the function will create a token expiring after the specified duration.\n If a dateTime is used, then the function will create a token expiring that date.\n If an integer is used, then the function will create a token expiring after the specified number of seconds.\n", "summary" : "

    Creates a new project token, that expires at the desired date.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "expiration", "type" : "xs:anyAtomicType", "occurrence" : null, "description" : "
    describes the expiration date of the token.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the new project token" }, "errors" : [ "project:INVALID-PARAMETER expiration information is invalid (not a duration, date or number of seconds)" ] } ], "variables" : [ ] }, "http://zorba.io/modules/http-client" : { "ns" : "http://zorba.io/modules/http-client", "description" : "

    \n This module provides functions for performing HTTP requests.\n

    \n

    A simple GET request using the get#1 convenience function

    \n
    \n import module namespace http=\"http://zorba.io/modules/http-client\";\n http:get(\"http://www.example.com\")\n 
    \n

    \n This example makes a GET request to example.com and returns the server's response\n as a JSON object.\n

    \n
    \n {\n   \"status\" : 200,\n   \"message\" : \"OK\",\n   \"headers\" : {\n     \"Content-Length\" : \"1270\",\n     \"Date\" : \"Tue, 11 Jun 2013 22:27:10 GMT\",\n     ...\n   },\n   \"body\" : {\n     \"media-type\" : \"text/html\",\n     \"content\" : \"...\"\n   }\n }\n 
    \n

    Response format

    \n

    Most functions in this module (all except options#1)\n return a single JSON item, describing the server's response, as in the previous\n example.\n The server status (integer) and message (string) fields are always present.\n If the server replied sending one or more headers, they are reported\n in an optional headers object. Each header is represented as a single (string)\n field.

    \n

    For non-multipart responses, as in the previous example, the response body,\n if any, is reported as a body object. This object contains both the (string)\n media-type returned by the server and its content.\n The type of the content field is determined by the media-type returned by the\n server. If the media-type indicates that the body content is textual,\n then the content has type string, base64Binary otherwise.\n Specifically, the body content is considered textual only if the MIME-type specified in\n the media-type is one of:\n

      \n
    • \"application/json\"
    • \n
    • \"application/x-javascript\"
    • \n
    • \"application/xml\"
    • \n
    • \"application/xml-external-parsed-entity\"
    • \n
    \n or if the MIME-type starts with \"text/\" or ends with \"+xml\".

    \n

    For multipart responses, multiple bodies are returned, as in the following example:

    \n
    \n {\n   \"status\" : 200,\n   \"message\" : \"OK\",\n   \"headers\" : {\n     \"Date\" : \"Tue, 11 Jun 2013 22:34:13 GMT\",\n     ...\n   },\n   \"multipart\" : {\n     \"boundary\": \"--AaB03x\",\n     \"parts\": [\n       {\n         \"headers\" : {\n            \"Content Disposition: file\",\n            ...\n         },\n         \"body\": {\n           \"media-type\" : \"image/gif\",\n           \"content\" : \"...\"\n         }\n       },\n       {\n         \"body\" : {\n           \"media-type\" : \"text/html\",\n           \"content\" : \"...\"\n         }\n       }\n    ]\n }\n 
    \n

    The multipart field contains both the boundary used to separate parts\n and an array containing all parts. Each part contains its specific headers,\n if any, and the corresponding body.

    \n

    Important Notice Regarding Nondeterministic Functions

    \n

    \n The following functions in this module -\n get#1,\n get-text#1,\n get-binary#1,\n send-nondeterministic-request-1,\n head#1, and\n options#1\n are declared to be nondeterministic, which means that their results\n will not be cached.\n However, they are not declared to be\n sequential, which means that they may be re-ordered during query optimization.\n According to the HTTP RFC, GET, HEAD an OPTIONS requests should not have any side-effects.\n However, in practice it is not uncommon, especially for GET requests, to have side-effects.\n If your application depends on the ordering of side-effects from requests issued through\n these functions, you should either use the send-request()\n function (which is declared sequential), or alternatively\n wrap each call to get() in your own sequential function, to ensure\n that the requests are not reordered.\n Conversely, if you want their results to be cached you can use the\n send-deterministic-request()\n function (which is declared deterministic).\n

    \n

    $href Arguments to Functions

    \n

    Several functions in this module accept a URL argument named $href. In\n all cases, the value passed to $href must be a valid anyURI.\n However, all functions declare $href to be of type string. This\n is for convenience, since you can pass a string literal value (that\n is, a URL in double-quotes spelled out explicitly in your query)\n to an string parameter.

    \n

    Relation to the EXPath http-client module

    \n

    EXPath defines its own http-client\n module, which is available separately.\n There are two primary differences between EXPath's http-client and\n this module:\n

      \n
    1. EXPath does not include the simpler get(), post(), put(), delete(),\n head(), options() and patch() functions defined by this module.
    2. \n
    3. EXPath uses XML to represent request for its send-request() function,\n whereas this module uses JSON.
    4. \n
    5. EXPath specifies that all XML content returned by an HTTP server\n will be parsed and returned as an XML document, whereas all HTML content\n will be tidied up into valid XML, and then parsed into an element.\n This module returns any textual content as string and any binary content\n as base6Binary.
    6. \n
    7. EXPath accepts XML nodes as body in the send-request() function and\n automatically serializes them into a string. The send-request() function\n defined in this module only allows string, base64Binary, and hexBinary\n as body types.\n
    8. \n
    \n

    \n

    \n See the full spec\n of the EXPath http-client module for more information.\n

    \n", "sees" : [ "XQuery 1.1: Function Declaration" ], "authors" : [ "Federico Cavalieri" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://zorba.io/modules/http-client", "prefix" : "http" }, { "uri" : "http://jsoniq.org/function-library", "prefix" : "libjn" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "delete", "qname" : "http:delete", "signature" : "($href as string) as object()", "description" : "

    \n This function makes an HTTP DELETE request to a given URL.\n

    \n", "summary" : "

    \n This function makes an HTTP DELETE request to a given URL.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified request is not valid.", "http:TIMEOUT A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 1, "name" : "get-binary", "qname" : "http:get-binary", "signature" : "($href as string) as object()", "description" : "

    \n This function makes a GET request on a given URL. All returned bodies\n are forced to be interpreted as binary data, and will be returned\n as base64Binary items.\n

    \n", "summary" : "

    \n This function makes a GET request on a given URL.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified href is not valid.", "http:TIMEOUT A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 1, "name" : "get-text", "qname" : "http:get-text", "signature" : "($href as string) as object()", "description" : "

    \n This function makes a GET request to a given URL. All returned bodies\n are forced to be interpreted as textual, with a UTF-8 charset and will\n be returned as string items.\n

    \n", "summary" : "

    \n This function makes a GET request to a given URL.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified href is not valid.", "http:TIMEOUT A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 1, "name" : "get", "qname" : "http:get", "signature" : "($href as string) as object()", "description" : "

    \n This function makes a GET request to a given URL.\n

    \n", "summary" : "

    \n This function makes a GET request to a given URL.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified href is not valid.", "http:TIMEOUT A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 1, "name" : "head", "qname" : "http:head", "signature" : "($href as string) as object()", "description" : "

    \n This function makes an HTTP HEAD request on a given URL.\n

    \n", "summary" : "

    \n This function makes an HTTP HEAD request on a given URL.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified href is not valid.", "http:TIMEOUT A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 1, "name" : "options", "qname" : "http:options", "signature" : "($href as string) as string*", "description" : "

    \n This function makes an HTTP OPTIONS request, which asks the server\n which operations it supports.\n

    \n", "summary" : "

    \n This function makes an HTTP OPTIONS request, which asks the server\n which operations it supports.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " } ], "returns" : { "type" : "string*", "description" : "A sequence of string values of the allowed operations." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified href is not valid.", "http:TIMEOUT A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 2, "name" : "patch", "qname" : "http:patch", "signature" : "($href as string, $body as atomic) as object()", "description" : "

    \n This function makes an HTTP PATCH request to a given URL.\n

    \n

    \n The body passed to this function must be either a string, a base64Binary or\n an hexBinary.\n If it is a string, the Content-Type sent to the server will be \"text/plain\",\n \"application/octet-stream\" otherwise.\n

    \n", "summary" : "

    \n This function makes an HTTP PATCH request to a given URL.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " }, { "name" : "body", "type" : "atomic", "occurrence" : null, "description" : "
    The body which will be sent to the server.
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified request is not valid.", "http:TIMEOUT A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 3, "name" : "patch", "qname" : "http:patch", "signature" : "($href as string, $body as atomic, $content-type as string) as object()", "description" : "

    \n This function makes an HTTP PATCH request to a given URL.\n

    \n

    \n The body passed to this function must be either a string, a base64Binary, or\n an hexBinary.\n In any case, Content-Type of the request sent to the server will\n be $content-type.\n

    \n", "summary" : "

    \n This function makes an HTTP PATCH request to a given URL.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " }, { "name" : "body", "type" : "atomic", "occurrence" : null, "description" : "
    The body which will be sent to the server.
    " }, { "name" : "content-type", "type" : "string", "occurrence" : null, "description" : "
    The content type of $body to send to the server.
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified request is not valid.", "http:TIMEOUT A timeout occurred waiting for the response.", "http:CHARSET The specified charset is unsupported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "post", "qname" : "http:post", "signature" : "($href as string, $body as atomic) as object()", "description" : "

    \n This function makes an HTTP POST request to a given URL.\n

    \n

    \n The body passed to this function must be either a string, a base64Binary, or an\n hexBinary.\n If it is a string, the Content-Type sent to the server will be \"text/plain\",\n \"application/octet-stream\" otherwise.\n

    \n", "summary" : "

    \n This function makes an HTTP POST request to a given URL.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " }, { "name" : "body", "type" : "atomic", "occurrence" : null, "description" : "
    The body which will be sent to the server.
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified request is not valid.", "http:TIMEOUT A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 3, "name" : "post", "qname" : "http:post", "signature" : "($href as string, $body as atomic, $content-type as string) as object()", "description" : "

    \n This function makes an HTTP POST request to a given URL.\n

    \n

    \n The body passed to this function must be either a string, a base64Binary,\n or an hexBinary.\n In any case, Content-Type of the request sent to the server will\n be $content-type.\n

    \n", "summary" : "

    \n This function makes an HTTP POST request to a given URL.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " }, { "name" : "body", "type" : "atomic", "occurrence" : null, "description" : "
    The body which will be sent to the server
    " }, { "name" : "content-type", "type" : "string", "occurrence" : null, "description" : "
    The content type of the body as described above.
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified request is not valid.", "http:TIMEOUT A timeout occurred waiting for the response.", "http:CHARSET The specified charset is unsupported." ] }, { "isDocumented" : true, "arity" : 2, "name" : "put", "qname" : "http:put", "signature" : "($href as string, $body as atomic) as object()", "description" : "

    \n This function makes an HTTP PUT request to a given URL.\n

    \n

    \n The body passed to this function must be either a string, a base64Binary or\n an hexBinary.\n If it is a string, the Content-Type sent to the server will be \"text/plain\",\n \"application/octet-stream\" otherwise.\n

    \n", "summary" : "

    \n This function makes an HTTP PUT request to a given URL.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " }, { "name" : "body", "type" : "atomic", "occurrence" : null, "description" : "
    The body which will be sent to the server.
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified request is not valid.", "http:TIMEOUT A timeout occurred waiting for the response." ] }, { "isDocumented" : true, "arity" : 3, "name" : "put", "qname" : "http:put", "signature" : "($href as string, $body as atomic, $content-type as string) as object()", "description" : "

    \n This function makes an HTTP PUT request to a given URL.\n

    \n

    \n The body passed to this function must be either a string, a base64Binary, or\n an hexBinary.\n In any case, Content-Type of the request sent to the server will\n be $content-type.\n

    \n", "summary" : "

    \n This function makes an HTTP PUT request to a given URL.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "href", "type" : "string", "occurrence" : null, "description" : "
    The URL to which the request will be made (see note above).
    " }, { "name" : "body", "type" : "atomic", "occurrence" : null, "description" : "
    The body which will be sent to the server.
    " }, { "name" : "content-type", "type" : "string", "occurrence" : null, "description" : "
    The content type of $body to send to the server.
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified request is not valid.", "http:TIMEOUT A timeout occurred waiting for the response.", "http:CHARSET The specified charset is unsupported." ] }, { "isDocumented" : true, "arity" : 1, "name" : "send-deterministic-request", "qname" : "http:send-deterministic-request", "signature" : "($request as object()) as object()", "description" : "

    \n This function sends an HTTP request and returns the corresponding response.\n

    \n

    \n This function has the same semantics as send-request-1,\n but is declared as deterministic and thus should only be used when\n the request has no side-effects and behaves deterministic as required by the\n application.\n

    \n", "summary" : "

    \n This function sends an HTTP request and returns the corresponding response.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "request", "type" : "object()", "occurrence" : null, "description" : "
    see request parameter of send-request#1
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified request is not valid.", "http:TIMEOUT A timeout occurred waiting for the response.", "http:FOLLOW Cannot follow a redirect of a POST, PUT, or DELETE request.", "http:CHARSET The specified charset is unsupported." ] }, { "isDocumented" : true, "arity" : 1, "name" : "send-nondeterministic-request", "qname" : "http:send-nondeterministic-request", "signature" : "($request as object()) as object()", "description" : "

    \n This function sends an HTTP request and returns the corresponding response.\n

    \n

    \n This function has the same semantics as send-request-1,\n but is declared as being non deterministic and thus should only be used when\n the request has no side-effects.\n

    \n", "summary" : "

    \n This function sends an HTTP request and returns the corresponding response.

    ", "annotation_str" : " %an:nondeterministic", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "nondeterministic", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "request", "type" : "object()", "occurrence" : null, "description" : "
    see request parameter of send-request#1
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified request is not valid.", "http:TIMEOUT A timeout occurred waiting for the response.", "http:FOLLOW Cannot follow a redirect of a POST, PUT, or DELETE request.", "http:CHARSET The specified charset is unsupported." ] }, { "isDocumented" : true, "arity" : 1, "name" : "send-request", "qname" : "http:send-request", "signature" : "($request as object()) as object()", "description" : "

    \n This function sends an HTTP request and returns the corresponding response.\n

    \n

    \n This function is declared as sequential and should be used whenever the\n request may have side-effects.\n

    \n

    \n The request parameters are specified in the $request JSON object, which\n has the following minimal structure:\n

    \n   {\n     \"href\": \"http://www.example.com\"\n   }\n 
    \n

    \n

    This object specifies a GET request of the URI \"http://www.example.com\"

    \n

    Additional optional parameters can be specified when issuing a request,\n using the following structure:

    \n
    \n  {\n    \"method\": \"POST\",\n    \"href\": \"http://www.example.com\",\n    \"authentication\":\n    {\n      \"username\" : \"user\",\n      \"password\" : \"pass\",\n      \"auth-method\" : \"Basic\"\n    },\n    \"options\":\n    {\n      \"status-only\": true,\n      \"override-media-type\": \"text/plain\",\n      \"follow-redirect\": false,\n      \"timeout\": 30,\n      \"user-agent\": \"Mozilla/5.0\",\n      \"retry\":\n      {\n        \"delay\": [1000, 2000, 5000],\n        \"on-connection-error\": false,\n        \"on-statuses\": [500, 501]\n      }\n    },\n    \"headers\":\n    {\n      \"name\": \"value\",\n      ...\n    },\n    \"body\":\n    {\n      \"media-type\": \"text/plain\",\n      \"content\": \"...\"\n    }\n  }\n
    \n

    \n The method field (string) defines the HTTP verb to use in the HTTP request (i.e., GET, HEAD, OPTIONS,\n POST, PUT, DELETE). If not specified GET will be used.\n The authentication field can be used to specify the credentials and authentication method\n used when issuing a request (e.g, Basic). If the authentication field is specified, all its (string)\n subfields must be specified. If an authentication object is provided, it overrides any\n Authorization header specified in the request.\n Additionally, the following options can be specified:\n

      \n
    • status-only. If true, the response body contents are omitted from the response object.
    • \n
    • override-media-type. Is a MIME type that will override the Content-Type header returned\n by the server. It affects the type of the result body content.
    • \n
    • follow-redirect. Control whether an http redirect is automatically followed or not. If\n it is false, the http redirect is returned as the response. If it is\n true (the default) the function tries to follow the redirect, by\n sending the same request to the new address (including body, headers,\n and authentication credentials.) Maximum one redirect is followed\n (there is no attempt to follow a redirect in response to following a\n first redirect).
    • \n
    • timeout. Is the maximum number of seconds to wait for the server to respond.\n If no response is received withing this time duration, an error is thrown.
    • \n
    • user-agent. The user agent sent to the server when issuing the request.\n If not specified libcurl-agent/1.0 is used.
    • \n
    • retry. The request will be automatically retried in case of connection error\n following mandatory suboptions:\n
        \n
      • delay: an array specifying the milliseconds of wait before each retry.
      • \n
      • on-connection-error: whether to retry the request if a connection to the\n server cannot be estabilished
      • \n
      • on-statuses: an array containing the statuses which will trigger a retry
      • \n
    • \n
    \n

    \n

    One or more headers can be sent to the server, specifying them in an optional headers object.\n Each header is represented as a single (string) field. These headers are overridden if the corresponding\n option/authentication has been specified in the request.

    \n

    For non-multipart request a body object can be specified.\n This object must contain both the desired (string) media-type and its content.\n The type of the content field must be either string, base64Binary, or hexBinary.

    \n

    For multipart requests, multipart object can be specified in place of the body object.\n The multipart object has the following structure:

    \n
    \n  \"multipart\" : {\n    \"boundary\": \"--AaB03x\",\n    \"parts\": [\n      {\n        \"headers\" : {\n           \"Content Disposition: file\",\n           ...\n        },\n        \"body\": {\n          \"media-type\" : \"image/gif\",\n          \"content\" : \"...\"\n        }\n      },\n      {\n        \"body\" : {\n          \"media-type\" : \"text/html\",\n          \"content\" : \"...\"\n        }\n      }\n   ]\n }\n 
    \n

    The multipart field contains an optional (string) field which specifies\n the boundary used to separate each part and an array containing all parts.\n Each part contains its specific headers, if any, and the corresponding body.\n

    \n", "summary" : "

    \n This function sends an HTTP request and returns the corresponding response.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "request", "type" : "object()", "occurrence" : null, "description" : "
    a JSON http-client request object
    " } ], "returns" : { "type" : "object()", "description" : "standard http-client return type." }, "errors" : [ "http:HTTP An HTTP error occurred.", "http:REQUEST The specified request is not valid.", "http:TIMEOUT A timeout occurred waiting for the response.", "http:FOLLOW Cannot follow a redirect of a POST, PUT, or DELETE request.", "http:CHARSET The specified charset is unsupported." ] } ], "variables" : [ ] }, "http://zorba.io/modules/data-cleaning/consolidation" : { "ns" : "http://zorba.io/modules/data-cleaning/consolidation", "description" : "

    This library module provides data consolidation functions that generally take as input a sequence of XML nodes\n and apply some rule in order do decide which node is better suited to represent the entire sequence.

    \n

    \n

    The logic contained in this module is not specific to any particular XQuery implementation,\n although the consolidation functions based on matching sequences against XPath expressions require\n some form of dynamic evaluation for XPath expressions.

    \n", "sees" : [ ], "authors" : [ "Bruno Martins" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/data-cleaning/consolidation", "prefix" : "con" }, { "uri" : "http://zorba.io/modules/data-cleaning/set-similarity", "prefix" : "set" }, { "uri" : "http://zorba.io/modules/data-cleaning/character-based-string-similarity", "prefix" : "simc" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "all-xpaths", "qname" : "con:all-xpaths", "signature" : "($s as element(*)*, $paths as xs:string*) as element(*)*", "description" : "

    Returns the elements from an input sequence of elements that, when matched to a given set of XPath expressions,\n produce a non-empty set of nodes in all the cases.

    \n

    \n

    Example usage :

     all-xpaths( ( <a><b/></a>, <c><d/></c>, <d/>), (\".//b\") ) 

    \n

    \n

    The function invocation in the example above returns :

     (<a><b/></a>) 

    \n", "summary" : "

    Returns the elements from an input sequence of elements that, when matched to a given set of XPath expressions,\n produce a non-empty set of nodes in all the cases.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "element(*)", "occurrence" : "*", "description" : "
    A sequence of elements.
    " }, { "name" : "paths", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings denoting XPath expressions.
    " } ], "returns" : { "type" : "element(*)*", "description" : "The elements that, when matched to the given set of XPath expressions, always return a non-empty set of nodes." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "least-attributes", "qname" : "con:least-attributes", "signature" : "($s) as element(*)", "description" : "

    Returns the single node having the smallest number of descending attributes (attributes at any given depth)\n in a sequence of nodes provided as input.

    \n

    If more then one answer is possible, return the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

    least-attributes( ( <a att1=\"a1\" att2=\"a2\"/>, <b att1=\"a1\" />, <c/> ) )

    \n

    \n

    The function invocation in the example above returns :

    (<c/>)

    \n", "summary" : "

    Returns the single node having the smallest number of descending attributes (attributes at any given depth)\n in a sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "element(*)", "description" : "The node having the smallest number of descending attributes in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "least-distinct-attributes", "qname" : "con:least-distinct-attributes", "signature" : "($s) as element(*)", "description" : "

    Returns the single node having the smallest number of distinct descending attributes (attributes at any\n given depth) in a sequence of nodes provided as input.

    \n

    If more then one answer is possible, return the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

     least-distinct-attributes( ( <a att1=\"a1\" att2=\"a2\"/>, <b att1=\"a1\" />, <c/> ) ) 

    \n

    \n

    The function invocation in the example above returns :

     (<c/>) 

    \n", "summary" : "

    Returns the single node having the smallest number of distinct descending attributes (attributes at any\n given depth) in a sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "element(*)", "description" : "The node having the smallest number of distinct descending attributes in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "least-distinct-elements", "qname" : "con:least-distinct-elements", "signature" : "($s) as element(*)", "description" : "

    Returns the single node having the smallest number of distinct descending elements (sub-elements at any\n given depth) in a sequence of nodes provided as input.

    \n

    If more then one answer is possible, return the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

     least-distinct-elements( ( <a><b/></a>, <b><c/></b>, <d/>) ) 

    \n

    \n

    The function invocation in the example above returns :

     (<d/>) 

    \n", "summary" : "

    Returns the single node having the smallest number of distinct descending elements (sub-elements at any\n given depth) in a sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "element(*)", "description" : "The node having the smallest number of distinct descending elements in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "least-distinct-nodes", "qname" : "con:least-distinct-nodes", "signature" : "($s) as element(*)", "description" : "

    Returns the single node having the smallest number of distinct descending nodes (sub-nodes at any given depth)\n in a sequence of nodes provided as input.

    \n

    If more then one answer is possible, return the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

     least-distinct-nodes( ( <a><b/></a>, <b><c/></b>, <d/>) ) 

    \n

    \n

    The function invocation in the example above returns :

     (<d/>) 

    \n", "summary" : "

    Returns the single node having the smallest number of distinct descending nodes (sub-nodes at any given depth)\n in a sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "element(*)", "description" : "The node having the smallest number of distinct descending nodes in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "least-elements", "qname" : "con:least-elements", "signature" : "($s) as element(*)", "description" : "

    Returns the single node having the smallest number of descending elements (sub-elements at any given depth)\n in a sequence of nodes provided as input.

    \n

    If more then one answer is possible, return the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

    least-elements( ( <a><b/></a>, <b><c/></b>, <d/>) )

    \n

    \n

    The function invocation in the example above returns :

    (<d/>)

    \n", "summary" : "

    Returns the single node having the smallest number of descending elements (sub-elements at any given depth)\n in a sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "element(*)", "description" : "The node having the smallest number of descending elements in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "least-frequent", "qname" : "con:least-frequent", "signature" : "($s) as item()", "description" : "

    Returns the single less frequent node in a sequence of nodes provided as input.

    \n

    If more then one answer is possible, return the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

    least-frequent( ( \"a\", \"a\", \"b\") )

    \n

    \n

    The function invocation in the example above returns :

    (\"b\")

    \n", "summary" : "

    Returns the single less frequent node in a sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "item()", "description" : "The least frequent node in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "least-nodes", "qname" : "con:least-nodes", "signature" : "($s) as element(*)", "description" : "

    Returns the single node having the smallest number of descending nodes (sub-nodes at any given depth)\n in a sequence of nodes provided as input.

    \n

    If more then one answer is possible, return the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

    least-nodes( ( <a><b/></a>, <b><c/></b>, <d/>) )

    \n

    \n

    The function invocation in the example above returns :

    (<d/>)

    \n", "summary" : "

    Returns the single node having the smallest number of descending nodes (sub-nodes at any given depth)\n in a sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "element(*)", "description" : "The node having the smallest number of descending nodes in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "least-similar-edit-distance", "qname" : "con:least-similar-edit-distance", "signature" : "($s as xs:string*, $m as xs:string) as xs:string?", "description" : "

    Returns the single least similar string, in terms of the edit distance metric towards an input string,\n in a sequence of strings provided as input. If more than one string has a minimum similarity (a maximum\n value for the edit distance metric), return the first string according to the order of the input sequence.

    \n

    \n

    Example usage :

    least-similar-edit-distance( ( \"aaabbbccc\", \"aaabbb\", \"eeefff\" ), \"aaab\" )

    \n

    \n

    The function invocation in the example above returns :

    ( \"eeefff\" )

    \n", "summary" : "

    Returns the single least similar string, in terms of the edit distance metric towards an input string,\n in a sequence of strings provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings.
    " }, { "name" : "m", "type" : "xs:string", "occurrence" : null, "description" : "
    The string towards which we want to measure the edit distance.
    " } ], "returns" : { "type" : "xs:string?", "description" : "The least similar string in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "least-tokens", "qname" : "con:least-tokens", "signature" : "($s as xs:string*, $r as xs:string) as xs:string?", "description" : "

    Returns the single shortest string, in terms of the number of tokens, in a sequence of strings provided as input.

    \n

    If more then one answer is possible, return the first string according to the order of the input sequence.

    \n

    \n

    Example usage :

    least-tokens( ( \"a b c\", \"a b\", \"a\"), \" +\" )

    \n

    \n

    The function invocation in the example above returns :

    (\"a\")

    \n", "summary" : "

    Returns the single shortest string, in terms of the number of tokens, in a sequence of strings provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings.
    " }, { "name" : "r", "type" : "xs:string", "occurrence" : null, "description" : "
    A regular expression forming the delimiter character(s) which mark the boundaries between adjacent tokens.
    " } ], "returns" : { "type" : "xs:string?", "description" : "The shortest string in the input sequence, in terms of the number of tokens." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "least-xpaths", "qname" : "con:least-xpaths", "signature" : "($s as element(*)*, $paths as xs:string*) as element(*)*", "description" : "

    Returns the single element from an input sequence of elements that matches the smallest number of\n XPath expressions from a given set, producing a non-empty set of nodes.

    \n

    If more then one answer is possible, return the first element according to the order of the input sequence.

    \n

    \n

    Example usage :

     least-xpaths( ( <a><b/></a>, <d><c/><b/></d>, <d/>) , (\".//b\", \".//c\") ) 

    \n

    \n

    The function invocation in the example above returns :

     ( $lt;d/> ) 

    \n", "summary" : "

    Returns the single element from an input sequence of elements that matches the smallest number of\n XPath expressions from a given set, producing a non-empty set of nodes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "element(*)", "occurrence" : "*", "description" : "
    A sequence of elements.
    " }, { "name" : "paths", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings denoting XPath expressions.
    " } ], "returns" : { "type" : "element(*)*", "description" : "The element that matches the smallest number of XPath expressions producing a non-empty set of nodes." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "longest", "qname" : "con:longest", "signature" : "($s as xs:string*) as xs:string?", "description" : "

    Returns the single longest string, in terms of the number of characters, in a sequence of strings provided as input.

    \n

    If more then one answer is possible, return the first string according to the order of the input sequence.

    \n

    \n

    Example usage :

    con:longest( ( \"a\", \"aa\", \"aaa\") )

    \n

    \n

    The function invocation in the example above returns :

    (\"aaa\")

    \n", "summary" : "

    Returns the single longest string, in terms of the number of characters, in a sequence of strings provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings.
    " } ], "returns" : { "type" : "xs:string?", "description" : "The longest string in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "matching", "qname" : "con:matching", "signature" : "($s as xs:string*, $r as xs:string) as xs:string*", "description" : "

    Returns the strings from an input sequence of strings that match a particular regular expression.

    \n

    \n

    Example usage :

    matching( ( \"a A b\", \"c AAA d\", \"e BB f\"), \"A+\" )

    \n

    \n

    The function invocation in the example above returns :

    ( \"a A b\", \"c AAA d\")

    \n", "summary" : "

    Returns the strings from an input sequence of strings that match a particular regular expression.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings.
    " }, { "name" : "r", "type" : "xs:string", "occurrence" : null, "description" : "
    The regular expression to be used in the matching.
    " } ], "returns" : { "type" : "xs:string*", "description" : "The strings in the input sequence that match the input regular expression." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "most-attributes", "qname" : "con:most-attributes", "signature" : "($s) as element(*)", "description" : "

    Returns the single node having the largest number of descending attributes (attributes at any given depth)\n in a sequence of nodes provided as input.

    \n

    If more then one answer is possible, return the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

    most-attributes( ( <a att1=\"a1\" att2=\"a2\"/>, <b att1=\"a1\" />, <c/> ) )

    \n

    \n

    The function invocation in the example above returns :

    (<a att1=\"a1\" att2=\"a2\"/>)

    \n", "summary" : "

    Returns the single node having the largest number of descending attributes (attributes at any given depth)\n in a sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "element(*)", "description" : "The node having the largest number of descending attributes in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "most-distinct-attributes", "qname" : "con:most-distinct-attributes", "signature" : "($s) as element(*)", "description" : "

    Returns the single node having the largest number of distinct descending attributes (attributes at any\n given depth) in a sequence of nodes provided as input.

    \n

    If more then one answer is possible, return the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

    most-distinct-attributes( ( <a att1=\"a1\" att2=\"a2\" att3=\"a3\"/>, <a att1=\"a1\" att2=\"a2\"><b att2=\"a2\" /></a>, <c/> ) )

    \n

    \n

    The function invocation in the example above returns :

    (<a att1=\"a1\" att2=\"a2\" att3=\"a3\"/>)

    \n", "summary" : "

    Returns the single node having the largest number of distinct descending attributes (attributes at any\n given depth) in a sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "element(*)", "description" : "The node having the largest number of distinct descending attributes in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "most-distinct-elements", "qname" : "con:most-distinct-elements", "signature" : "($s) as element(*)", "description" : "

    Returns the single node having the largest number of distinct descending elements (sub-elements at any\n given depth) in a sequence of nodes provided as input.

    \n

    If more then one answer is possible, return the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

    most-distinct-elements( ( <a><b/><c/><d/></a>, <a><b/><b/><c/></a>, <a/> ) )

    \n

    \n

    The function invocation in the example above returns :

    (<a><b/><c/><d/></a>)

    \n", "summary" : "

    Returns the single node having the largest number of distinct descending elements (sub-elements at any\n given depth) in a sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "element(*)", "description" : "The node having the largest number of distinct descending elements in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "most-distinct-nodes", "qname" : "con:most-distinct-nodes", "signature" : "($s) as element(*)", "description" : "

    Returns the single node having the largest number of distinct descending nodes (sub-nodes at any given depth) in\n a sequence of nodes provided as input.

    \n

    If more then one answer is possible, return the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

    most-distinct-nodes( ( <a><b/></a>, <a><a/></a>, <b/>) )

    \n

    \n

    The function invocation in the example above returns :

    (<a><b/></a>)

    \n", "summary" : "

    Returns the single node having the largest number of distinct descending nodes (sub-nodes at any given depth) in\n a sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "element(*)", "description" : "The node having the largest number of distinct descending nodes in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "most-elements", "qname" : "con:most-elements", "signature" : "($s) as element(*)", "description" : "

    Returns the single node having the largest number of descending elements (sub-elements at any given depth)\n in a sequence of nodes provided as input.

    \n

    If more then one answer is possible, return the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

    most-elements( ( <a><b/></a>, <a/>, <b/>) )

    \n

    \n

    The function invocation in the example above returns :

    (<a><b/></a>)

    \n", "summary" : "

    Returns the single node having the largest number of descending elements (sub-elements at any given depth)\n in a sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "element(*)", "description" : "The node having the largest number of descending elements in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "most-frequent", "qname" : "con:most-frequent", "signature" : "($s) as item()", "description" : "

    Returns the single most frequent node in a sequence of nodes provided as input.

    \n

    If more then one answer is possible, returns the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

    most-frequent( ( \"a\", \"a\", \"b\") )

    \n

    \n

    The function invocation in the example above returns :

    (\"a\")

    \n", "summary" : "

    Returns the single most frequent node in a sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "item()", "description" : "The most frequent node in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "most-nodes", "qname" : "con:most-nodes", "signature" : "($s) as element(*)", "description" : "

    Returns the single node having the largest number of descending nodes (sub-nodes at any given depth) in a\n sequence of nodes provided as input.

    \n

    If more then one answer is possible, return the first node according to the order of the input sequence.

    \n

    \n

    Example usage :

    most-nodes( ( <a><b/></a>, <a/>, <b/>) )

    \n

    \n

    The function invocation in the example above returns :

    (<a><b/></a>)

    \n", "summary" : "

    Returns the single node having the largest number of descending nodes (sub-nodes at any given depth) in a\n sequence of nodes provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A sequence of nodes.
    " } ], "returns" : { "type" : "element(*)", "description" : "The node having the largest number of descending nodes in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "most-similar-edit-distance", "qname" : "con:most-similar-edit-distance", "signature" : "($s as xs:string*, $m as xs:string) as xs:string?", "description" : "

    Returns the single most similar string, in terms of the edit distance metric towards an input string,\n in a sequence of strings provided as input. If more than one string has a maximum similarity (a minimum\n value for the edit distance metric), the function return the first string according to the order of the\n input sequence.

    \n

    \n

    Example usage :

    most-similar-edit-distance( ( \"aaabbbccc\", \"aaabbb\", \"eeefff\" ), \"aaab\" )

    \n

    \n

    The function invocation in the example above returns :

    ( \"aaabbb\" )

    \n", "summary" : "

    Returns the single most similar string, in terms of the edit distance metric towards an input string,\n in a sequence of strings provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings.
    " }, { "name" : "m", "type" : "xs:string", "occurrence" : null, "description" : "
    The string towards which we want to measure the edit distance.
    " } ], "returns" : { "type" : "xs:string?", "description" : "The most similar string in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "most-tokens", "qname" : "con:most-tokens", "signature" : "($s as xs:string*, $r as xs:string) as xs:string?", "description" : "

    Returns the single longest string, in terms of the number of tokens, in a sequence of strings provided as input.

    \n

    If more then one answer is possible, return the first string according to the order of the input sequence.

    \n

    \n

    Example usage :

    most-tokens( ( \"a b c\", \"a b\", \"a\"), \" +\" )

    \n

    \n

    The function invocation in the example above returns :

    (\"a b c\")

    \n", "summary" : "

    Returns the single longest string, in terms of the number of tokens, in a sequence of strings provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings.
    " }, { "name" : "r", "type" : "xs:string", "occurrence" : null, "description" : "
    A regular expression forming the delimiter character(s) which mark the boundaries between adjacent tokens.
    " } ], "returns" : { "type" : "xs:string?", "description" : "The longest string in the input sequence, in terms of the number of tokens." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "most-xpaths", "qname" : "con:most-xpaths", "signature" : "($s as element(*)*, $paths as xs:string*) as element(*)*", "description" : "

    Returns the single element from an input sequence of elements that matches the largest number of\n XPath expressions from a given set, producing a non-empty set of nodes.

    \n

    If more then one answer is possible, return the first element according to the order of the input sequence.

    \n

    \n

    Example usage :

     most-xpaths( ( <a><b/></a>, <d><c/><b/></d>, <d/>) , (\".//b\", \".//c\") ) 

    \n

    \n

    The function invocation in the example above returns :

     ( <d><c/><b/></d> ) 

    \n", "summary" : "

    Returns the single element from an input sequence of elements that matches the largest number of\n XPath expressions from a given set, producing a non-empty set of nodes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "element(*)", "occurrence" : "*", "description" : "
    A sequence of elements.
    " }, { "name" : "paths", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings denoting XPath expressions.
    " } ], "returns" : { "type" : "element(*)*", "description" : "The element that matches the largest number of XPath expressions producing a non-empty set of nodes." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "shortest", "qname" : "con:shortest", "signature" : "($s as xs:string*) as xs:string?", "description" : "

    Returns the single shortest string, in terms of the number of characters, in a sequence of strings provided as input.

    \n

    If more then one answer is possible, return the first string according to the order of the input sequence.

    \n

    \n

    Example usage :

    shortest( ( \"a\", \"aa\", \"aaa\") )

    \n

    \n

    The function invocation in the example above returns :

    (\"a\")

    \n", "summary" : "

    Returns the single shortest string, in terms of the number of characters, in a sequence of strings provided as input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings.
    " } ], "returns" : { "type" : "xs:string?", "description" : "The shortest string in the input sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "some-xpaths", "qname" : "con:some-xpaths", "signature" : "($s as element(*)*, $paths as xs:string*) as element(*)*", "description" : "

    Returns the elements from a sequence of elements that, when matched to a given set of XPath expressions,\n produce a non-empty set of nodes for some of the cases.

    \n

    \n

    Example usage :

     some-xpaths( ( <a><b/></a>, <d><c/></d>, <d/>), (\".//b\", \".//c\") ) 

    \n

    \n

    The function invocation in the example above returns :

     ( <a><b/></a> , <d><c/></d> ) 

    \n", "summary" : "

    Returns the elements from a sequence of elements that, when matched to a given set of XPath expressions,\n produce a non-empty set of nodes for some of the cases.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "element(*)", "occurrence" : "*", "description" : "
    A sequence of elements.
    " }, { "name" : "paths", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings denoting XPath expressions.
    " } ], "returns" : { "type" : "element(*)*", "description" : "The elements that, when matched to the given set of XPath expressions, return a non-empty set of nodes for at least one of the cases." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "superstring", "qname" : "con:superstring", "signature" : "($s as xs:string*) as xs:string?", "description" : "

    Returns the single string, from an input sequence of strings, that appears more frequently as part\n of the other strings in the sequence. If no such string exists, the function returns an empty sequence.

    \n

    If more then one answer is possible, the function returns the first string according to the order of the input sequence.

    \n

    \n

    Example usage :

    super-string( ( \"aaa bbb ccc\", \"aaa bbb\", \"aaa ddd\", \"eee fff\" ) )

    \n

    \n

    The function invocation in the example above returns :

    ( \"aaa bbb\" )

    \n", "summary" : "

    Returns the single string, from an input sequence of strings, that appears more frequently as part\n of the other strings in the sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "xs:string", "occurrence" : "*", "description" : "
    A sequence of strings.
    " } ], "returns" : { "type" : "xs:string?", "description" : "The string that appears more frequently as part of the other strings in the sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "validating-schema", "qname" : "con:validating-schema", "signature" : "($s as element(*)*, $schema as element(*)) as element(*)*", "description" : "

    Returns the nodes from an input sequence of nodes that validate against a given XML Schema.

    \n

    \n

    Example usage :

     validating-schema ( ( <a/> , <b/> ), <xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"><xs:element name=\"a\" /></xs:schema> ) 

    \n

    \n

    The function invocation in the example above returns :

     ( <a/> ) 

    \n", "summary" : "

    Returns the nodes from an input sequence of nodes that validate against a given XML Schema.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : "element(*)", "occurrence" : "*", "description" : "
    A sequence of elements.
    " }, { "name" : "schema", "type" : "element(*)", "occurrence" : null, "description" : "
    An element encoding an XML Schema.
    " } ], "returns" : { "type" : "element(*)*", "description" : "The nodes that validate against the XML Schema. Attention : This function is still not implemented. " }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/node" : { "ns" : "http://zorba.io/modules/node", "description" : " This module defines a set of function which can be used\n to determine (1) the relationship between two nodes (e.g. if one\n is the ancestor if another) and (2) properties of given\n nodes (e.g. their level in the tree).\n The same functionality can be achieved with simple XPath expressions.\n However, please note that using the functions in this modules instead\n of path expressions guarantees better performance.\n", "sees" : [ ], "authors" : [ "Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/node", "prefix" : "node" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "ancestor-of", "qname" : "node:ancestor-of", "signature" : "($node1 as node(), $node2 as node()) as xs:boolean external", "description" : " Determines whether the node given as second argument is an\n ancestor of the node given as first argument.\n", "summary" : "

    Determines whether the node given as second argument is an\n ancestor of the node given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node1", "type" : "node()", "occurrence" : null, "description" : "
    the potential descendant
    " }, { "name" : "node2", "type" : "node()", "occurrence" : null, "description" : "
    the potential ancestor
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if $node2 is an ancestor of $node1; false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "child-of", "qname" : "node:child-of", "signature" : "($node1 as node(), $node2 as node()) as xs:boolean external", "description" : " Determines whether the node given as second argument is a\n child of the node given as first argument.\n", "summary" : "

    Determines whether the node given as second argument is a\n child of the node given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node1", "type" : "node()", "occurrence" : null, "description" : "
    the potential parent
    " }, { "name" : "node2", "type" : "node()", "occurrence" : null, "description" : "
    the potential child
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if $node2 is a child of $node1; false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "copy", "qname" : "node:copy", "signature" : "($input as node()*) as node()* external", "description" : " Return a deep copy of every given node according to the properties\n specified in the static context of the invoking module.

    \n Please note that a copy of a node is parentless.\n", "summary" : "

    Return a deep copy of every given node according to the properties\n specified in the static context of the invoking module.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "input", "type" : "node()", "occurrence" : "*", "description" : "
    the node to copy
    " } ], "returns" : { "type" : "node()*", "description" : "a deep copy of every node in the input sequence or the empty sequence if $input is the empty sequence." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "descendant-of", "qname" : "node:descendant-of", "signature" : "($node1 as node(), $node2 as node()) as xs:boolean external", "description" : " Determines whether the node given as second argument is a\n descendant of the node given as first argument.\n", "summary" : "

    Determines whether the node given as second argument is a\n descendant of the node given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node1", "type" : "node()", "occurrence" : null, "description" : "
    the potential ancestor
    " }, { "name" : "node2", "type" : "node()", "occurrence" : null, "description" : "
    the potential descendant
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if $node2 is a descendant of $node1; false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "following-of", "qname" : "node:following-of", "signature" : "($node1 as node(), $node2 as node()) as xs:boolean external", "description" : " Determines whether the node given as second argument is\n following the node given as first argument.\n", "summary" : "

    Determines whether the node given as second argument is\n following the node given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node1", "type" : "node()", "occurrence" : null, "description" : "
    the potential preceding node
    " }, { "name" : "node2", "type" : "node()", "occurrence" : null, "description" : "
    the potential following node
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if $node2 is following the node $node1; false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "following-sibling-of", "qname" : "node:following-sibling-of", "signature" : "($node1 as node(), $node2 as node()) as xs:boolean external", "description" : " Determines whether the node given as second argument is a\n following-sibling of the node given as first argument.\n", "summary" : "

    Determines whether the node given as second argument is a\n following-sibling of the node given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node1", "type" : "node()", "occurrence" : null, "description" : "
    the potential preceding-sibling
    " }, { "name" : "node2", "type" : "node()", "occurrence" : null, "description" : "
    the potential following-sibling
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if $node2 is a following-sibling of $node1; false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "least-common-ancestor", "qname" : "node:least-common-ancestor", "signature" : "($node1 as node(), $node2 as node()) as node()? external", "description" : " Computes the least common ancestor of two given nodes in\n the tree.\n", "summary" : "

    Computes the least common ancestor of two given nodes in\n the tree.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node1", "type" : "node()", "occurrence" : null, "description" : "
    the first node
    " }, { "name" : "node2", "type" : "node()", "occurrence" : null, "description" : "
    the second node
    " } ], "returns" : { "type" : "node()?", "description" : "the least common ancestor of the two given nodes or the empty sequence if the two nodes are not part of the same tree." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "level", "qname" : "node:level", "signature" : "($node as node()) as xs:integer external", "description" : " Computes the level of a given node in the tree.\n Note: The first level has the number one.\n", "summary" : "

    Computes the level of a given node in the tree.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node", "type" : "node()", "occurrence" : null, "description" : "
    the node for which the level should be computed
    " } ], "returns" : { "type" : "xs:integer", "description" : "The level as xs:integer of the given node in the tree." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "parent-of", "qname" : "node:parent-of", "signature" : "($node1 as node(), $node2 as node()) as xs:boolean external", "description" : " Determines whether the node given as second argument is a\n parent of the node given as first argument.\n", "summary" : "

    Determines whether the node given as second argument is a\n parent of the node given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node1", "type" : "node()", "occurrence" : null, "description" : "
    the potential child
    " }, { "name" : "node2", "type" : "node()", "occurrence" : null, "description" : "
    the potential parent
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if $node2 is a parent of $node1; false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "preceding-of", "qname" : "node:preceding-of", "signature" : "($node1 as node(), $node2 as node()) as xs:boolean external", "description" : " Determines whether the node given as second argument is\n preceding the node given as first argument.\n", "summary" : "

    Determines whether the node given as second argument is\n preceding the node given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node1", "type" : "node()", "occurrence" : null, "description" : "
    the potential following node
    " }, { "name" : "node2", "type" : "node()", "occurrence" : null, "description" : "
    the potential preceding node
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if $node2 is preceding the node $node1; false otherwise." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "preceding-sibling-of", "qname" : "node:preceding-sibling-of", "signature" : "($node1 as node(), $node2 as node()) as xs:boolean external", "description" : " Determines whether the node given as second argument is a\n preceding-sibling of the node given as first argument.\n", "summary" : "

    Determines whether the node given as second argument is a\n preceding-sibling of the node given as first argument.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "node1", "type" : "node()", "occurrence" : null, "description" : "
    the potential following-sibling
    " }, { "name" : "node2", "type" : "node()", "occurrence" : null, "description" : "
    the potential preceding-sibling
    " } ], "returns" : { "type" : "xs:boolean", "description" : "true if $node2 is a preceding-sibling of $node1; false otherwise." }, "errors" : [ ] } ], "variables" : [ ] }, "http://zorba.io/modules/archive" : { "ns" : "http://zorba.io/modules/archive", "description" : " This module provides functionality to work with (possibly compressed)\n archives. For example, it provides functions to retrieve the names or\n extract the values of several entries in a ZIP archive. Moreover,\n there exist functions that allow to create or update archives.

    \n The following archive formats and compression algorithms are supported:\n

      \n
    • ZIP (with compression DEFLATE or STORE)
    • \n
    • TAR (with compression GZIP)
    • \n
    \n

    \n", "sees" : [ ], "authors" : [ "Luis Rodgriguez, Juan Zacarias, and Matthias Brantner" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/archive", "prefix" : "a" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "create", "qname" : "a:create", "signature" : "($entries as item()*, $contents as item()*) as xs:base64Binary external", "description" : " Creates a new ZIP archive out of the given entries and contents.

    \n All entries are compressed with the DEFLATE compression algorithm.

    \n The parameters $entries and $contents have the same meaning as for\n the function a:create with three arguments.

    \n Entry entries can include a type element, this element can have one\n of two possible values: \"regular\" or \"directory\". If \"regular\" is\n specified then the entry will be created as a regular file; if \"directory\"\n is specified then the entry will be created as a directory, no contents\n will be read from $contents in this case. If no value is specified for type\n then it will be set to \"regular\".

    \n Example:\n

    \n $zip-file := a:create(\n    ({ \"encoding\" : \"ISO-8859-1\", \"type\" : \"directory\", \"name\" : \"dir1\" }, \"dir1/file1\"),\n    (\"file contents\"))\n 
    \n

    \n", "summary" : "

    Creates a new ZIP archive out of the given entries and contents.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "entries", "type" : "item()", "occurrence" : "*", "description" : "
    the meta data for the entries in the archive. Each entry can be of type xs:string or a JSON oibject describing the entry.
    " }, { "name" : "contents", "type" : "item()", "occurrence" : "*", "description" : "
    the content for the archive. Each item in the sequence can be of type xs:string or xs:base64Binary.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the generated archive as xs:base64Binary" }, "errors" : [ "a:ENTRY-COUNT-MISMATCH if the number of entries that don't describe directories differs from the number of items in the $contents sequence: count($non-directory-entries) ne count($contents)", "a:INVALID-ENTRY-VALS if a values in an entry object are invalid", "a:INVALID-ENCODING if a given encoding is invalid or not supported", "err:FORG0006 if an item in the contents sequence is not of type xs:string or xs:base64Binary" ] }, { "isDocumented" : true, "arity" : 3, "name" : "create", "qname" : "a:create", "signature" : "($entries as item()*, $contents as item()*, $options as object()) as xs:base64Binary external", "description" : " Creates a new archive out of the given entries and contents.

    \n The $entries arguments provides meta data for each entry in the archive.\n For example, the name of the entry (mandatory) or the last-modified date\n (optional). An entry can either be of type xs:string to describe the entry\n name or of type xs:base64Binary to provide additional meta data.

    \n The $contents sequence provides the data (xs:string or xs:base64Binary) for\n the entries that should be included in the archive. Its length needs to\n match the length of the entries in the $entries sequence that don't describe\n directory entries (a:ARCH0001). All items of type xs:base64Binary are decoded\n before being added to the archive.

    \n For each entry, the name, last-modified date and time, and compression\n can be specified. In addition, an encoding can be specified which is used to\n store entries of type xs:string. If no last-modified attribute is given, the\n default is the current date and time. The compression is useful if various\n entries in a ZIP archive are compressed using different compression\n algorithms (i.e. store or deflate).

    \n For example, the following sequence may be used to describe an archive\n containing two elements:

    \n

    {\n   \"last-modified\" : \"{fn:current-dateTime()}\"\n   \"name\" : \"myfile.txt\"\n },\n {\n   \"encoding\" : \"ISO-8859-1\",\n   \"compression\" : \"store\",\n   \"name\" : \"dir/myfile.xml\"\n }\n 
    \n

    \n The $options argument may be used to describe general options for the\n archive. For example, the following options can be used to create a ZIP\n archive in which all entries are compressed with the DEFLATE compression\n algorithm:

    \n

    {\n   \"format\" : \"ZIP\",\n   \"compression\" : \"DEFLATE\"\n }\n 
    \n

    \n The result of the function is the generated archive as a item of type\n xs:base64Binary.

    \n", "summary" : "

    Creates a new archive out of the given entries and contents.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "entries", "type" : "item()", "occurrence" : "*", "description" : "
    the meta data for the entries in the archive. Each entry can be of type xs:string or an JSON object describing the entry.
    " }, { "name" : "contents", "type" : "item()", "occurrence" : "*", "description" : "
    the content for the archive. Each item in the sequence can be of type xs:string or xs:base64Binary.
    " }, { "name" : "options", "type" : "object()", "occurrence" : null, "description" : "
    the options used to generate the archive.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the generated archive as xs:base64Binary" }, "errors" : [ "a:ENTRY-COUNT-MISMATCH if the number of entries describing non-directories differs from the number of items in the $contents sequence: count($non-directoy-entries) ne count($contents)", "a:INVALID-OPTIONS if the options argument contains invalid values", "a:INVALID-ENTRY-VALS if any values in an entry are invalid", "a:INVALID-ENCODING if a given encoding is invalid or not supported", "a:DIFFERENT-COMPRESSIONS-NOT-SUPPORTED if different compression algorithms were selected but the actual version of libarchive doesn't support it.", "err:FORG0006 if an item in the contents sequence is not of type xs:string or xs:base64Binary" ] }, { "isDocumented" : true, "arity" : 2, "name" : "delete", "qname" : "a:delete", "signature" : "($archive as xs:base64Binary, $entry-names as xs:string*) as xs:base64Binary external", "description" : " Deletes entries from an archive.

    \n", "summary" : "

    Deletes entries from an archive.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the archive to extract the entries from as xs:base64Binary
    " }, { "name" : "entry-names", "type" : "xs:string", "occurrence" : "*", "description" : "
    a sequence of names for entries which should be deleted
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the updated base64Binary" }, "errors" : [ "a:CORRUPTED-ARCHIVE if $archive is not an archive or corrupted" ] }, { "isDocumented" : true, "arity" : 1, "name" : "entries", "qname" : "a:entries", "signature" : "($archive as xs:base64Binary) as object()* external", "description" : " Returns the header information of all entries in the given archive as a JSON\n objects sequence.

    \n Such information includes the name of the entry, the uncompressed size,\n as well as the last-modified timestamp. Note that not all values are\n available in every archive.

    \n", "summary" : "

    Returns the header information of all entries in the given archive as a JSON\n objects sequence.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the archive to list the entries from as xs:base64Binary
    " } ], "returns" : { "type" : "object()*", "description" : "a sequence of strings, one for each entry in the archive" }, "errors" : [ "a:CORRUPTED-ARCHIVE if $archive is not an archive or corrupted" ] }, { "isDocumented" : true, "arity" : 1, "name" : "extract-binary", "qname" : "a:extract-binary", "signature" : "($archive as xs:base64Binary) as xs:base64Binary* external", "description" : " Returns the entries identified by the given paths from the archive\n as base64Binary.

    \n", "summary" : "

    Returns the entries identified by the given paths from the archive\n as base64Binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the archive to extract the entries from as xs:base64Binary
    " } ], "returns" : { "type" : "xs:base64Binary*", "description" : "one xs:base64Binary item for the contents of each entry in the archive" }, "errors" : [ "a:CORRUPTED-ARCHIVE if $archive is not an archive or corrupted" ] }, { "isDocumented" : true, "arity" : 2, "name" : "extract-binary", "qname" : "a:extract-binary", "signature" : "($archive as xs:base64Binary, $entry-names as xs:string*) as xs:base64Binary* external", "description" : " Returns the entries identified by the given paths from the archive\n as base64Binary.

    \n", "summary" : "

    Returns the entries identified by the given paths from the archive\n as base64Binary.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the archive to extract the entries from as xs:base64Binary
    " }, { "name" : "entry-names", "type" : "xs:string", "occurrence" : "*", "description" : "
    a sequence of names for entries which should be extracted
    " } ], "returns" : { "type" : "xs:base64Binary*", "description" : "a sequence of xs:base64Binary itmes for the given sequence of names or the empty sequence if no entries match the given names." }, "errors" : [ "a:CORRUPTED-ARCHIVE if $archive is not an archive or corrupted" ] }, { "isDocumented" : true, "arity" : 1, "name" : "extract-text", "qname" : "a:extract-text", "signature" : "($archive as xs:base64Binary) as xs:string* external", "description" : " Extracts the contents of all entries in the given archive as text\n using UTF-8 as default encoding.

    \n", "summary" : "

    Extracts the contents of all entries in the given archive as text\n using UTF-8 as default encoding.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the archive to extract the entries from as xs:base64Binary
    " } ], "returns" : { "type" : "xs:string*", "description" : "one string for the contents of each entry in the archive" }, "errors" : [ "a:CORRUPTED-ARCHIVE if $archive is not an archive or corrupted", "err:FOCH0001 if any of the entries contains invalid utf-8 characters" ] }, { "isDocumented" : true, "arity" : 2, "name" : "extract-text", "qname" : "a:extract-text", "signature" : "($archive as xs:base64Binary, $entry-names as xs:string*) as xs:string* external", "description" : " Extracts the contets of the entries identified by a given sequence of\n names as text.\n The default encoding used to read the string is UTF-8.

    \n", "summary" : "

    Extracts the contets of the entries identified by a given sequence of\n names as text.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the archive to extract the entries from as xs:base64Binary
    " }, { "name" : "entry-names", "type" : "xs:string", "occurrence" : "*", "description" : "
    a sequence of names for entries which should be extracted
    " } ], "returns" : { "type" : "xs:string*", "description" : "a sequence of strings for the given sequence of names or the empty sequence if no entries match the given names." }, "errors" : [ "a:CORRUPTED-ARCHIVE if $archive is not an archive or corrupted", "err:FOCH0001 if any of the entries requested contains invalid utf-8 characters" ] }, { "isDocumented" : true, "arity" : 3, "name" : "extract-text", "qname" : "a:extract-text", "signature" : "($archive as xs:base64Binary, $entry-names as xs:string*, $encoding as xs:string) as xs:string* external", "description" : " Extracts the contets of the entries identified by a given sequence of\n names as text. Each entry is treated with the given encoding.

    \n", "summary" : "

    Extracts the contets of the entries identified by a given sequence of\n names as text.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the archive to extract the entries from as xs:base64Binary
    " }, { "name" : "entry-names", "type" : "xs:string", "occurrence" : "*", "description" : "
    a sequence of entry names that should be extracted
    " }, { "name" : "encoding", "type" : "xs:string", "occurrence" : null, "description" : "
    a encoding for transcoding each of the extracted entries
    " } ], "returns" : { "type" : "xs:string*", "description" : "a sequence of strings for the given sequence of names or the empty sequence if no entries match the given names." }, "errors" : [ "a:CORRUPTED-ARCHIVE if $archive is not an archive or corrupted", "a:INVALID-ENCODING if the given $encoding is invalid or not supported", "err:FOCH0001 if a transcoding error happens" ] }, { "isDocumented" : true, "arity" : 1, "name" : "options", "qname" : "a:options", "signature" : "($archive as xs:base64Binary) as object() external", "description" : " Returns the algorithm and format options as a JSON object for a given archive.\n For example, for a ZIP archive, the following options element\n would be returned:

    \n

    {\n   \"format\" : \"ZIP\",\n   \"compression\" : \"DEFLATE\"\n }\n 
    \n

    \n", "summary" : "

    Returns the algorithm and format options as a JSON object for a given archive.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the archive as xs:base64Binary
    " } ], "returns" : { "type" : "object()", "description" : "the algorithm and format options as a JSON object" }, "errors" : [ "a:CORRUPTED-ARCHIVE if $archive is not an archive or corrupted" ] }, { "isDocumented" : true, "arity" : 3, "name" : "update", "qname" : "a:update", "signature" : "($archive as xs:base64Binary, $entries as item()*, $contents as item()*) as xs:base64Binary external", "description" : " Adds and replaces entries in an archive according to\n the given spec. The contents can be string and base64Binary items.

    \n The parameters $entries and $contents have the same meaning as for\n the function a:create with three arguments.

    \n", "summary" : "

    Adds and replaces entries in an archive according to\n the given spec.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "archive", "type" : "xs:base64Binary", "occurrence" : null, "description" : "
    the archive to add or replace content
    " }, { "name" : "entries", "type" : "item()", "occurrence" : "*", "description" : "
    the meta data for the entries in the archive. Each entry can be of type xs:string or a JSON object. For mandatory fields in the JSON object see create function.
    " }, { "name" : "contents", "type" : "item()", "occurrence" : "*", "description" : "
    the content for the archive. Each item in the sequence can be of type xs:string or xs:base64Binary.
    " } ], "returns" : { "type" : "xs:base64Binary", "description" : "the updated xs:base64Binary" }, "errors" : [ "a:ENTRY-COUNT-MISMATCH if the number of entry elements differs from the number of items in the $contents sequence: count($non-directory-entries) ne count($contents)", "a:INVALID-ENTRY-VALS if a value for an entry element is invalid", "a:INVALID-ENCODING if a given encoding is invalid or not supported", "a:DIFFERENT-COMPRESSIONS-NOT-SUPPORTED if different compression algorithms were selected but the actual version of libarchive doesn't support it.", "err:FORG0006 if an item in the contents sequence is not of type xs:string or xs:base64Binary", "a:CORRUPTED-ARCHIVE if $archive is not an archive or corrupted" ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/converters/html" : { "ns" : "http://www.zorba-xquery.com/modules/converters/html", "description" : "

    \n This module provides functions to tidy a HTML document.
    \n The functions in this module take an HTML document (a string) as parameter,\n tidy it in order to result in valid XHTML, and return this XHTML document as a document-node.\n

    \n", "sees" : [ ], "authors" : [ "Sorin Nasoi" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://ww.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://www.zorba-xquery.com/modules/converters/html", "prefix" : "html" }, { "uri" : "http://www.zorba-xquery.com/modules/converters/html-options", "prefix" : "html-options" }, { "uri" : "http://zorba.io/modules/schema", "prefix" : "schema" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "parse", "qname" : "html:parse", "signature" : "($html as xs:string) as document()", "description" : "

    This function tidies the given HTML string and returns\n a valid XHTML document node.

    \n

    This functions automatically sets the following tidying parameters:\n

      \n
    • output-xml=yes
    • \n
    • doctype=omit
    • \n
    • quote-nbsp=no
    • \n
    • char-encoding=utf8
    • \n
    • newline=LF
    • \n
    • tidy-mark=no
    • \n
    \n

    \n", "summary" : "

    This function tidies the given HTML string and returns\n a valid XHTML document node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "html", "type" : "xs:string", "occurrence" : null, "description" : "
    the HTML string to tidy
    " } ], "returns" : { "type" : "document()", "description" : "the tidied XML document" }, "errors" : [ "html:InternalError if an internal error occurred while tidying the string." ] }, { "isDocumented" : true, "arity" : 2, "name" : "parse", "qname" : "html:parse", "signature" : "($html as xs:string, $options as element(html-options:options)) as document()", "description" : "

    This function tidies the given HTML string and returns\n a valid XHTML document node.

    \n

    The second parameter allows to specify options that\n configure the tidy process. This parameter is a sequence\n of name=value pairs. Allowed parameter names and values\n are documented at \n http://tidy.sourceforge.net/docs/quickref.html.

    \n", "summary" : "

    This function tidies the given HTML string and returns\n a valid XHTML document node.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "html", "type" : "xs:string", "occurrence" : null, "description" : "
    the HTML string to tidy
    " }, { "name" : "options", "type" : "element(html-options:options)", "occurrence" : null, "description" : "
    a set of name and value pairs that provide options to configure the tidy process that have to be validated against the \"http://www.zorba-xquery.com/modules/converters/html-options\" schema.
    " } ], "returns" : { "type" : "document()", "description" : "the tidied XHTML document node" }, "errors" : [ "err:XQDY0027 if $options can not be validated against the html-options schema", "html:TidyOption if there was an error with one of the options in the $options parameter that couldn't have been caught by validating against the schema", "html:InternalError if an internal error occurred while tidying the string." ] } ], "variables" : [ ] }, "http://zorba.io/modules/data-cleaning/set-similarity" : { "ns" : "http://zorba.io/modules/data-cleaning/set-similarity", "description" : "

    This library module provides similarity functions for comparing sets of XML\n nodes (e.g., sets of XML elements, attributes or atomic values).

    \n

    \n

    These functions are particularly useful for matching near duplicate sets of XML nodes.

    \n

    \n

    The logic contained in this module is not specific to any particular XQuery implementation.

    \n", "sees" : [ ], "authors" : [ "Bruno Martins" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/modules/data-cleaning/set-similarity", "prefix" : "set" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "deep-intersect", "qname" : "set:deep-intersect", "signature" : "($s1, $s2) as item()*", "description" : "

    Returns the intersection between two sets, using the deep-equal() function to compare the XML nodes from the sets.

    \n

    \n

    Example usage :

     deep-intersect ( ( \"a\", \"b\", \"c\") , ( \"a\", \"a\",  ) ) 

    \n

    \n

    The function invocation in the example above returns :

     (\"a\") 

    \n", "summary" : "

    Returns the intersection between two sets, using the deep-equal() function to compare the XML nodes from the sets.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : null, "occurrence" : null, "description" : "
    The first set.
    " }, { "name" : "s2", "type" : null, "occurrence" : null, "description" : "
    The second set.
    " } ], "returns" : { "type" : "item()*", "description" : "The intersection of both sets." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "deep-union", "qname" : "set:deep-union", "signature" : "($s1, $s2) as item()*", "description" : "

    Returns the union between two sets, using the deep-equal() function to compare the XML nodes from the sets.

    \n

    \n

    Example usage :

     deep-union ( ( \"a\", \"b\", \"c\") , ( \"a\", \"a\",  ) ) 

    \n

    \n

    The function invocation in the example above returns :

     (\"a\", \"b\", \"c\",  ) 

    \n", "summary" : "

    Returns the union between two sets, using the deep-equal() function to compare the XML nodes from the sets.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : null, "occurrence" : null, "description" : "
    The first set.
    " }, { "name" : "s2", "type" : null, "occurrence" : null, "description" : "
    The second set.
    " } ], "returns" : { "type" : "item()*", "description" : "The union of both sets." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "dice", "qname" : "set:dice", "signature" : "($s1, $s2) as xs:double", "description" : "

    Returns the Dice similarity coefficient between two sets of XML nodes.

    \n

    The Dice coefficient is defined as defined as twice the shared information between the input sets\n (i.e., the size of the intersection) over the sum of the cardinalities for the input sets.

    \n

    \n

    Example usage :

     dice ( ( \"a\", \"b\",  ) , ( \"a\", \"a\", \"d\") ) 

    \n

    \n

    The function invocation in the example above returns :

     0.4 

    \n", "summary" : "

    Returns the Dice similarity coefficient between two sets of XML nodes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : null, "occurrence" : null, "description" : "
    The first set.
    " }, { "name" : "s2", "type" : null, "occurrence" : null, "description" : "
    The second set.
    " } ], "returns" : { "type" : "xs:double", "description" : "The Dice similarity coefficient between the two sets." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "distinct", "qname" : "set:distinct", "signature" : "($s) as item()*", "description" : "

    Removes exact duplicates from a set, using the deep-equal() function to compare the XML nodes from the sets.

    \n

    \n

    Example usage :

     distinct ( ( \"a\", \"a\",  ) ) 

    \n

    \n

    The function invocation in the example above returns :

     (\"a\",  ) 

    \n", "summary" : "

    Removes exact duplicates from a set, using the deep-equal() function to compare the XML nodes from the sets.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s", "type" : null, "occurrence" : null, "description" : "
    A set.
    " } ], "returns" : { "type" : "item()*", "description" : "The set provided as input without the exact duplicates (i.e., returns the distinct nodes from the set provided as input)." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "jaccard", "qname" : "set:jaccard", "signature" : "($s1, $s2) as xs:double", "description" : "

    Returns the Jaccard similarity coefficient between two sets of XML nodes.

    \n

    The Jaccard coefficient is defined as the size of the intersection divided by the size of the\n union of the input sets.

    \n

    \n

    Example usage :

     jaccard ( ( \"a\", \"b\",  ) , ( \"a\", \"a\", \"d\") ) 

    \n

    \n

    The function invocation in the example above returns :

     0.25 

    \n", "summary" : "

    Returns the Jaccard similarity coefficient between two sets of XML nodes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : null, "occurrence" : null, "description" : "
    The first set.
    " }, { "name" : "s2", "type" : null, "occurrence" : null, "description" : "
    The second set.
    " } ], "returns" : { "type" : "xs:double", "description" : "The Jaccard similarity coefficient between the two sets." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 2, "name" : "overlap", "qname" : "set:overlap", "signature" : "($s1, $s2) as xs:double", "description" : "

    Returns the overlap coefficient between two sets of XML nodes.

    \n

    The overlap coefficient is defined as the shared information between the input sets\n (i.e., the size of the intersection) over the size of the smallest input set.

    \n

    \n

    Example usage :

     overlap ( ( \"a\", \"b\",  ) , ( \"a\", \"a\", \"b\" ) ) 

    \n

    \n

    The function invocation in the example above returns :

     1.0 

    \n", "summary" : "

    Returns the overlap coefficient between two sets of XML nodes.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "s1", "type" : null, "occurrence" : null, "description" : "
    The first set.
    " }, { "name" : "s2", "type" : null, "occurrence" : null, "description" : "
    The second set.
    " } ], "returns" : { "type" : "xs:double", "description" : "The overlap coefficient between the two sets." }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.28msec.com/modules/http/util/cache" : { "ns" : "http://www.28msec.com/modules/http/util/cache", "description" : " This module contains a collection of convenience functions to help\n developers work with HTTP caching options.\n", "sees" : [ ], "authors" : [ "28msec" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://zorba.io/annotations", "prefix" : "an" }, { "uri" : "http://www.28msec.com/modules/http/util/cache", "prefix" : "cache" }, { "uri" : "http://www.28msec.com/modules/http/response", "prefix" : "resp" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 0, "name" : "no-cache", "qname" : "cache:no-cache", "signature" : "() as empty-sequence()", "description" : "

    Forces a client not to cache the response by setting the appropriate\n HTTP headers.

    \n In detail, the following HTTP headers will be set in the response:\n
      \n
    • Cache-Control: no-cache
    • \n
    • Pragma: no-cache
    • \n
    • Expires: 0
    • \n
    \n", "summary" : "

    Forces a client not to cache the response by setting the appropriate\n HTTP headers.

    ", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "http://zorba.io/annotations", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "empty-sequence()", "description" : "On success, the empty-sequence is returned" }, "errors" : [ ] } ], "variables" : [ ] }, "http://www.zorba-xquery.com/modules/schema-tools" : { "ns" : "http://www.zorba-xquery.com/modules/schema-tools", "description" : " This module provides funtionality to get sample XMLSchema from XML instances\n and sample XML instances from XMLSchema.\n Apache XMLBeans library is used to implement\n inst2xsd and xsd2inst functions.\n
    \n
    \n Note: Since this module has a Java library dependency a JVM required\n to be installed on the system. For Windows: jvm.dll is required on the system\n path ( usually located in \"C:\\Program Files\\Java\\jre6\\bin\\client\".\n", "sees" : [ "http://xmlbeans.apache.org/", "http://xmlbeans.apache.org" ], "authors" : [ "Cezar Andrei" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.w3.org/2005/xqt-errors", "prefix" : "err" }, { "uri" : "http://zorba.io/modules/schema", "prefix" : "schema-options" }, { "uri" : "http://www.zorba-xquery.com/modules/schema-tools", "prefix" : "schema-tools" }, { "uri" : "http://www.zorba-xquery.com/modules/schema-tools/schema-tools-options", "prefix" : "st-options" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "inst2xsd", "qname" : "schema-tools:inst2xsd", "signature" : "($instances as element(*)+, $options as element(st-options:inst2xsd-options)?) as document()*", "description" : " The inst2xsd function takes a set of sample XML instance elements as input and\n generates a set of sample XMLSchema documents that define\n the content of the given input.\n
    \n Please consult the\n official documentation for further\n information.\n
    \n Example:
    \n  import module namespace st = \"http://www.zorba-xquery.com/modules/schema-tools\";\n  declare namespace sto =\n      \"http://www.zorba-xquery.com/modules/schema-tools/schema-tools-options\";\n  let $instances := (<a><b/><c/></a>, <b/>, <c>ccc</c>)\n  let $options  :=\n     <sto:inst2xsd-options xmlns:sto=\n       \"http://www.zorba-xquery.com/modules/schema-tools/schema-tools-options\">\n       <sto:design>vbd</sto:design>\n       <sto:simple-content-types>smart</sto:simple-content-types>\n       <sto:use-enumeration>10</sto:use-enumeration>\n     </sto:inst2xsd-options>\n  return\n      st:inst2xsd($instances, $options)\n 
    \n
    \n", "summary" : "

    The inst2xsd function takes a set of sample XML instance elements as input and\n generates a set of sample XMLSchema documents that define\n the content of the given input.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "instances", "type" : "element(*)", "occurrence" : "+", "description" : "
    The input XML instance elements
    " }, { "name" : "options", "type" : "element(st-options:inst2xsd-options)", "occurrence" : "?", "description" : "
    Options:
    • design: Choose the generated schema design
      - rdd: Russian Doll Design - local elements and local types
      - ssd: Salami Slice Design - global elements and local types
      - vbd (default): Venetian Blind Design - local elements and global complex types
    • simple-content-types: type of leaf nodes
      - smart (default): try to find the right simple XMLSchema type
      - always-string: use xsd:string for all simple types
    • use-enumeration: - when there are multiple valid values in a list
      - 1: never use enumeration
      - 2 or more (default 10): use enumeration if less than this number of occurrences - number option
    • verbose: - stdout verbose info
      - true: - output type holder information
      - false (default): no output
    " } ], "returns" : { "type" : "document()*", "description" : "The generated XMLSchema documents." }, "errors" : [ "schema-tools:VM001 If Zorba was unable to start the JVM.", "schema-tools:JAVA-EXCEPTION If Apache XMLBeans throws an exception." ] }, { "isDocumented" : true, "arity" : 3, "name" : "xsd2inst", "qname" : "schema-tools:xsd2inst", "signature" : "($schemas as element(*)+, $rootElementName as xs:string, $options as element(st-options:xsd2inst-options)?) as document()", "description" : " The xsd2inst function takes a set of XML Schema elements as input and the\n local name of the root element and\n generates a document that represents one sample XML instance of the given\n input schemas. The local name is searched in schema global element definitions\n in the order of schemas parameter.\n
    \n Please consult the\n official documentation for further\n information.\n
    \n Example:
    \n  import module namespace st = \"http://www.zorba-xquery.com/modules/schema-tools\";\n  declare namespace sto =\n      \"http://www.zorba-xquery.com/modules/schema-tools/schema-tools-options\";\n  let $xsds  :=\n     ( <xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n           attributeFormDefault=\"unqualified\"\n           elementFormDefault=\"qualified\">\n         <xs:element name=\"a\" type=\"aType\"/>\n         <xs:complexType name=\"aType\">\n           <xs:sequence>\n             <xs:element type=\"xs:string\" name=\"b\"/>\n             <xs:element type=\"xs:string\" name=\"c\"/>\n           </xs:sequence>\n         </xs:complexType>\n       </xs:schema> )\n  let $options :=\n    <sto:xsd2inst-options xmlns:sto=\n      \"http://www.zorba-xquery.com/modules/schema-tools/schema-tools-options\">\n      <sto:network-downloads>false</sto:network-downloads>\n      <sto:no-pvr>false</sto:no-pvr>\n      <sto:no-upa>false</sto:no-upa>\n    </sto:xsd2inst-options>\n  return\n      st:xsd2inst($xsds, \"a\", $options)\n 

    \n", "summary" : "

    The xsd2inst function takes a set of XML Schema elements as input and the\n local name of the root element and\n generates a document that represents one sample XML instance of the given\n input schemas.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "schemas", "type" : "element(*)", "occurrence" : "+", "description" : "
    elements representing XMLSchema definitions
    " }, { "name" : "rootElementName", "type" : "xs:string", "occurrence" : null, "description" : "
    The local name of the instance root element. If multiple target namespaces are used, first one found - using the sequence order - will be used.
    " }, { "name" : "options", "type" : "element(st-options:xsd2inst-options)", "occurrence" : "?", "description" : "
    Options:
    • network-downloads: boolean (default false)
      - true allows XMLBeans to use network when resolving schema imports and includes
    • no-pvr: boolean (default false)
      - true to disable particle valid (restriction) rule, false otherwise
    • no-upa: boolean (default false)
      - true to disable unique particle attribution rule, false otherwise
    " } ], "returns" : { "type" : "document()", "description" : "The generated output document, representing a sample XML instance." }, "errors" : [ "schema-tools:VM001 If Zorba was unable to start the JVM.", "schema-tools:JAVA-EXCEPTION If Apache XMLBeans throws an exception." ] } ], "variables" : [ ] }, "http://xbrl.io/modules/bizql/entities" : { "ns" : "http://xbrl.io/modules/bizql/entities", "description" : "

    This module provides functions for retrieving information about entities.\n Entities submit archives (see archives module),\n for example, to a reporting authority. Entities\n are identified with an EID (Entity ID).

    \n

    With this module, you can retrieve all entities, or a certain number of entities\n with their EIDs, or obtain the EID of entities you already have.

    \n

    Entities are stored in a MongoDB datasource called xbrl.

    \n

    Each entity can be associated with a set of tags that makes it easier\n to manage them. The e:entities#1 function\n allows to retrieve all entities with a given tag.

    \n", "sees" : [ ], "authors" : [ "Charles Hoffman", "Matthias Brantner", "Dennis Knochenwefel", "Ghislain Fourny" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.28msec.com/modules/credentials", "prefix" : "credentials" }, { "uri" : "http://xbrl.io/modules/bizql/entities", "prefix" : "entities" }, { "uri" : "http://www.28msec.com/modules/mongodb", "prefix" : "mongo" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 1, "name" : "eid", "qname" : "entities:eid", "signature" : "($entities-or-ids as item()*) as atomic*", "description" : "

    Converts the input to a normalized entity identifier (EID). The input\n can be either an EID, or an entity object which contains an _id.

    \n", "summary" : "

    Converts the input to a normalized entity identifier (EID).

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "entities-or-ids", "type" : "item()", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : "atomic*", "description" : "the normalized EIDs." }, "errors" : [ "entities:INVALID_PARAMETER if the EID or entity is not valid." ] }, { "isDocumented" : true, "arity" : 0, "name" : "entities", "qname" : "entities:entities", "signature" : "() as object()*", "description" : "

    Return all entities.

    \n", "summary" : "

    Return all entities.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ ], "returns" : { "type" : "object()*", "description" : "all entities." }, "errors" : [ ] }, { "isDocumented" : true, "arity" : 1, "name" : "entities", "qname" : "entities:entities", "signature" : "($entities-or-ids as item()*) as object()*", "description" : "

    Return the entities with the given EIDs.

    \n", "summary" : "

    Return the entities with the given EIDs.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "entities-or-ids", "type" : "item()", "occurrence" : "*", "description" : "
    the ids of the entities (EIDs) or the entities themselves.
    " } ], "returns" : { "type" : "object()*", "description" : "the entities with the given EIDs the empty sequence if no entity was found or if the input is an empty sequence." }, "errors" : [ ] } ], "variables" : [ { "name" : "entities:col", "type" : "string", "description" : " Name of the collection the entities are stored in.\n" } ] }, "http://www.zorba-xquery.com/modules/cryptography/hmac" : { "ns" : "http://www.zorba-xquery.com/modules/cryptography/hmac", "description" : " This module provides a function to generate hash-based\n message authentication codes (HMAC) involving a cryptographic\n hash function (e.g. SHA1).\n", "sees" : [ ], "authors" : [ "William Candillon" ], "version" : null, "encoding" : "utf-8", "namespaces" : [ { "uri" : "http://www.zorba-xquery.com/modules/cryptography/hmac", "prefix" : "hmac" }, { "uri" : "http://zorba.io/options/versioning", "prefix" : "ver" } ], "functions" : [ { "isDocumented" : true, "arity" : 2, "name" : "sha1", "qname" : "hmac:sha1", "signature" : "($message as xs:string, $secret-key as xs:string) as xs:string external", "description" : " This function provides hash-based message authentication code using\n the SHA1 algorithm.\n", "summary" : "

    This function provides hash-based message authentication code using\n the SHA1 algorithm.

    ", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "message", "type" : "xs:string", "occurrence" : null, "description" : "
    the message to be authenticated
    " }, { "name" : "secret-key", "type" : "xs:string", "occurrence" : null, "description" : "
    the secret key used for calculating the authentication
    " } ], "returns" : { "type" : "xs:string", "description" : "hash-based base64 encoded message authentication code" }, "errors" : [ ] } ], "variables" : [ ] }, "http://api.28.io/csvview" : { "ns" : "http://api.28.io/csvview", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "", "prefix" : "an" }, { "uri" : "http://api.28.io/csvview", "prefix" : "csvview" }, { "uri" : "http://api.28.io/model", "prefix" : "model" } ], "functions" : [ { "isDocumented" : false, "arity" : 1, "name" : "column", "qname" : "csvview:column", "signature" : "($data) as xs:string", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "data", "type" : null, "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "line", "qname" : "csvview:line", "signature" : "($entries as xs:string*)", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "entries", "type" : "xs:string", "occurrence" : "*", "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 2, "name" : "show-nodes", "qname" : "csvview:show-nodes", "signature" : "($nodes, $show-headers as xs:boolean)", "description" : "", "summary" : "", "annotation_str" : " %an:sequential", "annotations" : [ { "prefix" : "an", "ns" : "", "name" : "sequential", "value" : "" } ], "updating" : false, "parameters" : [ { "name" : "nodes", "type" : null, "occurrence" : null, "description" : "" }, { "name" : "show-headers", "type" : "xs:boolean", "occurrence" : null, "description" : "" } ], "returns" : { "type" : null, "description" : "" }, "errors" : [ ] } ], "variables" : [ ] }, "http://api.28.io/util" : { "ns" : "http://api.28.io/util", "description" : "", "sees" : [ ], "authors" : [ ], "version" : null, "encoding" : null, "namespaces" : [ { "uri" : "http://www.28msec.com/modules/http/request", "prefix" : "req" }, { "uri" : "http://api.28.io/util", "prefix" : "util" } ], "functions" : [ { "isDocumented" : false, "arity" : 1, "name" : "param-or-body", "qname" : "util:param-or-body", "signature" : "($param-name as xs:string) as xs:string?", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "param-name", "type" : "xs:string", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string?", "description" : "" }, "errors" : [ ] }, { "isDocumented" : false, "arity" : 1, "name" : "path", "qname" : "util:path", "signature" : "($from as xs:integer) as xs:string*", "description" : "", "summary" : "", "annotation_str" : "", "annotations" : [ ], "updating" : false, "parameters" : [ { "name" : "from", "type" : "xs:integer", "occurrence" : null, "description" : "" } ], "returns" : { "type" : "xs:string*", "description" : "" }, "errors" : [ ] } ], "variables" : [ { "name" : "util:collection-namespace", "type" : "item()*", "description" : "" } ] } }; -}); diff --git a/lib/ace/mode/xquery_worker.js b/lib/ace/mode/xquery_worker.js index da522a75..2ca32fe5 100644 --- a/lib/ace/mode/xquery_worker.js +++ b/lib/ace/mode/xquery_worker.js @@ -35,7 +35,6 @@ var oop = require("../lib/oop"); var Mirror = require("../worker/mirror").Mirror; var XQLintLib = require("./xquery/xqlint"); var XQLint = XQLintLib.XQLint; -//var Modules = require("./xquery/modules").Modules; var getModuleResolverFromModules = function(modules){ return function(uri){ From 49b50ff347660ac8f803e77e60bfdf64ab150a72 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 23 Nov 2014 16:46:56 +0400 Subject: [PATCH 073/315] fix broken paths in kitchen-sink demo --- Makefile.dryice.js | 1 + demo/kitchen-sink/doclist.js | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile.dryice.js b/Makefile.dryice.js index a40549ef..f6f4b42f 100755 --- a/Makefile.dryice.js +++ b/Makefile.dryice.js @@ -120,6 +120,7 @@ function demo() { function changeComments(data) { return (data + .replace("doc/site/images/ace-logo.png", "demo/kitchen-sink/ace-logo.png") .replace(//g, "") .replace(/PACKAGE\-\->| Date: Mon, 24 Nov 2014 09:29:37 -0500 Subject: [PATCH 074/315] progress appears to be working, need to clean up still --- lib/ace/mode/folding/cstyle.js | 63 ++++++++++++++++++++++++++++++++++ lib/ace/mode/folding/html.js | 2 +- lib/ace/mode/javascript.js | 2 +- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/lib/ace/mode/folding/cstyle.js b/lib/ace/mode/folding/cstyle.js index dd151e24..d7541f06 100644 --- a/lib/ace/mode/folding/cstyle.js +++ b/lib/ace/mode/folding/cstyle.js @@ -51,9 +51,48 @@ oop.inherits(FoldMode, BaseFoldMode); this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; + // this.startBlockRegionRe = /^\s*\/\*#region\b/; + // this.startLineRegionRe = /^\s*\/\/#region\b/; + this.startRegionRe = /^\s*((\/\*)|(\/\/))#region\b/; + this.getFoldWidgetBase = this.getFoldWidget; + + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row).trim(); + + var isRegionStart = this.startRegionRe.test(line); + + if (line.length > 3 && line.substring(0, 2) === '/*' && line.substring(line.length - 2) === '*/') { + // Don't create fold widgets for single line block comments + // unless its a region start comment, or it starts with 3 stars [/***] + if (line.substring(0, 4) !== '/***' && !isRegionStart /*!this.startBlockRegionRe.test(line)*/) + return ""; + } + + var fw = this.getFoldWidgetBase(session, foldStyle, row); + if (!fw) { + // check for block comment region start + if(isRegionStart) /*if (this.startLineRegionRe.test(line)) */ + return "start"; + } + + return fw; + }; this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) { var line = session.getLine(row); + + if(this.startRegionRe.test(line)) + return this.getRegionBlock(session, line, row); + + /*// first check for block comment region + if (this.startBlockRegionRe.test(line)) + return this.getRegionBlock(session, line, row, true); + + // now check for line comment region + if (this.startLineRegionRe.test(line)) + return this.getRegionBlock(session, line, row, false);*/ + + var match = line.match(this.foldingStartMarker); if (match) { var i = match.index; @@ -118,6 +157,30 @@ oop.inherits(FoldMode, BaseFoldMode); return new Range(startRow, startColumn, endRow, session.getLine(endRow).length); }; + + this.getRegionBlock = function(session, line, row) { + var startColumn = line.search(/\s*$/); + var maxRow = session.getLength(); + var startRow = row; + + var re = /^\s*((\/\*)|(\/\/))#(end)?region\b/;// isBlock? /^\s*\/\*#(end)?region\b/ : /^\s*\/\/#(end)?region\b/; + var depth = 1; + while (++row < maxRow) { + line = session.getLine(row); + var m = re.exec(line); + if (!m) continue; + if (m[1]) depth--; + else depth++; + + if (!depth) break; + } + + var endRow = row; + if (endRow > startRow) { + var endColumn = line.search(/\S/); + return new Range(startRow, startColumn, endRow, endColumn); + } + }; }).call(FoldMode.prototype); diff --git a/lib/ace/mode/folding/html.js b/lib/ace/mode/folding/html.js index a84f4478..5edbe0b8 100644 --- a/lib/ace/mode/folding/html.js +++ b/lib/ace/mode/folding/html.js @@ -34,7 +34,7 @@ define(function(require, exports, module) { var oop = require("../../lib/oop"); var MixedFoldMode = require("./mixed").FoldMode; var XmlFoldMode = require("./xml").FoldMode; -var CStyleFoldMode = require("./javascript").FoldMode; +var CStyleFoldMode = require("./cstyle").FoldMode; var FoldMode = exports.FoldMode = function(voidElements, optionalTags) { MixedFoldMode.call(this, new XmlFoldMode(voidElements, optionalTags), { diff --git a/lib/ace/mode/javascript.js b/lib/ace/mode/javascript.js index 4e7f0dac..af62ae76 100644 --- a/lib/ace/mode/javascript.js +++ b/lib/ace/mode/javascript.js @@ -38,7 +38,7 @@ var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutd var Range = require("../range").Range; var WorkerClient = require("../worker/worker_client").WorkerClient; var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; -var CStyleFoldMode = require("./folding/javascript").FoldMode; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; var Mode = function() { this.HighlightRules = JavaScriptHighlightRules; From f26841da41ab94ba1aef8a8eff11fde51915d009 Mon Sep 17 00:00:00 2001 From: sevin7676 Date: Mon, 24 Nov 2014 09:48:41 -0500 Subject: [PATCH 075/315] tested and cleaned up --- lib/ace/mode/folding/cstyle.js | 45 ++++++------- lib/ace/mode/folding/javascript.js | 104 ----------------------------- 2 files changed, 21 insertions(+), 128 deletions(-) delete mode 100644 lib/ace/mode/folding/javascript.js diff --git a/lib/ace/mode/folding/cstyle.js b/lib/ace/mode/folding/cstyle.js index d7541f06..d9821d1b 100644 --- a/lib/ace/mode/folding/cstyle.js +++ b/lib/ace/mode/folding/cstyle.js @@ -51,30 +51,36 @@ oop.inherits(FoldMode, BaseFoldMode); this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; - // this.startBlockRegionRe = /^\s*\/\*#region\b/; - // this.startLineRegionRe = /^\s*\/\/#region\b/; this.startRegionRe = /^\s*((\/\*)|(\/\/))#region\b/; this.getFoldWidgetBase = this.getFoldWidget; + /** + * Gets fold widget with some non-standard extras: + * + * @example lineCommentRegionStart + * //#region [optional description] + * + * @example blockCommentRegionStart + * /*#region [optional description] *[/] + * + * @example tripleStarFoldingSection + * /*** this folds even though 1 line because it has 3 stars ***[/] + */ this.getFoldWidget = function(session, foldStyle, row) { var line = session.getLine(row).trim(); - + var isRegionStart = this.startRegionRe.test(line); - + if (line.length > 3 && line.substring(0, 2) === '/*' && line.substring(line.length - 2) === '*/') { - // Don't create fold widgets for single line block comments - // unless its a region start comment, or it starts with 3 stars [/***] - if (line.substring(0, 4) !== '/***' && !isRegionStart /*!this.startBlockRegionRe.test(line)*/) + if (!isRegionStart && line.substring(0, 4) !== '/***') return ""; } - + var fw = this.getFoldWidgetBase(session, foldStyle, row); - if (!fw) { - // check for block comment region start - if(isRegionStart) /*if (this.startLineRegionRe.test(line)) */ - return "start"; - } + if (!fw && isRegionStart) + return "start"; // lineCommentRegionStart + return fw; }; @@ -84,15 +90,6 @@ oop.inherits(FoldMode, BaseFoldMode); if(this.startRegionRe.test(line)) return this.getRegionBlock(session, line, row); - /*// first check for block comment region - if (this.startBlockRegionRe.test(line)) - return this.getRegionBlock(session, line, row, true); - - // now check for line comment region - if (this.startLineRegionRe.test(line)) - return this.getRegionBlock(session, line, row, false);*/ - - var match = line.match(this.foldingStartMarker); if (match) { var i = match.index; @@ -163,7 +160,7 @@ oop.inherits(FoldMode, BaseFoldMode); var maxRow = session.getLength(); var startRow = row; - var re = /^\s*((\/\*)|(\/\/))#(end)?region\b/;// isBlock? /^\s*\/\*#(end)?region\b/ : /^\s*\/\/#(end)?region\b/; + var re = /^\s*((\/\*)|(\/\/))#(end)?region\b/; var depth = 1; while (++row < maxRow) { line = session.getLine(row); @@ -178,7 +175,7 @@ oop.inherits(FoldMode, BaseFoldMode); var endRow = row; if (endRow > startRow) { var endColumn = line.search(/\S/); - return new Range(startRow, startColumn, endRow, endColumn); + return new Range(startRow, startColumn, endRow, line.length); } }; diff --git a/lib/ace/mode/folding/javascript.js b/lib/ace/mode/folding/javascript.js deleted file mode 100644 index e92c6c3c..00000000 --- a/lib/ace/mode/folding/javascript.js +++ /dev/null @@ -1,104 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2010, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ - -define(function(require, exports, module) { -"use strict"; - -var oop = require("../../lib/oop"); -var Range = require("../../range").Range; -var CFoldMode = require("./cstyle").FoldMode; - -var FoldMode = exports.FoldMode = function(commentRegex) { - if (commentRegex) { - this.foldingStartMarker = new RegExp( - this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start) - ); - this.foldingStopMarker = new RegExp( - this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end) - ); - } -}; -oop.inherits(FoldMode, CFoldMode); - -(function() { - this.getFoldWidgetRangeBase = this.getFoldWidgetRange; - this.getFoldWidgetBase = this.getFoldWidget; - - this.getFoldWidget = function(session, foldStyle, row) { - var fw = this.getFoldWidgetBase(session, foldStyle, row); - if (!fw) { - var line = session.getLine(row); - if (/^\s*\/\/#region\b/.test(line)) - return "start"; - } - return fw; - }; - - this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) { - var range = this.getFoldWidgetRangeBase(session, foldStyle, row, forceMultiline); - if (range) - return range; - - var line = session.getLine(row); - if (/^\s*\/\/#region\b/.test(line)) - return this.getRegionBlock(session, line, row); - }; - - this.getRegionBlock = function(session, line, row) { - var startColumn = line.search(/\s*$/); - var maxRow = session.getLength(); - var startRow = row; - - var re = /^\s*\/\/#(end)?region\b/; - var depth = 1; - while (++row < maxRow) { - line = session.getLine(row); - var m = re.exec(line); - if (!m) - continue; - if (m[1]) - depth--; - else - depth++; - - if (!depth) - break; - } - - var endRow = row; - if (endRow > startRow) { - var endColumn = line.search(/\S/); - return new Range(startRow, startColumn, endRow, endColumn); - } - }; - -}).call(FoldMode.prototype); - -}); From 03730ce381dde221842c32b53598e02b9588b7aa Mon Sep 17 00:00:00 2001 From: sevin7676 Date: Mon, 24 Nov 2014 09:52:57 -0500 Subject: [PATCH 076/315] extra comment to help explain code --- lib/ace/mode/folding/cstyle.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ace/mode/folding/cstyle.js b/lib/ace/mode/folding/cstyle.js index d9821d1b..f5f6a0de 100644 --- a/lib/ace/mode/folding/cstyle.js +++ b/lib/ace/mode/folding/cstyle.js @@ -72,6 +72,7 @@ oop.inherits(FoldMode, BaseFoldMode); var isRegionStart = this.startRegionRe.test(line); if (line.length > 3 && line.substring(0, 2) === '/*' && line.substring(line.length - 2) === '*/') { + // No widget for single line block comment unless region or triple star if (!isRegionStart && line.substring(0, 4) !== '/***') return ""; } From 602a7efd5fc45f0859657705a723967c3e629204 Mon Sep 17 00:00:00 2001 From: sevin7676 Date: Mon, 24 Nov 2014 10:18:00 -0500 Subject: [PATCH 077/315] removed unused line the end of the range should be the end of the line as we don't want to see [//#endreigon] in our fold widget. --- lib/ace/mode/folding/cstyle.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/ace/mode/folding/cstyle.js b/lib/ace/mode/folding/cstyle.js index f5f6a0de..caeb606a 100644 --- a/lib/ace/mode/folding/cstyle.js +++ b/lib/ace/mode/folding/cstyle.js @@ -175,7 +175,6 @@ oop.inherits(FoldMode, BaseFoldMode); var endRow = row; if (endRow > startRow) { - var endColumn = line.search(/\S/); return new Range(startRow, startColumn, endRow, line.length); } }; From 1869024de6f51153525a77822510c1cdb2408bb1 Mon Sep 17 00:00:00 2001 From: sevin7676 Date: Tue, 25 Nov 2014 06:58:45 -0500 Subject: [PATCH 078/315] changes per nightwing recommendations Rename this.getFoldWidgetBase to avoid conflict with C# mode. Use regex instead of substring and trim to determine single line block comment. Fixed formatting. Renamed this.getRegionBlock to this.getCommentRegionBlock to prevent C# mode conflict. Updated this.getCommentRegionBlock regex to make nested regions work properly. Cleaned up this.startRegionRe (had unneeded parenthesis). --- lib/ace/mode/folding/cstyle.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/ace/mode/folding/cstyle.js b/lib/ace/mode/folding/cstyle.js index caeb606a..c2f302c2 100644 --- a/lib/ace/mode/folding/cstyle.js +++ b/lib/ace/mode/folding/cstyle.js @@ -48,11 +48,13 @@ var FoldMode = exports.FoldMode = function(commentRegex) { oop.inherits(FoldMode, BaseFoldMode); (function() { - + this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; - this.startRegionRe = /^\s*((\/\*)|(\/\/))#region\b/; - this.getFoldWidgetBase = this.getFoldWidget; + this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/; + this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/; + this.startRegionRe = /^\s*(\/\*|\/\/)#region\b/; + this._getFoldWidgetBase = this.getFoldWidget; /** * Gets fold widget with some non-standard extras: @@ -67,19 +69,17 @@ oop.inherits(FoldMode, BaseFoldMode); * /*** this folds even though 1 line because it has 3 stars ***[/] */ this.getFoldWidget = function(session, foldStyle, row) { - var line = session.getLine(row).trim(); + var line = session.getLine(row); - var isRegionStart = this.startRegionRe.test(line); - - if (line.length > 3 && line.substring(0, 2) === '/*' && line.substring(line.length - 2) === '*/') { + if (this.singleLineBlockCommentRe.test(line)) { // No widget for single line block comment unless region or triple star - if (!isRegionStart && line.substring(0, 4) !== '/***') + if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line)) return ""; } - var fw = this.getFoldWidgetBase(session, foldStyle, row); - - if (!fw && isRegionStart) + var fw = this._getFoldWidgetBase(session, foldStyle, row); + + if (!fw && this.startRegionRe.test(line)) return "start"; // lineCommentRegionStart return fw; @@ -88,8 +88,8 @@ oop.inherits(FoldMode, BaseFoldMode); this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) { var line = session.getLine(row); - if(this.startRegionRe.test(line)) - return this.getRegionBlock(session, line, row); + if (this.startRegionRe.test(line)) + return this.getCommentRegionBlock(session, line, row); var match = line.match(this.foldingStartMarker); if (match) { @@ -156,12 +156,12 @@ oop.inherits(FoldMode, BaseFoldMode); return new Range(startRow, startColumn, endRow, session.getLine(endRow).length); }; - this.getRegionBlock = function(session, line, row) { + this.getCommentRegionBlock = function(session, line, row) { var startColumn = line.search(/\s*$/); var maxRow = session.getLength(); var startRow = row; - - var re = /^\s*((\/\*)|(\/\/))#(end)?region\b/; + + var re = /^\s*(?:\/\*|\/\/)#(end)?region\b/; var depth = 1; while (++row < maxRow) { line = session.getLine(row); From 41df1f265f1afb85a82db0e9b68d12809312bdb5 Mon Sep 17 00:00:00 2001 From: sevin7676 Date: Tue, 25 Nov 2014 07:01:09 -0500 Subject: [PATCH 079/315] Fix fold widget range for region End range should be at end of line as we don't want to display the '#endregion' text after the fold widget (this is consistent with cstyle region comment folding). Added missing semi-colons. --- lib/ace/mode/folding/csharp.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/ace/mode/folding/csharp.js b/lib/ace/mode/folding/csharp.js index c4507534..ec9a2f48 100644 --- a/lib/ace/mode/folding/csharp.js +++ b/lib/ace/mode/folding/csharp.js @@ -110,8 +110,8 @@ oop.inherits(FoldMode, CFoldMode); var maxRow = session.getLength(); var startRow = row; - var re = /^\s*#(end)?region\b/ - var depth = 1 + var re = /^\s*#(end)?region\b/; + var depth = 1; while (++row < maxRow) { line = session.getLine(row); var m = re.exec(line); @@ -128,8 +128,7 @@ oop.inherits(FoldMode, CFoldMode); var endRow = row; if (endRow > startRow) { - var endColumn = line.search(/\S/); - return new Range(startRow, startColumn, endRow, endColumn); + return new Range(startRow, startColumn, endRow, line.length); } }; From f7144da4ecafa5f6d637e8ee2154d9b9bf243d4f Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 25 Nov 2014 13:37:36 -0800 Subject: [PATCH 080/315] more dart keywords --- lib/ace/mode/dart_highlight_rules.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ace/mode/dart_highlight_rules.js b/lib/ace/mode/dart_highlight_rules.js index 0cd5811b..65ec475a 100644 --- a/lib/ace/mode/dart_highlight_rules.js +++ b/lib/ace/mode/dart_highlight_rules.js @@ -13,8 +13,8 @@ var DartHighlightRules = function() { var constantLanguage = "true|false|null"; var variableLanguage = "this|super"; - var keywordControl = "try|catch|finally|throw|rethrow|assert|break|case|continue|default|do|else|for|if|in|return|switch|while|new"; - var keywordDeclaration = "abstract|class|extends|external|factory|implements|get|native|operator|set|typedef|with"; + var keywordControl = "try|catch|finally|throw|rethrow|assert|break|case|continue|default|do|else|for|if|in|return|switch|while|new|deferred|async|await"; + var keywordDeclaration = "abstract|class|extends|external|factory|implements|get|native|operator|set|typedef|with|enum"; var storageModifier = "static|final|const"; var storageType = "void|bool|num|int|double|dynamic|var|String"; From c1a8e777606bc03cab10bb08247490785aa49215 Mon Sep 17 00:00:00 2001 From: sevin7676 Date: Fri, 28 Nov 2014 08:18:33 -0500 Subject: [PATCH 081/315] Add comment to explain unusual naming and remove ending whitespace --- lib/ace/mode/folding/cstyle.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/ace/mode/folding/cstyle.js b/lib/ace/mode/folding/cstyle.js index c2f302c2..a98807ab 100644 --- a/lib/ace/mode/folding/cstyle.js +++ b/lib/ace/mode/folding/cstyle.js @@ -54,6 +54,8 @@ oop.inherits(FoldMode, BaseFoldMode); this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/; this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/; this.startRegionRe = /^\s*(\/\*|\/\/)#region\b/; + + //prevent naming conflict with any modes that inherit from cstyle and override this (like csharp) this._getFoldWidgetBase = this.getFoldWidget; /** @@ -61,10 +63,10 @@ oop.inherits(FoldMode, BaseFoldMode); * * @example lineCommentRegionStart * //#region [optional description] - * + * * @example blockCommentRegionStart * /*#region [optional description] *[/] - * + * * @example tripleStarFoldingSection * /*** this folds even though 1 line because it has 3 stars ***[/] */ @@ -73,13 +75,13 @@ oop.inherits(FoldMode, BaseFoldMode); if (this.singleLineBlockCommentRe.test(line)) { // No widget for single line block comment unless region or triple star - if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line)) + if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line)) return ""; } var fw = this._getFoldWidgetBase(session, foldStyle, row); - if (!fw && this.startRegionRe.test(line)) + if (!fw && this.startRegionRe.test(line)) return "start"; // lineCommentRegionStart return fw; From fc322711ca1dd744a9aadccd40229381baa49859 Mon Sep 17 00:00:00 2001 From: James Allen Date: Fri, 28 Nov 2014 13:34:16 +0000 Subject: [PATCH 082/315] Highlight \ref, \vref, \cite and \citep as labels The `\ref`, and `\cite` commands in LaTeX are similar to `\label`s in that they refer to user defined labels elsewhere in the text, and it makes sense to highlight them with the same color scheme. Particularly the coloring of arguments to `\ref` commands should match the color of `\label` commands because `\label` defines the strings that `\ref` then references. --- lib/ace/mode/latex_highlight_rules.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/mode/latex_highlight_rules.js b/lib/ace/mode/latex_highlight_rules.js index f3238bfb..bf9b9f3b 100644 --- a/lib/ace/mode/latex_highlight_rules.js +++ b/lib/ace/mode/latex_highlight_rules.js @@ -19,7 +19,7 @@ var LatexHighlightRules = function() { }, { // A label token : ["keyword","lparen", "variable.parameter", "rparen"], - regex : "(\\\\label)(?:({)([^}]*)(}))?" + regex : "(\\\\(?:label|v?ref|cite(?:[^{]*)))(?:({)([^}]*)(}))?" }, { // A block token : ["storage.type", "lparen", "variable.parameter", "rparen"], From 23a3ba85f014af153d2733a2f209d8128eb65da0 Mon Sep 17 00:00:00 2001 From: Adam Roben Date: Wed, 3 Dec 2014 13:56:22 -0500 Subject: [PATCH 083/315] Teach tmlanguage.js to process multiple .tmLanguage files at once You can now pass more than one .tmLanguage file to tmlanguage.js and it will process each one in turn. This can vastly speed up the processing of multiple files as you don't have to pay the node/V8 startup cost for each file. Note that the script's "dev mode" is now controlled by a --dev flag rather than an unnamed second argument. --- tool/tmlanguage.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tool/tmlanguage.js b/tool/tmlanguage.js index 9261a2f1..0e458330 100644 --- a/tool/tmlanguage.js +++ b/tool/tmlanguage.js @@ -684,13 +684,14 @@ function convertTmLanguage(name, langStr) { if (!module.parent) { var args = process.argv.splice(2); - var tmLanguageFile = args[0]; - var devMode = args[1]; - if (tmLanguageFile === undefined) { - console.error("Usage: node tmlanguage.js path/or/url/to/syntax.file"); + var devMode = args[0] == "--dev"; + if (devMode) + args.shift(); + if (args.length < 1) { + console.error("Usage: node tmlanguage.js [--dev] path/or/url/to/syntax.file ..."); process.exit(1); } - fetchAndConvert(tmLanguageFile); + args.forEach(fetchAndConvert); } else { exports.fetchAndConvert = fetchAndConvert; } From 8c1aa5c7723928283236efb358ac45f871ce219a Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 22 Jul 2014 03:27:51 +0400 Subject: [PATCH 084/315] do not use automatic scroll into view prepares for deprecating the feature in the next version of ace --- lib/ace/autocomplete/popup.js | 3 +++ lib/ace/commands/default_commands.js | 17 ++++++++++++-- lib/ace/commands/multi_select_commands.js | 13 ++++++++++- lib/ace/editor.js | 27 +++++++++++++++++++++-- lib/ace/mouse/default_handlers.js | 15 +++++++------ lib/ace/multi_select.js | 27 ----------------------- 6 files changed, 63 insertions(+), 39 deletions(-) diff --git a/lib/ace/autocomplete/popup.js b/lib/ace/autocomplete/popup.js index f580e391..862a1c5e 100644 --- a/lib/ace/autocomplete/popup.js +++ b/lib/ace/autocomplete/popup.js @@ -209,6 +209,8 @@ var AcePopup = function(parentNode) { return this.screenWidth = 0; }; + popup.$blockScrolling = Infinity; + // public popup.isOpen = false; popup.isTopdown = false; @@ -241,6 +243,7 @@ var AcePopup = function(parentNode) { popup.on("changeSelection", function() { if (popup.isOpen) popup.setRow(popup.selection.lead.row); + popup.renderer.scrollCursorIntoView(); }); popup.hide = function() { diff --git a/lib/ace/commands/default_commands.js b/lib/ace/commands/default_commands.js index a150a76f..c5d34aae 100644 --- a/lib/ace/commands/default_commands.js +++ b/lib/ace/commands/default_commands.js @@ -205,12 +205,14 @@ exports.commands = [{ bindKey: bindKey("Shift-Up", "Shift-Up"), exec: function(editor) { editor.getSelection().selectUp(); }, multiSelectAction: "forEach", + scrollIntoView: "cursor", readOnly: true }, { name: "golineup", bindKey: bindKey("Up", "Up|Ctrl-P"), exec: function(editor, args) { editor.navigateUp(args.times); }, multiSelectAction: "forEach", + scrollIntoView: "cursor", readOnly: true }, { name: "selecttoend", @@ -395,12 +397,21 @@ exports.commands = [{ bindKey: bindKey("Ctrl-P", "Ctrl-P"), exec: function(editor) { editor.jumpToMatching(); }, multiSelectAction: "forEach", + scrollIntoView: "animate", readOnly: true }, { name: "selecttomatching", bindKey: bindKey("Ctrl-Shift-P", "Ctrl-Shift-P"), exec: function(editor) { editor.jumpToMatching(true); }, multiSelectAction: "forEach", + scrollIntoView: "animate", + readOnly: true +}, { + name: "expandToMatching", + bindKey: bindKey("Ctrl-Shift-M", "Ctrl-Shift-M"), + exec: function(editor) { editor.jumpToMatching(true, true); }, + multiSelectAction: "forEach", + scrollIntoView: "animate", readOnly: true }, { name: "passKeysToBrowser", @@ -458,11 +469,13 @@ exports.commands = [{ name: "modifyNumberUp", bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"), exec: function(editor) { editor.modifyNumber(1); }, + scrollIntoView: "cursor", multiSelectAction: "forEach" }, { name: "modifyNumberDown", bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"), exec: function(editor) { editor.modifyNumber(-1); }, + scrollIntoView: "cursor", multiSelectAction: "forEach" }, { name: "replace", @@ -629,7 +642,7 @@ exports.commands = [{ var isBackwards = editor.selection.isBackwards(); var selectionStart = isBackwards ? editor.selection.getSelectionLead() : editor.selection.getSelectionAnchor(); var selectionEnd = isBackwards ? editor.selection.getSelectionAnchor() : editor.selection.getSelectionLead(); - var firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length + var firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length; var selectedText = editor.session.doc.getTextRange(editor.selection.getRange()); var selectedCount = selectedText.replace(/\n\s*/, " ").length; var insertLine = editor.session.doc.getLine(selectionStart.row); @@ -640,7 +653,7 @@ exports.commands = [{ curLine = " " + curLine; } insertLine += curLine; - }; + } if (selectionEnd.row + 1 < (editor.session.doc.getLength() - 1)) { // Don't insert a newline at the end of the document diff --git a/lib/ace/commands/multi_select_commands.js b/lib/ace/commands/multi_select_commands.js index 347eb606..ba6392bc 100644 --- a/lib/ace/commands/multi_select_commands.js +++ b/lib/ace/commands/multi_select_commands.js @@ -35,41 +35,49 @@ exports.defaultCommands = [{ name: "addCursorAbove", exec: function(editor) { editor.selectMoreLines(-1); }, bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"}, + scrollIntoView: "cursor", readonly: true }, { name: "addCursorBelow", exec: function(editor) { editor.selectMoreLines(1); }, bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"}, + scrollIntoView: "cursor", readonly: true }, { name: "addCursorAboveSkipCurrent", exec: function(editor) { editor.selectMoreLines(-1, true); }, bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"}, + scrollIntoView: "cursor", readonly: true }, { name: "addCursorBelowSkipCurrent", exec: function(editor) { editor.selectMoreLines(1, true); }, bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"}, + scrollIntoView: "cursor", readonly: true }, { name: "selectMoreBefore", exec: function(editor) { editor.selectMore(-1); }, bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"}, + scrollIntoView: "cursor", readonly: true }, { name: "selectMoreAfter", exec: function(editor) { editor.selectMore(1); }, bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"}, + scrollIntoView: "cursor", readonly: true }, { name: "selectNextBefore", exec: function(editor) { editor.selectMore(-1, true); }, bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"}, + scrollIntoView: "cursor", readonly: true }, { name: "selectNextAfter", exec: function(editor) { editor.selectMore(1, true); }, bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"}, + scrollIntoView: "cursor", readonly: true }, { name: "splitIntoLines", @@ -79,11 +87,13 @@ exports.defaultCommands = [{ }, { name: "alignCursors", exec: function(editor) { editor.alignCursors(); }, - bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"} + bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"}, + scrollIntoView: "cursor" }, { name: "findAll", exec: function(editor) { editor.findAll(); }, bindKey: {win: "Ctrl-Alt-K", mac: "Ctrl-Alt-G"}, + scrollIntoView: "cursor", readonly: true }]; @@ -92,6 +102,7 @@ exports.multiSelectCommands = [{ name: "singleSelection", bindKey: "esc", exec: function(editor) { editor.exitMultiSelectMode(); }, + scrollIntoView: "cursor", readonly: true, isAvailable: function(editor) {return editor && editor.inMultiSelectMode} }]; diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 59b136b1..a3fdc978 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -150,7 +150,8 @@ var Editor = function(renderer, session) { args: commadEvent.args, scrollTop: this.renderer.scrollTop }; - + if (this.curOp.command.name) + this.$blockScrolling++; // this.selections.push(this.selection.toJSON()); }; @@ -160,6 +161,8 @@ var Editor = function(renderer, session) { return this.curOp = null; this._signal("beforeEndOperation"); var command = this.curOp.command; + if (command.name && this.$blockScrolling) + this.$blockScrolling--; if (command && command.scrollIntoView) { switch (command.scrollIntoView) { case "center": @@ -714,6 +717,7 @@ var Editor = function(renderer, session) { this.$cursorChange(); if (!this.$blockScrolling) { + console.warn("In next version of ace automatic scrolling into view will be disabled"); this.renderer.scrollCursorIntoView(); } @@ -902,9 +906,28 @@ var Editor = function(renderer, session) { // todo this should change when paste becomes a command if (this.$readOnly) return; + var e = {text: text}; this._signal("paste", e); - this.insert(e.text, true); + text = e.text; + if (!this.inMultiSelectMode || this.inVirtualSelectionMode) { + this.insert(text); + } else { + var lines = text.split(/\r\n|\r|\n/); + var ranges = this.selection.rangeList.ranges; + + if (lines.length > ranges.length || lines.length < 2 || !lines[1]) + return this.commands.exec("insertstring", this, text); + + for (var i = ranges.length; i--;) { + var range = ranges[i]; + if (!range.isEmpty()) + this.session.remove(range); + + this.session.insert(range.start, lines[i]); + } + } + this.renderer.scrollCursorIntoView(); }; this.execCommand = function(command, args) { diff --git a/lib/ace/mouse/default_handlers.js b/lib/ace/mouse/default_handlers.js index bbd85484..a48d1097 100644 --- a/lib/ace/mouse/default_handlers.js +++ b/lib/ace/mouse/default_handlers.js @@ -70,10 +70,10 @@ function DefaultHandlers(mouseHandler) { if (button !== 0) { var selectionRange = editor.getSelectionRange(); var selectionEmpty = selectionRange.isEmpty(); - + editor.$blockScrolling++; if (selectionEmpty) editor.selection.moveToPosition(pos); - + editor.$blockScrolling--; // 2: contextmenu, 1: linux paste editor.textInput.onContextMenu(ev.domEvent); return; // stopping event here breaks contextmenu on ff mac @@ -100,7 +100,7 @@ function DefaultHandlers(mouseHandler) { pos = pos || this.editor.renderer.screenToTextCoordinates(this.x, this.y); var editor = this.editor; // allow double/triple click handlers to change selection - + editor.$blockScrolling++; if (this.mousedownEvent.getShiftKey()) editor.selection.selectToPosition(pos); else if (!waitForClickSelection) @@ -112,12 +112,13 @@ function DefaultHandlers(mouseHandler) { } editor.setStyle("ace_selecting"); this.setState("select"); + editor.$blockScrolling--; }; this.select = function() { var anchor, editor = this.editor; var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y); - + editor.$blockScrolling++; if (this.$clickSelection) { var cmp = this.$clickSelection.comparePoint(cursor); @@ -133,7 +134,7 @@ function DefaultHandlers(mouseHandler) { editor.selection.setSelectionAnchor(anchor.row, anchor.column); } editor.selection.selectToPosition(cursor); - + editor.$blockScrolling--; editor.renderer.scrollCursorIntoView(); }; @@ -141,7 +142,7 @@ function DefaultHandlers(mouseHandler) { var anchor, editor = this.editor; var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y); var range = editor.selection[unitName](cursor.row, cursor.column); - + editor.$blockScrolling++; if (this.$clickSelection) { var cmpStart = this.$clickSelection.comparePoint(range.start); var cmpEnd = this.$clickSelection.comparePoint(range.end); @@ -165,7 +166,7 @@ function DefaultHandlers(mouseHandler) { editor.selection.setSelectionAnchor(anchor.row, anchor.column); } editor.selection.selectToPosition(cursor); - + editor.$blockScrolling--; editor.renderer.scrollCursorIntoView(); }; diff --git a/lib/ace/multi_select.js b/lib/ace/multi_select.js index 729d5253..0635afc2 100644 --- a/lib/ace/multi_select.js +++ b/lib/ace/multi_select.js @@ -558,33 +558,6 @@ var Editor = require("./editor").Editor; } }; - // todo this should change when paste becomes a command - this.onPaste = function(text) { - if (this.$readOnly) - return; - - - var e = {text: text}; - this._signal("paste", e); - text = e.text; - if (!this.inMultiSelectMode || this.inVirtualSelectionMode) - return this.insert(text); - - var lines = text.split(/\r\n|\r|\n/); - var ranges = this.selection.rangeList.ranges; - - if (lines.length > ranges.length || lines.length < 2 || !lines[1]) - return this.commands.exec("insertstring", this, text); - - for (var i = ranges.length; i--;) { - var range = ranges[i]; - if (!range.isEmpty()) - this.session.remove(range); - - this.session.insert(range.start, lines[i]); - } - }; - /** * Finds and selects all the occurences of `needle`. * @param {String} The text to find From a71c17b46f2088d7584b3e9d09d2c83787bc1954 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 23 Nov 2014 15:10:50 +0400 Subject: [PATCH 085/315] add config.warn and refactor config to allow sharing with ace_tree --- lib/ace/config.js | 105 +------------------------ lib/ace/edit_session.js | 3 +- lib/ace/editor.js | 5 +- lib/ace/lib/app_config.js | 158 ++++++++++++++++++++++++++++++++++++++ lib/ace/lib/dom.js | 7 +- lib/ace/tokenizer.js | 10 +-- 6 files changed, 173 insertions(+), 115 deletions(-) create mode 100644 lib/ace/lib/app_config.js diff --git a/lib/ace/config.js b/lib/ace/config.js index 6116da96..34bf50fd 100644 --- a/lib/ace/config.js +++ b/lib/ace/config.js @@ -34,7 +34,9 @@ define(function(require, exports, module) { var lang = require("./lib/lang"); var oop = require("./lib/oop"); var net = require("./lib/net"); -var EventEmitter = require("./lib/event_emitter").EventEmitter; +var AppConfig = require("./lib/app_config").AppConfig; + +module.exports = exports = new AppConfig(); var global = (function() { return this; @@ -69,8 +71,6 @@ exports.all = function() { }; // module loading -oop.implement(exports, EventEmitter); - exports.moduleUrl = function(name, component) { if (options.$moduleUrls[name]) return options.$moduleUrls[name]; @@ -142,7 +142,6 @@ exports.loadModule = function(moduleName, onLoad) { net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad); }; - // initialization function init(packaged) { options.packaged = packaged || require.packaged || module.packaged || (global.define && define.packaged); @@ -200,102 +199,4 @@ function deHyphenate(str) { return str.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); }); } -var optionsProvider = { - setOptions: function(optList) { - Object.keys(optList).forEach(function(key) { - this.setOption(key, optList[key]); - }, this); - }, - getOptions: function(optionNames) { - var result = {}; - if (!optionNames) { - optionNames = Object.keys(this.$options); - } else if (!Array.isArray(optionNames)) { - result = optionNames; - optionNames = Object.keys(result); - } - optionNames.forEach(function(key) { - result[key] = this.getOption(key); - }, this); - return result; - }, - setOption: function(name, value) { - if (this["$" + name] === value) - return; - var opt = this.$options[name]; - if (!opt) { - if (typeof console != "undefined" && console.warn) - console.warn('misspelled option "' + name + '"'); - return undefined; - } - if (opt.forwardTo) - return this[opt.forwardTo] && this[opt.forwardTo].setOption(name, value); - - if (!opt.handlesSet) - this["$" + name] = value; - if (opt && opt.set) - opt.set.call(this, value); - }, - getOption: function(name) { - var opt = this.$options[name]; - if (!opt) { - if (typeof console != "undefined" && console.warn) - console.warn('misspelled option "' + name + '"'); - return undefined; - } - if (opt.forwardTo) - return this[opt.forwardTo] && this[opt.forwardTo].getOption(name); - return opt && opt.get ? opt.get.call(this) : this["$" + name]; - } -}; - -var defaultOptions = {}; -/* - * option {name, value, initialValue, setterName, set, get } - */ -exports.defineOptions = function(obj, path, options) { - if (!obj.$options) - defaultOptions[path] = obj.$options = {}; - - Object.keys(options).forEach(function(key) { - var opt = options[key]; - if (typeof opt == "string") - opt = {forwardTo: opt}; - - opt.name || (opt.name = key); - obj.$options[opt.name] = opt; - if ("initialValue" in opt) - obj["$" + opt.name] = opt.initialValue; - }); - - // implement option provider interface - oop.implement(obj, optionsProvider); - - return this; -}; - -exports.resetOptions = function(obj) { - Object.keys(obj.$options).forEach(function(key) { - var opt = obj.$options[key]; - if ("value" in opt) - obj.setOption(key, opt.value); - }); -}; - -exports.setDefaultValue = function(path, name, value) { - var opts = defaultOptions[path] || (defaultOptions[path] = {}); - if (opts[name]) { - if (opts.forwardTo) - exports.setDefaultValue(opts.forwardTo, name, value); - else - opts[name].value = value; - } -}; - -exports.setDefaultValues = function(path, optionHash) { - Object.keys(optionHash).forEach(function(key) { - exports.setDefaultValue(path, key, optionHash[key]); - }); -}; - }); diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 932a9e3d..347c854a 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -969,8 +969,7 @@ var EditSession = function(text, mode) { try { this.$worker = this.$mode.createWorker(this); } catch (e) { - if (typeof console == "object" && console.error) - console.log("Could not load worker", e); + config.warn("Could not load worker", e); this.$worker = null; } }; diff --git a/lib/ace/editor.js b/lib/ace/editor.js index a3fdc978..78c7c18d 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -717,7 +717,10 @@ var Editor = function(renderer, session) { this.$cursorChange(); if (!this.$blockScrolling) { - console.warn("In next version of ace automatic scrolling into view will be disabled"); + config.warn("Automatically scrolling cursor into view after selection change", + "this will be disabled in the next version", + "set editor.$blockScrolling = Infinity to disable this message" + ); this.renderer.scrollCursorIntoView(); } diff --git a/lib/ace/lib/app_config.js b/lib/ace/lib/app_config.js new file mode 100644 index 00000000..84b9e70c --- /dev/null +++ b/lib/ace/lib/app_config.js @@ -0,0 +1,158 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"no use strict"; + +var lang = require("./lang"); +var oop = require("./oop"); +var EventEmitter = require("./event_emitter").EventEmitter; + +var optionsProvider = { + setOptions: function(optList) { + Object.keys(optList).forEach(function(key) { + this.setOption(key, optList[key]); + }, this); + }, + getOptions: function(optionNames) { + var result = {}; + if (!optionNames) { + optionNames = Object.keys(this.$options); + } else if (!Array.isArray(optionNames)) { + result = optionNames; + optionNames = Object.keys(result); + } + optionNames.forEach(function(key) { + result[key] = this.getOption(key); + }, this); + return result; + }, + setOption: function(name, value) { + if (this["$" + name] === value) + return; + var opt = this.$options[name]; + if (!opt) { + return warn('misspelled option "' + name + '"'); + } + if (opt.forwardTo) + return this[opt.forwardTo] && this[opt.forwardTo].setOption(name, value); + + if (!opt.handlesSet) + this["$" + name] = value; + if (opt && opt.set) + opt.set.call(this, value); + }, + getOption: function(name) { + var opt = this.$options[name]; + if (!opt) { + return warn('misspelled option "' + name + '"'); + } + if (opt.forwardTo) + return this[opt.forwardTo] && this[opt.forwardTo].getOption(name); + return opt && opt.get ? opt.get.call(this) : this["$" + name]; + } +}; + +function warn(message) { + if (typeof console != "undefined" && console.warn) + console.warn.apply(console, arguments); +} + +function reportError(msg, data) { + var e = new Error(msg); + e.data = data; + if (typeof console == "object" && console.error) + console.error(e); + setTimeout(function() { throw e; }); +}; + +var AppConfig = function() { + this.$defaultOptions = {}; +}; + +(function() { + // module loading + oop.implement(this, EventEmitter); + /* + * option {name, value, initialValue, setterName, set, get } + */ + this.defineOptions = function(obj, path, options) { + if (!obj.$options) + this.$defaultOptions[path] = obj.$options = {}; + + Object.keys(options).forEach(function(key) { + var opt = options[key]; + if (typeof opt == "string") + opt = {forwardTo: opt}; + + opt.name || (opt.name = key); + obj.$options[opt.name] = opt; + if ("initialValue" in opt) + obj["$" + opt.name] = opt.initialValue; + }); + + // implement option provider interface + oop.implement(obj, optionsProvider); + + return this; + }; + + this.resetOptions = function(obj) { + Object.keys(obj.$options).forEach(function(key) { + var opt = obj.$options[key]; + if ("value" in opt) + obj.setOption(key, opt.value); + }); + }; + + this.setDefaultValue = function(path, name, value) { + var opts = this.$defaultOptions[path] || (this.$defaultOptions[path] = {}); + if (opts[name]) { + if (opts.forwardTo) + this.setDefaultValue(opts.forwardTo, name, value); + else + opts[name].value = value; + } + }; + + this.setDefaultValues = function(path, optionHash) { + Object.keys(optionHash).forEach(function(key) { + this.setDefaultValue(path, key, optionHash[key]); + }); + }; + + this.warn = warn; + this.reportError = reportError; + +}).call(AppConfig.prototype); + +exports.AppConfig = AppConfig; + +}); diff --git a/lib/ace/lib/dom.js b/lib/ace/lib/dom.js index 65f20d7d..ef2f7caa 100644 --- a/lib/ace/lib/dom.js +++ b/lib/ace/lib/dom.js @@ -31,9 +31,6 @@ define(function(require, exports, module) { "use strict"; -if (typeof document == "undefined") - return; - var XHTML_NS = "http://www.w3.org/1999/xhtml"; exports.getDocumentHead = function(doc) { @@ -175,6 +172,10 @@ exports.getInnerHeight = function(element) { ); }; + +if (typeof document == "undefined") + return; + if (window.pageYOffset !== undefined) { exports.getPageScrollTop = function() { return window.pageYOffset; diff --git a/lib/ace/tokenizer.js b/lib/ace/tokenizer.js index a0756157..72490fbb 100644 --- a/lib/ace/tokenizer.js +++ b/lib/ace/tokenizer.js @@ -31,6 +31,7 @@ define(function(require, exports, module) { "use strict"; +var config = require("./config"); // tokenizing lines longer than this makes editor very slow var MAX_TOKEN_COUNT = 2000; /** @@ -353,13 +354,8 @@ var Tokenizer = function(rules) { }; }; - this.reportError = function(msg, data) { - var e = new Error(msg); - e.data = data; - if (typeof console == "object" && console.error) - console.error(e); - setTimeout(function() { throw e; }); - }; + this.reportError = config.reportError; + }).call(Tokenizer.prototype); exports.Tokenizer = Tokenizer; From 29597325d97f324442e76b9f2c36ceb013ba332e Mon Sep 17 00:00:00 2001 From: Victorien ELVINGER Date: Sat, 6 Dec 2014 19:50:52 +0100 Subject: [PATCH 086/315] Update Eiffel programming language definition. - Disable comments into strings - Enable concise form for real numbers - Enable juxtaposed digit separators - Check char and string content. --- lib/ace/mode/eiffel_highlight_rules.js | 67 ++++++++++++-------------- 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/lib/ace/mode/eiffel_highlight_rules.js b/lib/ace/mode/eiffel_highlight_rules.js index f2cc8bd6..a95a4f37 100644 --- a/lib/ace/mode/eiffel_highlight_rules.js +++ b/lib/ace/mode/eiffel_highlight_rules.js @@ -39,7 +39,7 @@ var EiffelHighlightRules = function() { "class|convert|create|debug|deferred|detachable|do|else|elseif|end|" + "ensure|expanded|export|external|feature|from|frozen|if|inherit|" + "inspect|invariant|like|local|loop|not|note|obsolete|old|once|" + - "Precursor|redefine|rename|require|rescue|retry|select|separate|" + + "Precursor|redefine|rename|require|rescue|retry|select|separate|" + "some|then|undefine|until|variant|when"; var operatorKeywords = "and|implies|or|xor"; @@ -58,45 +58,44 @@ var EiffelHighlightRules = function() { "keyword": keywords }, "identifier", true); + var simpleString = /(?:[^"%\b\f\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_*[\da-fA-F])*|0[cC][0-7](?:_*[0-7])*|0[bB][01](?:_*[01])*|\d(?:_*\d)*)\/)+?/; + this.$rules = { "start": [{ - token : "comment.line.double-dash", - regex : /--.*$/ - }, { - token : "string.quoted.double", - regex : /"(?:%"|[^%])*?"/ - }, { - token : "string.quoted.other", // "[ ]" aligned verbatim string + token : "string.quoted.other", // Aligned-verbatim-strings (verbatim option not supported) regex : /"\[/, next: "aligned_verbatim_string" }, { - token : "string.quoted.other", // "{ }" non-aligned verbatim string + token : "string.quoted.other", // Non-aligned-verbatim-strings (verbatim option not supported) regex : /"\{/, next: "non-aligned_verbatim_string" + }, { + token : "string.quoted.double", + regex : /"(?:[^%\b\f\n\r\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_*[\da-fA-F])*|0[cC][0-7](?:_*[0-7])*|0[bB][01](?:_*[01])*|\d(?:_*\d)*)\/)*?"/ + }, { + token : "comment.line.double-dash", + regex : /--.*/ }, { token : "constant.character", - regex : /'(?:%%|%T|%R|%N|%F|%'|[^%])'/ + regex : /'(?:[^%\b\f\n\r\t\v]|%[A-DFHLNQR-V%'"()<>]|%\/(?:0[xX][\da-fA-F](?:_*[\da-fA-F])*|0[cC][0-7](?:_*[0-7])*|0[bB][01](?:_*[01])*|\d(?:_*\d)*)\/)'/ }, { - token : "constant.numeric", // real - regex : /(?:\d(?:_?\d)*\.|\.\d)(?:\d*[eE][+-]?\d+)?\b/ + token : "constant.numeric", // hexa | octal | bin + regex : /\b0(?:[xX][\da-fA-F](?:_*[\da-fA-F])*|[cC][0-7](?:_*[0-7])*|[bB][01](?:_*[01])*)\b/ }, { - token : "constant.numeric", // integer - regex : /\d(?:_?\d)*\b/ + token : "constant.numeric", + regex : /(?:(?:\d(?:_*\d)*)?\.(?:(?:\d(?:_*\d)*)?[eE][+-]?)?\d(?:_*\d)*)|\d(?:_*\d)*\.?/ }, { - token : "constant.numeric", // hex - regex : /0[xX][a-fA-F\d](?:_?[a-fA-F\d])*\b/ + token : "paren.lparen", + regex : /[\[({]|<<|\|\(/ }, { - token : "constant.numeric", // octal - regex : /0[cC][0-7](?:_?[0-7])*\b/ - },{ - token : "constant.numeric", // bin - regex : /0[bB][01](?:_?[01])*\b/ - }, { - token : "keyword.operator", - regex : /\+|\-|\*|\/|\\\\|\/\/|\^|~|\/~|<|>|<=|>=|\/=|=|:=|\|\.\.\||\.\./ + token : "paren.rparen", + regex : /[\])}]|>>|\|\)/ }, { token : "keyword.operator", // punctuation - regex : /\.|:|,|;\b/ + regex : /:=|->|\.(?=\w)|[;,:?]/ + }, { + token : "keyword.operator", + regex : /\\\\|\|\.\.\||\.\.|\/[~\/]?|[><\/]=?|[-+*^=~]/ }, { token : function (v) { var result = keywordMapper (v); @@ -106,33 +105,27 @@ var EiffelHighlightRules = function() { return result; }, regex : /[a-zA-Z][a-zA-Z\d_]*\b/ - }, { - token : "paren.lparen", - regex : /[\[({]/ - }, { - token : "paren.rparen", - regex : /[\])}]/ }, { token : "text", regex : /\s+/ } ], "aligned_verbatim_string" : [{ - token : "string", // closing multi-line comment + token : "string", regex : /]"/, next : "start" }, { - token : "string", // comment spanning whole line - regex : /[^(?:\]")]+/ + token : "string", + regex : simpleString } ], "non-aligned_verbatim_string" : [{ - token : "string.quoted.other", // closing multi-line comment + token : "string.quoted.other", regex : /}"/, next : "start" }, { - token : "string.quoted.other", // comment spanning whole line - regex : /[^(?:\}")]+/ + token : "string.quoted.other", + regex : simpleString } ]}; }; From 354dc37ea604916051024e4d9da368ae1ff46f98 Mon Sep 17 00:00:00 2001 From: Victorien ELVINGER Date: Sat, 6 Dec 2014 20:04:27 +0100 Subject: [PATCH 087/315] Remove unneeded regex groups for Eiffel --- lib/ace/mode/eiffel_highlight_rules.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/mode/eiffel_highlight_rules.js b/lib/ace/mode/eiffel_highlight_rules.js index a95a4f37..a3ca8896 100644 --- a/lib/ace/mode/eiffel_highlight_rules.js +++ b/lib/ace/mode/eiffel_highlight_rules.js @@ -83,7 +83,7 @@ var EiffelHighlightRules = function() { regex : /\b0(?:[xX][\da-fA-F](?:_*[\da-fA-F])*|[cC][0-7](?:_*[0-7])*|[bB][01](?:_*[01])*)\b/ }, { token : "constant.numeric", - regex : /(?:(?:\d(?:_*\d)*)?\.(?:(?:\d(?:_*\d)*)?[eE][+-]?)?\d(?:_*\d)*)|\d(?:_*\d)*\.?/ + regex : /(?:\d(?:_*\d)*)?\.(?:(?:\d(?:_*\d)*)?[eE][+-]?)?\d(?:_*\d)*|\d(?:_*\d)*\.?/ }, { token : "paren.lparen", regex : /[\[({]|<<|\|\(/ From e54882db64e20da55ff06f15acb452798fc3f2ae Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 7 Dec 2014 01:08:06 +0400 Subject: [PATCH 088/315] use setAttribute instead of autocorrect setter, since the setter doesn't work on ipad --- lib/ace/keyboard/textinput.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ace/keyboard/textinput.js b/lib/ace/keyboard/textinput.js index c0902e27..605f5b8e 100644 --- a/lib/ace/keyboard/textinput.js +++ b/lib/ace/keyboard/textinput.js @@ -45,10 +45,10 @@ var TextInput = function(parentNode, host) { if (useragent.isTouchPad) text.setAttribute("x-palm-disable-auto-cap", true); - text.wrap = "off"; - text.autocorrect = "off"; - text.autocapitalize = "off"; - text.spellcheck = false; + text.setAttribute("wrap", "off"); + text.setAttribute("autocorrect", "off"); + text.setAttribute("autocapitalize", "off"); + text.setAttribute("spellcheck", false); text.style.opacity = "0"; if (useragent.isOldIE) text.style.top = "-100px"; From 2fc497477de8a017bd61a173b2a93dbe4e81a655 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 7 Dec 2014 01:26:24 +0400 Subject: [PATCH 089/315] highlight tags when cursor is before tagname --- lib/ace/editor.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 78c7c18d..0d4e9df2 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -539,11 +539,14 @@ var Editor = function(renderer, session) { var iterator = new TokenIterator(self.session, pos.row, pos.column); var token = iterator.getCurrentToken(); - if (!token || token.type.indexOf('tag-name') === -1) { + if (!token || !/\b(?:tag-open|tag-name)/.test(token.type)) { session.removeMarker(session.$tagHighlight); session.$tagHighlight = null; return; } + + if (token.type.indexOf("tag-open") != -1) + token = iterator.stepForward(); var tag = token.value; var depth = 0; From c49e5bfef983da748a8a140e537a7f03a7bfee9c Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 7 Dec 2014 01:26:44 +0400 Subject: [PATCH 090/315] disable warning --- lib/ace/mouse/multi_select_handler.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/ace/mouse/multi_select_handler.js b/lib/ace/mouse/multi_select_handler.js index 8d6af6b5..9b52e237 100644 --- a/lib/ace/mouse/multi_select_handler.js +++ b/lib/ace/mouse/multi_select_handler.js @@ -150,7 +150,8 @@ function onMouseDown(e) { if (isSamePoint(screenCursor, newCursor) && isSamePoint(cursor, selection.lead)) return; screenCursor = newCursor; - + + editor.$blockScrolling++; editor.selection.moveToPosition(cursor); editor.renderer.scrollCursorIntoView(); @@ -160,8 +161,9 @@ function onMouseDown(e) { rectSel[0] = editor.$mouseHandler.$clickSelection.clone(); rectSel.forEach(editor.addSelectionMarker, editor); editor.updateSelectionMarkers(); + editor.$blockScrolling--; }; - + editor.$blockScrolling++; if (isMultiSelect && !accel) { selection.toSingleRange(); } else if (!isMultiSelect && accel) { @@ -173,6 +175,7 @@ function onMouseDown(e) { screenAnchor = session.documentToScreenPosition(selection.lead); else selection.moveToPosition(pos); + editor.$blockScrolling--; screenCursor = {row: -1, column: -1}; From 119259b7027574052a81e10d9e5947de69b2a86f Mon Sep 17 00:00:00 2001 From: "Matthias S. Benkmann" Date: Sun, 7 Dec 2014 16:54:41 +0100 Subject: [PATCH 091/315] add *~ (backup files created by various editors) to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c6a7ecc9..59ec847b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .DS_Store *.swp *.tmp +*~ # Project files that should not be in the repo .* From cfdb223e7a35f95cd023c5270ce0f6bd8197bb16 Mon Sep 17 00:00:00 2001 From: Adam Jimenez Date: Fri, 12 Dec 2014 10:27:45 +0000 Subject: [PATCH 092/315] Autocomplete exactMatch option Option to show only exact matches in autocomplete --- lib/ace/autocomplete.js | 74 ++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index 2544c858..dd04426e 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -42,6 +42,7 @@ var snippetManager = require("./snippets").snippetManager; var Autocomplete = function() { this.autoInsert = true; this.autoSelect = true; + this.exactMatch = false; this.keyboardHandler = new HashHandler(); this.keyboardHandler.bindKeys(this.commands); @@ -53,7 +54,7 @@ var Autocomplete = function() { this.changeTimer = lang.delayedCall(function() { this.updateCompletions(true); }.bind(this)); - + this.tooltipTimer = lang.delayedCall(this.updateDocTooltip.bind(this), 50); }; @@ -72,7 +73,7 @@ var Autocomplete = function() { this.popup.on("changeHoverMarker", this.tooltipTimer.bind(null, null)); return this.popup; }; - + this.getPopup = function() { return this.popup || this.$init(); }; @@ -118,7 +119,7 @@ var Autocomplete = function() { this.gatherCompletionsId += 1; this.popup.hide(); } - + if (this.base) this.base.detach(); this.activated = false; @@ -141,7 +142,7 @@ var Autocomplete = function() { // on IE preventDefault doesn't stop scrollbar from being focussed var el = document.activeElement; var text = this.editor.textInput.getElement() - if (el != text && el.parentNode != this.popup.container + if (el != text && el.parentNode != this.popup.container && el != this.tooltipNode && e.relatedTarget != this.tooltipNode && e.relatedTarget != text ) { @@ -227,7 +228,7 @@ var Autocomplete = function() { this.base = session.doc.createAnchor(pos.row, pos.column - prefix.length); this.base.$insertRight = true; - + var matches = []; var total = editor.completers.length; editor.completers.forEach(function(completer, i) { @@ -297,7 +298,7 @@ var Autocomplete = function() { var prefix = results.prefix; var matches = results && results.matches; - + if (!matches || !matches.length) return detachIfFinished(); @@ -306,6 +307,10 @@ var Autocomplete = function() { return; this.completions = new FilteredList(matches); + + if (this.exactMatch) + this.completions.exactMatch = true; + this.completions.setFilter(prefix); var filtered = this.completions.filtered; @@ -328,7 +333,7 @@ var Autocomplete = function() { this.cancelContextMenu = function() { this.editor.$mouseHandler.cancelContextMenu(); }; - + this.updateDocTooltip = function() { var popup = this.popup; var all = popup.data; @@ -343,14 +348,14 @@ var Autocomplete = function() { }); if (!doc) doc = selected; - + if (typeof doc == "string") doc = {docText: doc} if (!doc || !(doc.docHTML || doc.docText)) return this.hideDocTooltip(); this.showDocTooltip(doc); }; - + this.showDocTooltip = function(item) { if (!this.tooltipNode) { this.tooltipNode = dom.createElement("div"); @@ -360,21 +365,21 @@ var Autocomplete = function() { this.tooltipNode.tabIndex = -1; this.tooltipNode.onblur = this.blurListener.bind(this); } - + var tooltipNode = this.tooltipNode; if (item.docHTML) { tooltipNode.innerHTML = item.docHTML; } else if (item.docText) { tooltipNode.textContent = item.docText; } - + if (!tooltipNode.parentNode) - document.body.appendChild(tooltipNode); + document.body.appendChild(tooltipNode); var popup = this.popup; var rect = popup.container.getBoundingClientRect(); tooltipNode.style.top = popup.container.style.top; tooltipNode.style.bottom = popup.container.style.bottom; - + if (window.innerWidth - rect.right < 320) { tooltipNode.style.right = window.innerWidth - rect.left + "px"; tooltipNode.style.left = ""; @@ -384,7 +389,7 @@ var Autocomplete = function() { } tooltipNode.style.display = "block"; }; - + this.hideDocTooltip = function() { this.tooltipTimer.cancel(); if (!this.tooltipNode) return; @@ -392,7 +397,7 @@ var Autocomplete = function() { if (!this.editor.isFocused() && document.activeElement == el) this.editor.focus(); this.tooltipNode = null; - if (el.parentNode) + if (el.parentNode) el.parentNode.removeChild(el); }; @@ -403,7 +408,7 @@ Autocomplete.startCommand = { exec: function(editor) { if (!editor.completer) editor.completer = new Autocomplete(); - editor.completer.autoInsert = + editor.completer.autoInsert = editor.completer.autoSelect = true; editor.completer.showPopup(editor); // needed for firefox on mac @@ -416,6 +421,7 @@ var FilteredList = function(array, filterText, mutateData) { this.all = array; this.filtered = array; this.filterText = filterText || ""; + this.exactMatch = false; }; (function(){ this.setFilter = function(str) { @@ -452,23 +458,29 @@ var FilteredList = function(array, filterText, mutateData) { var matchMask = 0; var penalty = 0; var index, distance; - // caption char iteration is faster in Chrome but slower in Firefox, so lets use indexOf - for (var j = 0; j < needle.length; j++) { - // TODO add penalty on case mismatch - var i1 = caption.indexOf(lower[j], lastIndex + 1); - var i2 = caption.indexOf(upper[j], lastIndex + 1); - index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2; - if (index < 0) + + if (this.exactMatch) { + if (needle !== caption.substr(0, needle.length)) continue loop; - distance = index - lastIndex - 1; - if (distance > 0) { - // first char mismatch should be more sensitive - if (lastIndex === -1) - penalty += 10; - penalty += distance; + }else{ + // caption char iteration is faster in Chrome but slower in Firefox, so lets use indexOf + for (var j = 0; j < needle.length; j++) { + // TODO add penalty on case mismatch + var i1 = caption.indexOf(lower[j], lastIndex + 1); + var i2 = caption.indexOf(upper[j], lastIndex + 1); + index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2; + if (index < 0) + continue loop; + distance = index - lastIndex - 1; + if (distance > 0) { + // first char mismatch should be more sensitive + if (lastIndex === -1) + penalty += 10; + penalty += distance; + } + matchMask = matchMask | (1 << index); + lastIndex = index; } - matchMask = matchMask | (1 << index); - lastIndex = index; } item.matchMask = matchMask; item.exactMatch = penalty ? 0 : 1; From d8f0ab2a16886113839ab8346f8b7b8a3b172e28 Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 12 Dec 2014 16:56:02 +0400 Subject: [PATCH 093/315] fix regression in setDefaultValues --- lib/ace/config_test.js | 11 +++++++++-- lib/ace/lib/app_config.js | 7 +++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/ace/config_test.js b/lib/ace/config_test.js index ac664fae..2883d9e5 100644 --- a/lib/ace/config_test.js +++ b/lib/ace/config_test.js @@ -117,12 +117,19 @@ module.exports = { assert.equal(o.getOption("initialValue"), 8); o.setOption("initialValue", 7); assert.equal(o.getOption("opt2"), 7); - + + config.setDefaultValues("test_object", { + opt1: 1, + forwarded: 2 + }); + config.resetOptions(o); + assert.equal(o.getOption("opt1"), 1); + assert.equal(o.getOption("forwarded"), 2); } }; }); if (typeof module !== "undefined" && module === require.main) { - require("asyncjs").test.testcase(module.exports).exec() + require("asyncjs").test.testcase(module.exports).exec(); } diff --git a/lib/ace/lib/app_config.js b/lib/ace/lib/app_config.js index 84b9e70c..4fe78a1d 100644 --- a/lib/ace/lib/app_config.js +++ b/lib/ace/lib/app_config.js @@ -31,7 +31,6 @@ define(function(require, exports, module) { "no use strict"; -var lang = require("./lang"); var oop = require("./oop"); var EventEmitter = require("./event_emitter").EventEmitter; @@ -91,10 +90,10 @@ function reportError(msg, data) { if (typeof console == "object" && console.error) console.error(e); setTimeout(function() { throw e; }); -}; +} var AppConfig = function() { - this.$defaultOptions = {}; + this.$defaultOptions = {}; }; (function() { @@ -145,7 +144,7 @@ var AppConfig = function() { this.setDefaultValues = function(path, optionHash) { Object.keys(optionHash).forEach(function(key) { this.setDefaultValue(path, key, optionHash[key]); - }); + }, this); }; this.warn = warn; From 278f1d1674e002a737c8a74012d1d8160d41d26e Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 21 Nov 2014 00:54:29 +0400 Subject: [PATCH 094/315] add helper for creating tests --- demo/kitchen-sink/dev_util.js | 163 ++++++++++++++++++++++++++++++---- 1 file changed, 147 insertions(+), 16 deletions(-) diff --git a/demo/kitchen-sink/dev_util.js b/demo/kitchen-sink/dev_util.js index 81ab446b..4580d9be 100644 --- a/demo/kitchen-sink/dev_util.js +++ b/demo/kitchen-sink/dev_util.js @@ -29,6 +29,8 @@ * ***** END LICENSE BLOCK ***** */ define(function(require, exports, module) { +var dom = require("ace/lib/dom"); +var Range = require("ace/range").Range; // allow easy access to ace in console, but not in ace code which uses strict function isStrict() { try { return !arguments.callee.caller.caller.caller} @@ -59,21 +61,150 @@ def(window, "session", function(){ warn(); return window.env.editor.session }); def(window, "split", function(){ warn(); return window.env.split }); -/* for textinput debuggging -dom.importCssString("\ - .ace_text-input {\ - position: absolute;\ - z-index: 10!important;\ - width: 6em!important;\ - height: 1em;\ - opacity: 1!important;\ - background: rgba(0, 92, 255, 0.11);\ - border: none;\ - font: inherit;\ - padding: 0 1px;\ - margin: 0 -1px;\ - text-indent: 0em;\ -}\ -")*/ +def(window, "devUtil", function(){ warn(); return exports }); +exports.showTextArea = function(argument) { + dom.importCssString("\ + .ace_text-input {\ + position: absolute;\ + z-index: 10!important;\ + width: 6em!important;\ + height: 1em;\ + opacity: 1!important;\ + background: rgba(0, 92, 255, 0.11);\ + border: none;\ + font: inherit;\ + padding: 0 1px;\ + margin: 0 -1px;\ + text-indent: 0em;\ + }\ + "); +}; + +exports.addGlobals = function() { + window.oop = require("ace/lib/oop"); + window.dom = require("ace/lib/dom"); + window.Range = require("ace/range").Range; + window.Editor = require("ace/editor").Editor; + window.assert = require("ace/test/asyncjs/assert"); + window.asyncjs = require("ace/test/asyncjs/async"); + window.UndoManager = require("ace/undomanager").UndoManager; + window.EditSession = require("ace/edit_session").EditSession; + window.MockRenderer = require("ace/test/mockrenderer").MockRenderer; + window.EventEmitter = require("ace/lib/event_emitter").EventEmitter; +}; + +exports.recordTestCase = function() { + exports.addGlobals(); + var editor = window.editor; + var testcase = window.testcase = []; + var assert; + function getSelection(editor) { + var data = editor.multiSelect.toJSON(); + if (!data.length) data = [data]; + data = data.map(function(x) { + var a, c; + if (x.isBackwards) { + a = x.end; + c = x.start; + } else { + c = x.end; + a = x.start; + } + return Range.comparePoints(a, c) + ? [a.row, a.column, c.row, c.column] + : [a.row, a.column]; + }); + return data.length > 1 ? data : data[0]; + } + function setSelection(editor, data) { + if (typeof data[0] == "number") + data = [data]; + editor.selection.fromJSON(data.map(function(x) { + var start = {row: x[0], column: x[1]}; + var end = x.length == 2 ? start : {row: x[2], column: x[3]}; + var isBackwards = Range.comparePoints(start, end) > 0; + return isBackwards ? { + start: end, + end: start, + isBackwards: true + } : { + start: start, + end: end, + isBackwards: true + }; + })); + } + function testSelection(editor, data) { + assert.equal(getSelection(editor) + "", data + ""); + } + + testcase.push({ + type: "setValue", + data: editor.getValue() + }, { + type: "setSelection", + data: getSelection(editor) + }); + editor.commands.on("afterExec", function(e) { + testcase.push({ + type: "exec", + data: e + }); + testcase.push({ + type: "value", + data: editor.getValue() + }); + testcase.push({ + type: "selection", + data: getSelection(editor) + }); + }); + editor.on("mouseup", function() { + testcase.push({ + type: "setSelection", + data: getSelection(editor) + }); + }); + + testcase.toString = function() { + var lastValue = ""; + // var lastSelection = "" + var str = this.map(function(x) { + var data = x.data; + switch (x.type) { + case "exec": + return 'editor.execCommand("' + + data.command.name + + (data.args ? '", ' + JSON.stringify(data.args) : '"') + + ')'; + case "setSelection": + return 'setSelection(editor, ' + JSON.stringify(data) + ')'; + case "setValue": + if (lastValue != data) { + lastValue = data; + return 'editor.setValue(' + JSON.stringify(data) + ', -1)'; + } + return; + case "selection": + return 'testSelection(editor, ' + JSON.stringify(data) + ')'; + case "value": + if (lastValue != data) { + lastValue = data; + return 'assert.equal(' + + 'editor.getValue(),' + + JSON.stringify(data) + + ')'; + } + return; + } + }).filter(Boolean).join("\n"); + + return getSelection + "\n" + + testSelection + "\n" + + setSelection + "\n" + + "\n" + str + "\n"; + }; +}; + }); From 852e0673ca4dca473159f848d9b51d5e5bd11e56 Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 21 Nov 2014 00:58:25 +0400 Subject: [PATCH 095/315] fix pairing of quotes in cstyle behavior --- lib/ace/mode/behaviour/cstyle.js | 68 ++++++++++++++------------------ 1 file changed, 29 insertions(+), 39 deletions(-) diff --git a/lib/ace/mode/behaviour/cstyle.js b/lib/ace/mode/behaviour/cstyle.js index a8a18e72..db8f4a36 100644 --- a/lib/ace/mode/behaviour/cstyle.js +++ b/lib/ace/mode/behaviour/cstyle.js @@ -260,48 +260,38 @@ var CstyleBehaviour = function() { var cursor = editor.getCursorPosition(); var line = session.doc.getLine(cursor.row); var leftChar = line.substring(cursor.column-1, cursor.column); - + var rightChar = line.substring(cursor.column, cursor.column + 1); + + var token = session.getTokenAt(cursor.row, cursor.column); + var rightToken = session.getTokenAt(cursor.row, cursor.column + 1); // We're escaped. - if (leftChar == '\\') { + if (leftChar == "\\" && token && /escape/.test(token.type)) return null; + + var stringBefore = token && /string/.test(token.type); + var stringAfter = !rightToken || /string/.test(rightToken.type); + + var pair; + if (rightChar == quote) { + pair = stringBefore !== stringAfter; + } else { + if (stringBefore && !stringAfter) + return null; // wrap string with different quote + var wordRe = session.$mode.tokenRe; + wordRe.lastIndex = 0; + var isWordBefore = wordRe.test(leftChar); + wordRe.lastIndex = 0; + var isWordAfter = wordRe.test(leftChar); + if (isWordBefore || isWordAfter) + return null; // before or after alphanumeric + if (rightChar && !/[\s;,.})\]\\]/.test(rightChar)) + return null; // there is rightChar and it isn't closing + pair = true; } - - // Find what token we're inside. - var tokens = session.getTokens(selection.start.row); - var col = 0, token; - var quotepos = -1; // Track whether we're inside an open quote. - - for (var x = 0; x < tokens.length; x++) { - token = tokens[x]; - if (token.type == "string") { - quotepos = -1; - } else if (quotepos < 0) { - quotepos = token.value.indexOf(quote); - } - if ((token.value.length + col) > selection.start.column) { - break; - } - col += tokens[x].value.length; - } - - // Try and be smart about when we auto insert. - if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) { - if (!CstyleBehaviour.isSaneInsertion(editor, session)) - return; - return { - text: quote + quote, - selection: [1,1] - }; - } else if (token && token.type === "string") { - // Ignore input and move right one if we're typing over the closing quote. - var rightChar = line.substring(cursor.column, cursor.column + 1); - if (rightChar == quote) { - return { - text: '', - selection: [1, 1] - }; - } - } + return { + text: pair ? quote + quote : "", + selection: [1,1] + }; } } }); From 3fa54ce97e9d14ebd0b140deb702692c569d67fc Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 21 Nov 2014 01:02:31 +0400 Subject: [PATCH 096/315] fix copyLines* for multiple selections --- demo/kitchen-sink/dev_util.js | 85 ++++++++++++++++++----------------- kitchen-sink.html | 4 +- lib/ace/editor.js | 79 ++++++++++++++++---------------- lib/ace/multi_select_test.js | 70 +++++++++++++++++++++++++++++ 4 files changed, 159 insertions(+), 79 deletions(-) diff --git a/demo/kitchen-sink/dev_util.js b/demo/kitchen-sink/dev_util.js index 4580d9be..ae9200b7 100644 --- a/demo/kitchen-sink/dev_util.js +++ b/demo/kitchen-sink/dev_util.js @@ -91,53 +91,58 @@ exports.addGlobals = function() { window.EditSession = require("ace/edit_session").EditSession; window.MockRenderer = require("ace/test/mockrenderer").MockRenderer; window.EventEmitter = require("ace/lib/event_emitter").EventEmitter; + + window.getSelection = getSelection; + window.setSelection = setSelection; + window.testSelection = testSelection; }; +function getSelection(editor) { + var data = editor.multiSelect.toJSON(); + if (!data.length) data = [data]; + data = data.map(function(x) { + var a, c; + if (x.isBackwards) { + a = x.end; + c = x.start; + } else { + c = x.end; + a = x.start; + } + return Range.comparePoints(a, c) + ? [a.row, a.column, c.row, c.column] + : [a.row, a.column]; + }); + return data.length > 1 ? data : data[0]; +} +function setSelection(editor, data) { + if (typeof data[0] == "number") + data = [data]; + editor.selection.fromJSON(data.map(function(x) { + var start = {row: x[0], column: x[1]}; + var end = x.length == 2 ? start : {row: x[2], column: x[3]}; + var isBackwards = Range.comparePoints(start, end) > 0; + return isBackwards ? { + start: end, + end: start, + isBackwards: true + } : { + start: start, + end: end, + isBackwards: true + }; + })); +} +function testSelection(editor, data) { + assert.equal(getSelection(editor) + "", data + ""); +} + exports.recordTestCase = function() { exports.addGlobals(); var editor = window.editor; var testcase = window.testcase = []; var assert; - function getSelection(editor) { - var data = editor.multiSelect.toJSON(); - if (!data.length) data = [data]; - data = data.map(function(x) { - var a, c; - if (x.isBackwards) { - a = x.end; - c = x.start; - } else { - c = x.end; - a = x.start; - } - return Range.comparePoints(a, c) - ? [a.row, a.column, c.row, c.column] - : [a.row, a.column]; - }); - return data.length > 1 ? data : data[0]; - } - function setSelection(editor, data) { - if (typeof data[0] == "number") - data = [data]; - editor.selection.fromJSON(data.map(function(x) { - var start = {row: x[0], column: x[1]}; - var end = x.length == 2 ? start : {row: x[2], column: x[3]}; - var isBackwards = Range.comparePoints(start, end) > 0; - return isBackwards ? { - start: end, - end: start, - isBackwards: true - } : { - start: start, - end: end, - isBackwards: true - }; - })); - } - function testSelection(editor, data) { - assert.equal(getSelection(editor) + "", data + ""); - } - + testcase.push({ type: "setValue", data: editor.getValue() diff --git a/kitchen-sink.html b/kitchen-sink.html index 65fe2a2a..a8e1fb7b 100644 --- a/kitchen-sink.html +++ b/kitchen-sink.html @@ -257,7 +257,9 @@ - + diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 78c7c18d..f487b49e 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -1655,9 +1655,7 @@ var Editor = function(renderer, session) { * @related EditSession.moveLinesUp **/ this.moveLinesDown = function() { - this.$moveLines(function(firstRow, lastRow) { - return this.session.moveLinesDown(firstRow, lastRow); - }); + this.$moveLines(1, false); }; /** @@ -1666,9 +1664,7 @@ var Editor = function(renderer, session) { * @related EditSession.moveLinesDown **/ this.moveLinesUp = function() { - this.$moveLines(function(firstRow, lastRow) { - return this.session.moveLinesUp(firstRow, lastRow); - }); + this.$moveLines(-1, false); }; /** @@ -1692,10 +1688,7 @@ var Editor = function(renderer, session) { * **/ this.copyLinesUp = function() { - this.$moveLines(function(firstRow, lastRow) { - this.session.duplicateLines(firstRow, lastRow); - return 0; - }); + this.$moveLines(-1, true); }; /** @@ -1705,51 +1698,61 @@ var Editor = function(renderer, session) { * **/ this.copyLinesDown = function() { - this.$moveLines(function(firstRow, lastRow) { - return this.session.duplicateLines(firstRow, lastRow); - }); + this.$moveLines(1, true); }; /** - * Executes a specific function, which can be anything that manipulates selected lines, such as copying them, duplicating them, or shifting them. - * @param {Function} mover A method to call on each selected row - * + * for internal use + * @ignore * **/ - this.$moveLines = function(mover) { + this.$moveLines = function(dir, copy) { + var rows, moved; var selection = this.selection; if (!selection.inMultiSelectMode || this.inVirtualSelectionMode) { var range = selection.toOrientedRange(); - var rows = this.$getSelectedRows(range); - var linesMoved = mover.call(this, rows.first, rows.last); - range.moveBy(linesMoved, 0); + rows = this.$getSelectedRows(range); + moved = this.session.$moveLines(rows.first, rows.last, copy ? 0 : dir); + if (copy && dir == -1) moved = 0; + range.moveBy(moved, 0); selection.fromOrientedRange(range); } else { var ranges = selection.rangeList.ranges; selection.rangeList.detach(this.session); - - for (var i = ranges.length; i--; ) { + this.inVirtualSelectionMode = true; + + var diff = 0; + var totalDiff = 0; + var l = ranges.length; + for (var i = 0; i < l; i++) { var rangeIndex = i; - var rows = ranges[i].collapseRows(); - var last = rows.end.row; - var first = rows.start.row; - while (i--) { - rows = ranges[i].collapseRows(); - if (first - rows.end.row <= 1) - first = rows.end.row; - else + ranges[i].moveBy(diff, 0); + rows = this.$getSelectedRows(ranges[i]); + var first = rows.first; + var last = rows.last; + while (++i < l) { + if (totalDiff) ranges[i].moveBy(totalDiff, 0); + var subRows = this.$getSelectedRows(ranges[i]); + if (copy && subRows.first != last) break; + else if (!copy && subRows.first > last + 1) + break; + last = subRows.last; } - i++; - - var linesMoved = mover.call(this, first, last); - while (rangeIndex >= i) { - ranges[rangeIndex].moveBy(linesMoved, 0); - rangeIndex--; + i--; + diff = this.session.$moveLines(first, last, copy ? 0 : dir); + if (copy && dir == -1) rangeIndex = i + 1; + while (rangeIndex <= i) { + ranges[rangeIndex].moveBy(diff, 0); + rangeIndex++; } + if (!copy) diff = 0; + totalDiff += diff; } + selection.fromOrientedRange(selection.ranges[0]); selection.rangeList.attach(this.session); + this.inVirtualSelectionMode = false; } }; @@ -1762,8 +1765,8 @@ var Editor = function(renderer, session) { * * @returns {Object} **/ - this.$getSelectedRows = function() { - var range = this.getSelectionRange().collapseRows(); + this.$getSelectedRows = function(range) { + range = (range || this.getSelectionRange()).collapseRows(); return { first: this.session.getRowFoldStart(range.start.row), diff --git a/lib/ace/multi_select_test.js b/lib/ace/multi_select_test.js index 2e71aefa..1eccc4ce 100644 --- a/lib/ace/multi_select_test.js +++ b/lib/ace/multi_select_test.js @@ -51,6 +51,45 @@ var exec = function(name, times, args) { var testRanges = function(str) { assert.equal(editor.selection.getAllRanges() + "", str + ""); }; +function getSelection(editor) { + var data = editor.multiSelect.toJSON(); + if (!data.length) data = [data]; + data = data.map(function(x) { + var a, c; + if (x.isBackwards) { + a = x.end; + c = x.start; + } else { + c = x.end; + a = x.start; + } + return Range.comparePoints(a, c) + ? [a.row, a.column, c.row, c.column] + : [a.row, a.column]; + }); + return data.length > 1 ? data : data[0]; +} +function testSelection(editor, data) { + assert.equal(getSelection(editor) + "", data + ""); +} +function setSelection(editor, data) { + if (typeof data[0] == "number") + data = [data]; + editor.selection.fromJSON(data.map(function(x) { + var start = {row: x[0], column: x[1]}; + var end = x.length == 2 ? start : {row: x[2], column: x[3]}; + var isBackwards = Range.comparePoints(start, end) > 0; + return isBackwards ? { + start: end, + end: start, + isBackwards: true + } : { + start: start, + end: end, + isBackwards: true + }; + })); +} module.exports = { @@ -167,6 +206,37 @@ module.exports = { editor.execCommand('insertfoo'); assert.equal('l1foo\nl2foo', editor.getValue()); }, + + "test multiselect move lines": function() { + editor = new Editor(new MockRenderer()); + + editor.setValue("l1\nl2\nl3\nl4", -1); + setSelection(editor, [[0,2],[1,2],[2,2],[3,2]]); + + exec("copylinesdown"); + assert.equal(editor.getValue(),"l1\nl1\nl2\nl2\nl3\nl3\nl4\nl4"); + testSelection(editor, [[1,2],[3,2],[5,2],[7,2]]); + exec("copylinesup"); + assert.equal(editor.getValue(),"l1\nl1\nl1\nl2\nl2\nl2\nl3\nl3\nl3\nl4\nl4\nl4"); + testSelection(editor, [[1,2],[4,2],[7,2],[10,2]]); + exec("removeline"); + assert.equal(editor.getValue(),"l1\nl1\nl2\nl2\nl3\nl3\nl4\nl4"); + testSelection(editor, [[1,0],[3,0],[5,0],[7,0]]); + + setSelection(editor, [[1,2],[1,0,1,1],[3,0,3,1],[5,0,5,1],[7,0,7,1]]); + exec("copylinesdown"); + exec("copylinesup"); + assert.equal(editor.getValue(),"l1\nl1\nl1\nl1\nl2\nl2\nl2\nl2\nl3\nl3\nl3\nl3\nl4\nl4\nl4\nl4"); + testSelection(editor, [[2,2],[2,0,2,1],[6,0,6,1],[10,0,10,1],[14,0,14,1]]); + + exec("movelinesdown", 12); + assert.equal(editor.getValue(),"l1\nl1\nl1\nl2\nl2\nl2\nl3\nl3\nl3\nl4\nl4\nl4\nl1\nl2\nl3\nl4"); + testSelection(editor, [[12,2],[12,0,12,1],[13,0,13,1],[14,0,14,1],[15,0,15,1]]); + + exec("movelinesup", 12); + assert.equal(editor.getValue(),"l1\nl2\nl3\nl4\nl1\nl1\nl1\nl2\nl2\nl2\nl3\nl3\nl3\nl4\nl4\nl4"); + testSelection(editor, [[0,2],[0,0,0,1],[1,0,1,1],[2,0,2,1],[3,0,3,1]]); + }, "test multiselect fromJSON/toJSON": function() { var doc = new EditSession(["l1", "l2"]); From ec18d9493d89805f702e66854f84c687ac0d6f89 Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 21 Nov 2014 01:04:11 +0400 Subject: [PATCH 097/315] fix toggleComment command in php mode --- lib/ace/mode/php.js | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/lib/ace/mode/php.js b/lib/ace/mode/php.js index 2754ef51..c7688d43 100644 --- a/lib/ace/mode/php.js +++ b/lib/ace/mode/php.js @@ -55,6 +55,24 @@ oop.inherits(PhpMode, TextMode); (function() { + this.tokenRe = new RegExp("^[" + + unicode.packages.L + + unicode.packages.Mn + unicode.packages.Mc + + unicode.packages.Nd + + unicode.packages.Pc + "\_]+", "g" + ); + + this.nonTokenRe = new RegExp("^(?:[^" + + unicode.packages.L + + unicode.packages.Mn + unicode.packages.Mc + + unicode.packages.Nd + + unicode.packages.Pc + "\_]|\s])+", "g" + ); + + + this.lineCommentStart = ["//", "#"]; + this.blockComment = {start: "/*", end: "*/"}; + this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); @@ -100,8 +118,10 @@ oop.inherits(PhpMode, TextMode); var Mode = function(opts) { if (opts && opts.inline) { - PhpMode.call(this); - return; + var mode = new PhpMode(); + mode.createWorker = this.createWorker; + mode.inlinePhp = true; + return mode; } HtmlMode.call(this); this.HighlightRules = PhpHighlightRules; @@ -116,24 +136,6 @@ oop.inherits(Mode, HtmlMode); (function() { - this.tokenRe = new RegExp("^[" - + unicode.packages.L - + unicode.packages.Mn + unicode.packages.Mc - + unicode.packages.Nd - + unicode.packages.Pc + "\_]+", "g" - ); - - this.nonTokenRe = new RegExp("^(?:[^" - + unicode.packages.L - + unicode.packages.Mn + unicode.packages.Mc - + unicode.packages.Nd - + unicode.packages.Pc + "\_]|\s])+", "g" - ); - - - this.lineCommentStart = ["//", "#"]; - this.blockComment = {start: "/*", end: "*/"}; - this.createWorker = function(session) { var worker = new WorkerClient(["ace"], "ace/mode/php_worker", "PhpWorker"); worker.attachToDocument(session.getDocument()); From 6b13aedf5f45fad451dea7a0bb2431ea9737ce53 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 4 Dec 2014 14:47:17 +0400 Subject: [PATCH 098/315] do not pair quotes inside strings --- lib/ace/mode/behaviour/behaviour_test.js | 9 +++++++++ lib/ace/mode/behaviour/cstyle.js | 2 ++ 2 files changed, 11 insertions(+) diff --git a/lib/ace/mode/behaviour/behaviour_test.js b/lib/ace/mode/behaviour/behaviour_test.js index ded22ccb..ba0a5041 100644 --- a/lib/ace/mode/behaviour/behaviour_test.js +++ b/lib/ace/mode/behaviour/behaviour_test.js @@ -120,6 +120,15 @@ module.exports = { assert.equal(editor.getValue(), "{") exec("insertstring", 1, "\n"); assert.equal(editor.getValue(), "{\n \n}") + + editor.setValue(""); + exec("insertstring", 1, "("); + exec("insertstring", 1, '"'); + exec("insertstring", 1, '"'); + assert.equal(editor.getValue(), '("")'); + exec("backspace", 1); + exec("insertstring", 1, '"'); + assert.equal(editor.getValue(), '("")'); } }; diff --git a/lib/ace/mode/behaviour/cstyle.js b/lib/ace/mode/behaviour/cstyle.js index db8f4a36..5abf08fd 100644 --- a/lib/ace/mode/behaviour/cstyle.js +++ b/lib/ace/mode/behaviour/cstyle.js @@ -277,6 +277,8 @@ var CstyleBehaviour = function() { } else { if (stringBefore && !stringAfter) return null; // wrap string with different quote + if (stringBefore && stringAfter) + return null; // do not pair quotes inside strings var wordRe = session.$mode.tokenRe; wordRe.lastIndex = 0; var isWordBefore = wordRe.test(leftChar); From 5a03993f65a2a347c6f2d2da4fb9513999f1c8f3 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 13 Dec 2014 00:43:30 +0400 Subject: [PATCH 099/315] update vim.js --- lib/ace/keyboard/vim.js | 326 ++++++++++++++++++++--------------- lib/ace/keyboard/vim_test.js | 74 ++++++++ 2 files changed, 264 insertions(+), 136 deletions(-) diff --git a/lib/ace/keyboard/vim.js b/lib/ace/keyboard/vim.js index cbf3dda3..d3a01ebc 100644 --- a/lib/ace/keyboard/vim.js +++ b/lib/ace/keyboard/vim.js @@ -167,7 +167,7 @@ define(function(require, exports, module) { this.removeOverlay(); }; this.virtualSelectionMode = function() { - return this.ace.inVirtualSelectionMode && this.ace.selection.index + return this.ace.inVirtualSelectionMode && this.ace.selection.index; }; this.onChange = function(delta) { var oldDelta = delta.data; @@ -356,7 +356,7 @@ define(function(require, exports, module) { point.row = start.row; point.column = start.column; if (cmp2 === 0) - point.bias = 1 + point.bias = 1; } } }; @@ -421,9 +421,6 @@ define(function(require, exports, module) { throw "not implemented"; } }; - this.openDialog = function() { - debugger - }; this.getSearchCursor = function(query, pos, caseFold) { var caseSensitive = false; var isRegexp = false; @@ -566,12 +563,11 @@ define(function(require, exports, module) { var row = delta.start.row; if (row == delta.end.row) highlight.cache[row] = undefined; else highlight.cache.splice(row, highlight.cache.length); - } + }; highlight.session.on("changeEditor", highlight.destroy); highlight.session.on("change", highlight.updateOnChange); } var re = new RegExp(o.query.source, "gmi"); - console.log(re) this.$searchHighlight = o.highlight = highlight; this.$searchHighlight.setRegexp(re); this.ace.renderer.updateBackMarkers(); @@ -866,11 +862,11 @@ dom.importCssString(".normal-mode .ace_cursor{\ { keys: '', type: 'keyToKey', toKeys: 'k' }, { keys: '', type: 'keyToKey', toKeys: 'j' }, { keys: '', type: 'keyToKey', toKeys: 'l' }, - { keys: '', type: 'keyToKey', toKeys: 'h' }, + { keys: '', type: 'keyToKey', toKeys: 'h', context: 'normal'}, { keys: '', type: 'keyToKey', toKeys: 'W' }, - { keys: '', type: 'keyToKey', toKeys: 'B' }, + { keys: '', type: 'keyToKey', toKeys: 'B', context: 'normal' }, { keys: '', type: 'keyToKey', toKeys: 'w' }, - { keys: '', type: 'keyToKey', toKeys: 'b' }, + { keys: '', type: 'keyToKey', toKeys: 'b', context: 'normal' }, { keys: '', type: 'keyToKey', toKeys: 'j' }, { keys: '', type: 'keyToKey', toKeys: 'k' }, { keys: '', type: 'keyToKey', toKeys: '' }, @@ -1018,55 +1014,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ var Pos = CodeMirror.Pos; - var modifierCodes = [16, 17, 18, 91]; - var specialKey = {Enter:'CR',Backspace:'BS',Delete:'Del'}; - var mac = /Mac/.test(navigator.platform); var Vim = function() { return vimApi; } //{ - function lookupKey(e) { - var keyCode = e.keyCode; - if (modifierCodes.indexOf(keyCode) != -1) { return; } - var hasModifier = e.ctrlKey || e.metaKey; - var key = CodeMirror.keyNames[keyCode]; - key = specialKey[key] || key; - var name = ''; - if (e.ctrlKey) { name += 'C-'; } - if (e.altKey) { name += 'A-'; } - if (mac && e.metaKey || (!hasModifier && e.shiftKey) && key.length < 2) { - // Shift key bindings can only specified for special characters. - return; - } else if (e.shiftKey && !/^[A-Za-z]$/.test(key)) { - name += 'S-'; - } - if (key.length == 1) { key = key.toLowerCase(); } - name += key; - if (name.length > 1) { name = '<' + name + '>'; } - return name; - } - // Keys with modifiers are handled using keydown due to limitations of - // keypress event. - function handleKeyDown(cm, e) { - var name = lookupKey(e); - if (!name) { return; } - - CodeMirror.signal(cm, 'vim-keypress', name); - if (CodeMirror.Vim.handleKey(cm, name, 'user')) { - CodeMirror.e_stop(e); - } - } - // Keys without modifiers are handled using keypress to work best with - // non-standard keyboard layouts. - function handleKeyPress(cm, e) { - var code = e.charCode || e.keyCode; - if (e.ctrlKey || e.metaKey || e.altKey || - e.shiftKey && code < 32) { return; } - var name = String.fromCharCode(code); - - CodeMirror.signal(cm, 'vim-keypress', name); - if (CodeMirror.Vim.handleKey(cm, name, 'user')) { - CodeMirror.e_stop(e); - } - } - function enterVimMode(cm) { cm.setOption('disableInput', true); cm.setOption('showCursorWhenSelecting', false); @@ -1074,8 +1022,6 @@ dom.importCssString(".normal-mode .ace_cursor{\ cm.on('cursorActivity', onCursorActivity); maybeInitVimState(cm); CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); - cm.on('keypress', handleKeyPress); - cm.on('keydown', handleKeyDown); } function leaveVimMode(cm) { @@ -1083,8 +1029,6 @@ dom.importCssString(".normal-mode .ace_cursor{\ cm.off('cursorActivity', onCursorActivity); CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); cm.state.vim = null; - cm.off('keypress', handleKeyPress); - cm.off('keydown', handleKeyDown); } function detachVimMap(cm, next) { @@ -1109,6 +1053,60 @@ dom.importCssString(".normal-mode .ace_cursor{\ else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap"))) cm.setOption("keyMap", "default"); }); + + function cmKey(key, cm) { + if (!cm) { return undefined; } + var vimKey = cmKeyToVimKey(key); + if (!vimKey) { + return false; + } + var cmd = CodeMirror.Vim.findKey(cm, vimKey); + if (typeof cmd == 'function') { + CodeMirror.signal(cm, 'vim-keypress', vimKey); + } + return cmd; + } + + var modifiers = {'Shift': 'S', 'Ctrl': 'C', 'Alt': 'A', 'Cmd': 'D', 'Mod': 'A'}; + var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del'}; + function cmKeyToVimKey(key) { + if (key.charAt(0) == '\'') { + // Keypress character binding of format "'a'" + return key.charAt(1); + } + var pieces = key.split('-'); + if (/-$/.test(key)) { + // If the - key was typed, split will result in 2 extra empty strings + // in the array. Replace them with 1 '-'. + pieces.splice(-2, 2, '-'); + } + var lastPiece = pieces[pieces.length - 1]; + if (pieces.length == 1 && pieces[0].length == 1) { + // No-modifier bindings use literal character bindings above. Skip. + return false; + } else if (pieces.length == 2 && pieces[0] == 'Shift' && lastPiece.length == 1) { + // Ignore Shift+char bindings as they should be handled by literal character. + return false; + } + var hasCharacter = false; + for (var i = 0; i < pieces.length; i++) { + var piece = pieces[i]; + if (piece in modifiers) { pieces[i] = modifiers[piece]; } + else { hasCharacter = true; } + if (piece in specialKeys) { pieces[i] = specialKeys[piece]; } + } + if (!hasCharacter) { + // Vim does not support modifier only keys. + return false; + } + // TODO: Current bindings expect the character to be lower case, but + // it looks like vim key notation uses upper case. + if (isUpperCase(lastPiece)) { + pieces[pieces.length - 1] = lastPiece.toLowerCase(); + } + return '<' + pieces.join('-') + '>'; + } + function getOnPasteFn(cm) { var vim = cm.state.vim; if (!vim.onPasteFn) { @@ -1168,15 +1166,10 @@ dom.importCssString(".normal-mode .ace_cursor{\ function defineOption(name, defaultValue, type) { if (defaultValue === undefined) { throw Error('defaultValue is required'); } if (!type) { type = 'string'; } - var opt = name; - if (typeof name == "string") - opt = { - type: type, - defaultValue: defaultValue - }; - else - name = opt.name; - options[name] = opt; + options[name] = { + type: type, + defaultValue: defaultValue + }; setOption(name, defaultValue); } @@ -1193,8 +1186,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ value = true; } } - option.value = value; - if (option.set) option.set(value, cm); + option.value = option.type == 'boolean' ? !!value : value; } function getOption(name) { @@ -1428,9 +1420,23 @@ dom.importCssString(".normal-mode .ace_cursor{\ exCommands[name]=func; exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'}; }, - // This is the outermost function called by CodeMirror, after keys have - // been mapped to their Vim equivalents. - handleKey: function(cm, key, origin) { + handleKey: function (cm, key, origin) { + var command = this.findKey(cm, key, origin); + if (typeof command === 'function') { + return command(); + } + }, + /** + * This is the outermost function called by CodeMirror, after keys have + * been mapped to their Vim equivalents. + * + * Finds a command based on the key (and cached keys if there is a + * multi-key sequence). Returns `undefined` if no key is matched, a noop + * function if a partial match is found (multi-key), and a function to + * execute the bound command if a a key is matched. The function always + * returns true. + */ + findKey: function(cm, key, origin) { var vim = maybeInitVimState(cm); function handleMacroRecording() { var macroModeState = vimGlobalState.macroModeState; @@ -1496,13 +1502,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input'); } clearInputState(cm); - var command = match.command; - if (command.type == 'keyToKey') { - doKeyToKey(command.toKeys); - } else { - commandDispatcher.processCommand(cm, vim, command); - } - return true; + return match.command; } function handleKeyNonInsertMode() { @@ -1520,31 +1520,44 @@ dom.importCssString(".normal-mode .ace_cursor{\ else if (match.type == 'partial') { return true; } vim.inputState.keyBuffer = ''; - var command = match.command; var keysMatcher = /^(\d*)(.*)$/.exec(keys); if (keysMatcher[1] && keysMatcher[1] != '0') { vim.inputState.pushRepeatDigit(keysMatcher[1]); } - if (command.type == 'keyToKey') { - doKeyToKey(command.toKeys); - } else { - commandDispatcher.processCommand(cm, vim, command); - } - return true; + return match.command; } - return cm.operation(function() { - cm.curOp.isVimOp = true; - try { - if (vim.insertMode) { return handleKeyInsertMode(); } - else { return handleKeyNonInsertMode(); } - } catch (e) { - // clear VIM state in case it's in a bad state. - cm.state.vim = undefined; - maybeInitVimState(cm); - throw e; - } - }); + var command; + if (vim.insertMode) { command = handleKeyInsertMode(); } + else { command = handleKeyNonInsertMode(); } + if (command === false) { + return undefined; + } else if (command === true) { + // TODO: Look into using CodeMirror's multi-key handling. + // Return no-op since we are caching the key. Counts as handled, but + // don't want act on it just yet. + return function() {}; + } else { + return function() { + return cm.operation(function() { + cm.curOp.isVimOp = true; + try { + if (command.type == 'keyToKey') { + doKeyToKey(command.toKeys); + } else { + commandDispatcher.processCommand(cm, vim, command); + } + } catch (e) { + // clear VIM state in case it's in a bad state. + cm.state.vim = undefined; + maybeInitVimState(cm); + console['log'](e); + throw e; + } + return true; + }); + }; + } }, handleEx: function(cm, input) { exCommandDispatcher.processCommand(cm, input); @@ -2105,7 +2118,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ newHead = copyCursor(origHead); } if (vim.visualMode) { - newHead = clipCursorToContent(cm, newHead, true); + newHead = clipCursorToContent(cm, newHead, vim.visualBlock); if (newAnchor) { newAnchor = clipCursorToContent(cm, newAnchor, true); } @@ -2409,20 +2422,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page'); }, moveByParagraph: function(cm, head, motionArgs) { - var line = head.line; - var repeat = motionArgs.repeat; - var inc = motionArgs.forward ? 1 : -1; - for (var i = 0; i < repeat; i++) { - if ((!motionArgs.forward && line === cm.firstLine() ) || - (motionArgs.forward && line == cm.lastLine())) { - break; - } - line += inc; - while (line !== cm.firstLine() && line != cm.lastLine() && cm.getLine(line)) { - line += inc; - } - } - return Pos(line, 0); + var dir = motionArgs.forward ? 1 : -1; + return findParagraph(cm, head, motionArgs.repeat, dir); }, moveByScroll: function(cm, head, motionArgs, vim) { var scrollbox = cm.getScrollInfo(); @@ -2522,7 +2523,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ return Pos(lineNum, findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))); }, - textObjectManipulation: function(cm, head, motionArgs) { + textObjectManipulation: function(cm, head, motionArgs, vim) { // TODO: lots of possible exceptions that can be thrown here. Try da( // outside of a () block. @@ -2561,8 +2562,15 @@ dom.importCssString(".normal-mode .ace_cursor{\ tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, false /** bigWord */); } else if (character === 'p') { - tmp = expandParagraphUnderCursor(cm, inclusive, true /** forward */, - false /** bigWord */); + tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive); + motionArgs.linewise = true; + if (vim.visualMode) { + if (!vim.visualLine) { vim.visualLine = true; } + } else { + var operatorArgs = vim.inputState.operatorArgs; + if (operatorArgs) { operatorArgs.linewise = true; } + tmp.end.line--; + } } else { // No text object defined for this, don't move. return null; @@ -4070,6 +4078,54 @@ dom.importCssString(".normal-mode .ace_cursor{\ return idx; } + function findParagraph(cm, head, repeat, dir, inclusive) { + var line = head.line; + var min = cm.firstLine(); + var max = cm.lastLine(); + var start, end, i = line; + function isEmpty(i) { return !cm.getLine(i); } + function isBoundary(i, dir, any) { + if (any) { return isEmpty(i) != isEmpty(i + dir); } + return !isEmpty(i) && isEmpty(i + dir); + } + if (dir) { + while (min <= i && i <= max && repeat > 0) { + if (isBoundary(i, dir)) { repeat--; } + i += dir; + } + return new Pos(i, 0); + } + + var vim = cm.state.vim; + if (vim.visualLine && isBoundary(line, 1, true)) { + var anchor = vim.sel.anchor; + if (isBoundary(anchor.line, -1, true)) { + if (!inclusive || anchor.line != line) { + line += 1; + } + } + } + var startState = isEmpty(line); + for (i = line; i <= max && repeat; i++) { + if (isBoundary(i, 1, true)) { + if (!inclusive || isEmpty(i) != startState) { + repeat--; + } + } + } + end = new Pos(i, 0); + // select boundary before paragraph for the last one + if (i > max && !startState) { startState = true; } + else { inclusive = false; } + for (i = line; i > min; i--) { + if (!inclusive || isEmpty(i) == startState || i == line) { + if (isBoundary(i, -1, true)) { break; } + } + } + start = new Pos(i, 0); + return { start: start, end: end }; + } + // TODO: perhaps this finagling of start and end positions belonds // in codmirror/replaceRange? function selectCompanionObject(cm, head, symb, inclusive) { @@ -5276,7 +5332,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ CodeMirror.keyMap.vim = { attach: attachVimMap, - detach: detachVimMap + detach: detachVimMap, + call: cmKey }; function exitInsertMode(cm) { @@ -5349,20 +5406,16 @@ dom.importCssString(".normal-mode .ace_cursor{\ }, fallthrough: ['default'], attach: attachVimMap, - detach: detachVimMap - }; - - CodeMirror.keyMap['await-second'] = { - fallthrough: ['vim-insert'], - attach: attachVimMap, - detach: detachVimMap + detach: detachVimMap, + call: cmKey }; CodeMirror.keyMap['vim-replace'] = { 'Backspace': 'goCharLeft', fallthrough: ['vim-insert'], attach: attachVimMap, - detach: detachVimMap + detach: detachVimMap, + call: cmKey }; function executeMacroRegister(cm, vim, macroModeState, registerName) { @@ -5628,7 +5681,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ Vim = CodeMirror.Vim; - specialKey = {'return':'CR',backspace:'BS','delete':'Del',esc:'Esc', + var specialKey = {'return':'CR',backspace:'BS','delete':'Del',esc:'Esc', left:'Left',right:'Right',up:'Up',down:'Down',space: 'Space', home:'Home',end:'End',pageup:'PageUp',pagedown:'PageDown', enter: 'CR' }; @@ -5646,7 +5699,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ if (name.length > 1) { name = '<' + name + '>'; } return name; } - var handleKey = Vim.handleKey + var handleKey = Vim.handleKey.bind(Vim); Vim.handleKey = function(cm, key, origin) { return cm.operation(function() { return handleKey(cm, key, origin); @@ -5750,7 +5803,6 @@ dom.importCssString(".normal-mode .ace_cursor{\ }); return {command: "null", passEvent: true}; } - return {command: coreCommands.stop}; } else if (!vim.insertMode) { if (useragent.isMac && this.handleMacRepeat(data, hashId, key)) { hashId = -1; @@ -5925,10 +5977,10 @@ dom.importCssString(".normal-mode .ace_cursor{\ { keys: 'zf', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, { keys: 'zd', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAbove" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelow" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAboveSkipCurrent" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelowSkipCurrent" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAbove" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelow" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAboveSkipCurrent" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelowSkipCurrent" } }, { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreBefore" } }, { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreAfter" } }, { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectNextBefore" } }, @@ -5955,6 +6007,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ }, exports.handler.defaultKeymap = defaultKeymap; + exports.handler.actions = actions; + exports.Vim = Vim; Vim.map("Y", "yy"); }); diff --git a/lib/ace/keyboard/vim_test.js b/lib/ace/keyboard/vim_test.js index 8c9eeb65..7b51f23b 100644 --- a/lib/ace/keyboard/vim_test.js +++ b/lib/ace/keyboard/vim_test.js @@ -592,6 +592,80 @@ testVim('{', function(cm, vim, helpers) { helpers.doKeys('6', '{'); helpers.assertCursorAt(0, 0); }, { value: 'a\n\nb\nc\n\nd' }); +testVim('paragraph motions', function(cm, vim, helpers) { + cm.setCursor(10, 0); + helpers.doKeys('{'); + helpers.assertCursorAt(4, 0); + helpers.doKeys('{'); + helpers.assertCursorAt(0, 0); + helpers.doKeys('2', '}'); + helpers.assertCursorAt(7, 0); + helpers.doKeys('2', '}'); + helpers.assertCursorAt(16, 0); + + cm.setCursor(9, 0); + helpers.doKeys('}'); + helpers.assertCursorAt(14, 0); + + cm.setCursor(6, 0); + helpers.doKeys('}'); + helpers.assertCursorAt(7, 0); + + // ip inside empty space + cm.setCursor(10, 0); + helpers.doKeys('v', 'i', 'p'); + eqPos(Pos(7, 0), cm.getCursor('anchor')); + eqPos(Pos(12, 0), cm.getCursor('head')); + helpers.doKeys('i', 'p'); + eqPos(Pos(7, 0), cm.getCursor('anchor')); + eqPos(Pos(13, 1), cm.getCursor('head')); + helpers.doKeys('2', 'i', 'p'); + eqPos(Pos(7, 0), cm.getCursor('anchor')); + eqPos(Pos(16, 1), cm.getCursor('head')); + + // should switch to visualLine mode + cm.setCursor(14, 0); + helpers.doKeys('', 'v', 'i', 'p'); + helpers.assertCursorAt(14, 0); + + cm.setCursor(14, 0); + helpers.doKeys('', 'V', 'i', 'p'); + eqPos(Pos(16, 1), cm.getCursor('head')); + + // ap inside empty space + cm.setCursor(10, 0); + helpers.doKeys('', 'v', 'a', 'p'); + eqPos(Pos(7, 0), cm.getCursor('anchor')); + eqPos(Pos(13, 1), cm.getCursor('head')); + helpers.doKeys('a', 'p'); + eqPos(Pos(7, 0), cm.getCursor('anchor')); + eqPos(Pos(16, 1), cm.getCursor('head')); + + cm.setCursor(13, 0); + helpers.doKeys('v', 'a', 'p'); + eqPos(Pos(13, 0), cm.getCursor('anchor')); + eqPos(Pos(14, 0), cm.getCursor('head')); + + cm.setCursor(16, 0); + helpers.doKeys('v', 'a', 'p'); + eqPos(Pos(14, 0), cm.getCursor('anchor')); + eqPos(Pos(16, 1), cm.getCursor('head')); + + cm.setCursor(0, 0); + helpers.doKeys('v', 'a', 'p'); + eqPos(Pos(0, 0), cm.getCursor('anchor')); + eqPos(Pos(4, 0), cm.getCursor('head')); + + cm.setCursor(0, 0); + helpers.doKeys('d', 'i', 'p'); + var register = helpers.getRegisterController().getRegister(); + eq('a\na\n', register.toString()); + is(register.linewise); + helpers.doKeys('3', 'j', 'p'); + helpers.doKeys('y', 'i', 'p'); + is(register.linewise); + eq('b\na\na\nc\n', register.toString()); +}, { value: 'a\na\n\n\n\nb\nc\n\n\n\n\n\n\nd\n\ne\nf' }); // Operator tests testVim('dl', function(cm, vim, helpers) { From c5edaa3608d0e3a540d104be15be499a79677737 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 13 Dec 2014 16:45:56 +0400 Subject: [PATCH 100/315] allow filtering tests in browser runner --- lib/ace/test/all_browser.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/ace/test/all_browser.js b/lib/ace/test/all_browser.js index 1ffbb01a..7ac5092e 100644 --- a/lib/ace/test/all_browser.js +++ b/lib/ace/test/all_browser.js @@ -72,6 +72,8 @@ document.body.appendChild(nav); if (location.search) testNames = location.search.substr(1).split(",") +var filter = location.hash.substr(1); + require(testNames, function() { var tests = testNames.map(function(x) { var module = require(x); @@ -81,6 +83,12 @@ require(testNames, function() { async.list(tests) .expand(function(test) { + if (filter) { + Object.keys(test).forEach(function(method) { + if (method.match(/^>?test/) && !method.match(filter)) + test[method] = undefined; + }); + } return AsyncTest.testcase(test) }, AsyncTest.TestGenerator) .run() From 8019a21475618b03127459e43b4825660208c3ac Mon Sep 17 00:00:00 2001 From: Bernhard Weichel Date: Sun, 14 Dec 2014 20:34:41 +0100 Subject: [PATCH 101/315] added abc mode --- demo/kitchen-sink/docs/abc.abc | 171 +++ lib/ace/ext/modelist.js | 1 + lib/ace/mode/_test/tokens_abc.json | 2207 +++++++++++++++++++++++++++ lib/ace/mode/abc.js | 58 + lib/ace/mode/abc_highlight_rules.js | 114 ++ lib/ace/snippets/abc.js | 7 + lib/ace/snippets/abc.snippets | 15 + 7 files changed, 2573 insertions(+) create mode 100644 demo/kitchen-sink/docs/abc.abc create mode 100644 lib/ace/mode/_test/tokens_abc.json create mode 100644 lib/ace/mode/abc.js create mode 100644 lib/ace/mode/abc_highlight_rules.js create mode 100644 lib/ace/snippets/abc.js create mode 100644 lib/ace/snippets/abc.snippets diff --git a/demo/kitchen-sink/docs/abc.abc b/demo/kitchen-sink/docs/abc.abc new file mode 100644 index 00000000..d8ac326e --- /dev/null +++ b/demo/kitchen-sink/docs/abc.abc @@ -0,0 +1,171 @@ +%abc-2.1 +H:This file contains some example English tunes +% note that the comments (like this one) are to highlight usages +% and would not normally be included in such detail +O:England % the origin of all tunes is England + +X:1 % tune no 1 +T:Dusty Miller, The % title +T:Binny's Jig % an alternative title +C:Trad. % traditional +R:DH % double hornpipe +M:3/4 % meter +K:G % key +B>cd BAG|FA Ac BA|B>cd BAG|DG GB AG:| +Bdd gfg|aA Ac BA|Bdd gfa|gG GB AG:| +BG G/2G/2G BG|FA Ac BA|BG G/2G/2G BG|DG GB AG:| +W:Hey, the dusty miller, and his dusty coat; +W:He will win a shilling, or he spend a groat. +W:Dusty was the coat, dusty was the colour; +W:Dusty was the kiss, that I got frae the miller. + +X:2 +T:Old Sir Simon the King +C:Trad. +S:Offord MSS % from Offord manuscript +N:see also Playford % reference note +M:9/8 +R:SJ % slip jig +N:originally in C % transcription note +K:G +D|GFG GAG G2D|GFG GAG F2D|EFE EFE EFG|A2G F2E D2:| +D|GAG GAB d2D|GAG GAB c2D|[1 EFE EFE EFG|[A2G] F2E D2:|\ % no line-break in score +M:12/8 % change of meter +[2 E2E EFE E2E EFG|\ % no line-break in score +M:9/8 % change of meter +A2G F2E D2|] + +X:3 +T:William and Nancy +T:New Mown Hay +T:Legacy, The +C:Trad. +O:England; Gloucs; Bledington % place of origin +B:Sussex Tune Book % can be found in these books +B:Mally's Cotswold Morris vol.1 2 +D:Morris On % can be heard on this record +P:(AB)2(AC)2A % play the parts in this order +M:6/8 +K:G +[P:A] D|"G"G2G GBd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:| +[P:B] d|"G"e2d B2d|"C"gfe "G"d2d| "G"e2d B2d|"C"gfe "D7"d2c| + "G"B2B Bcd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:| +% changes of meter, using inline fields +[T:Slows][M:4/4][L:1/4][P:C]"G"d2|"C"e2 "G"d2|B2 d2|"Em"gf "A7"e2|"D7"d2 "G"d2|\ + "C"e2 "G"d2|[M:3/8][L:1/8] "G"B2 d |[M:6/8] "C"gfe "D7"d2c| + "G"B2B Bcd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:| + +X:4 +T:South Downs Jig +R:jig +S:Robert Harbron +M:6/8 +L:1/8 +K:G +|: d | dcA G3 | EFG AFE | DEF GAB | cde d2d | +dcA G3 | EFG AFE | DEF GAB | cAF G2 :| +B | Bcd e2c | d2B c2A | Bcd e2c | [M:9/8]d2B c2B A3 | +[M:6/8]DGF E3 | cBA FED | DEF GAB |1 cAF G2 :|2 cAF G3 |] + +X:5 +T:Atholl Brose +% in this example, which reproduces Highland Bagpipe gracing, +% the large number of grace notes mean that it is more convenient to be specific about +% score line-breaks (using the $ symbol), rather than using code line breaks to indicate them +I:linebreak $ +K:D +{gcd}c<{e}A {gAGAG}A2 {gef}e>A {gAGAG}Ad| +{gcd}c<{e}A {gAGAG}A>e {ag}a>f {gef}e>d| +{gcd}c<{e}A {gAGAG}A2 {gef}e>A {gAGAG}Ad| +{g}c/d/e {g}G>{d}B {gf}gG {dc}d>B:|$ +{g}ce {ag}a>e {gf}g>e| +{g}ce {ag}a2 {GdG}a>d| +{g}ce {ag}a>e {gf}g>f| +{gef}e>d {gf}g>d {gBd}B<{e}G {dc}d>B| +{g}ce {ag}a>e {gf}g>e| +{g}ce {ag}a2 {GdG}ad| +{g}c<{GdG}e {gf}ga {f}g>e {g}f>d| +{g}e/f/g {Gdc}d>c {gBd}B<{e}G {dc}d2|] + +X:6 +T:Untitled Reel +C:Trad. +K:D +eg|a2ab ageg|agbg agef|g2g2 fgag|f2d2 d2:|\ +ed|cecA B2ed|cAcA E2ed|cecA B2ed|c2A2 A2:| +K:G +AB|cdec BcdB|ABAF GFE2|cdec BcdB|c2A2 A2:| + +X:7 +T:Kitchen Girl +C:Trad. +K:D +[c4a4] [B4g4]|efed c2cd|e2f2 gaba|g2e2 e2fg| +a4 g4|efed cdef|g2d2 efed|c2A2 A4:| +K:G +ABcA BAGB|ABAG EDEG|A2AB c2d2|e3f edcB|ABcA BAGB| +ABAG EGAB|cBAc BAG2|A4 A4:| + +%abc-2.1 +%%pagewidth 21cm +%%pageheight 29.7cm +%%topspace 0.5cm +%%topmargin 1cm +%%botmargin 0cm +%%leftmargin 1cm +%%rightmargin 1cm +%%titlespace 0cm +%%titlefont Times-Bold 32 +%%subtitlefont Times-Bold 24 +%%composerfont Times 16 +%%vocalfont Times-Roman 14 +%%staffsep 60pt +%%sysstaffsep 20pt +%%musicspace 1cm +%%vocalspace 5pt +%%measurenb 0 +%%barsperstaff 5 +%%scale 0.7 +X: 1 +T: Canzonetta a tre voci +C: Claudio Monteverdi (1567-1643) +M: C +L: 1/4 +Q: "Andante mosso" 1/4 = 110 +%%score [1 2 3] +V: 1 clef=treble name="Soprano"sname="A" +V: 2 clef=treble name="Alto" sname="T" +V: 3 clef=bass middle=d name="Tenor" sname="B" +%%MIDI program 1 75 % recorder +%%MIDI program 2 75 +%%MIDI program 3 75 +K: Eb +% 1 - 4 +[V: 1] |:z4 |z4 |f2ec |_ddcc | +w: Son que-sti~i cre-spi cri-ni~e +w: Que-sti son gli~oc-chi che mi- +[V: 2] |:c2BG|AAGc|(F/G/A/B/)c=A|B2AA | +w: Son que-sti~i cre-spi cri-ni~e que - - - - sto~il vi-so e +w: Que-sti son~gli oc-chi che mi-ran - - - - do fi-so mi- +[V: 3] |:z4 |f2ec|_ddcf |(B/c/_d/e/)ff| +w: Son que-sti~i cre-spi cri-ni~e que - - - - sto~il +w: Que-sti son~gli oc-chi che mi-ran - - - - do +% 5 - 9 +[V: 1] cAB2 |cAAA |c3B|G2!fermata!Gz ::e4| +w: que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh, +w: ran-do fi-so, tut-to re-stai con-qui-so. +[V: 2] AAG2 |AFFF |A3F|=E2!fermata!Ez::c4| +w: que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh, +w: ran-do fi-so tut-to re-stai con-qui-so. +[V: 3] (ag/f/e2)|A_ddd|A3B|c2!fermata!cz ::A4| +w: vi - - - so ond' io ti-man-go~uc-ci-so. Deh, +w: fi - - - so tut-to re-stai con-qui-so. +% 10 - 15 +[V: 1] f_dec |B2c2|zAGF |\ +w: dim-me-lo ben mi-o, che que-sto\ +=EFG2 |1F2z2:|2F8|] % more notes +w: sol de-si-o_. % more lyrics +[V: 2] ABGA |G2AA|GF=EF |(GF3/2=E//D//E)|1F2z2:|2F8|] +w: dim-me-lo ben mi-o, che que-sto sol de-si - - - - o_. +[V: 3] _dBc>d|e2AF|=EFc_d|c4 |1F2z2:|2F8|] +w: dim-me-lo ben mi-o, che que-sto sol de-si-o_. \ No newline at end of file diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index 3245d8a7..cba800ac 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -43,6 +43,7 @@ Mode.prototype.supportsFile = function(filename) { // todo firstlinematch var supportedModes = { ABAP: ["abap"], + ABC: ["abc"], ActionScript:["as"], ADA: ["ada|adb"], Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"], diff --git a/lib/ace/mode/_test/tokens_abc.json b/lib/ace/mode/_test/tokens_abc.json new file mode 100644 index 00000000..c65ae2a5 --- /dev/null +++ b/lib/ace/mode/_test/tokens_abc.json @@ -0,0 +1,2207 @@ +[[ + "start", + ["comment.line.percentage","%abc-2.1"] +],[ + "start", + ["information.keyword","H:"], + ["information.argument.string.unquoted","This file contains some example English tunes"] +],[ + "start", + ["comment.line.percentage","% note that the comments (like this one) are to highlight usages"] +],[ + "start", + ["comment.line.percentage","% and would not normally be included in such detail"] +],[ + "start", + ["information.keyword","O:"], + ["information.argument.string.unquoted","England "], + ["comment.line.percentage","% the origin of all tunes is England"] +],[ + "start" +],[ + "start", + ["information.keyword","X:"], + ["information.argument.string.unquoted","1 "], + ["comment.line.percentage","% tune no 1"] +],[ + "start", + ["information.keyword","T:"], + ["information.argument.string.unquoted","Dusty Miller, The "], + ["comment.line.percentage","% title"] +],[ + "start", + ["information.keyword","T:"], + ["information.argument.string.unquoted","Binny's Jig "], + ["comment.line.percentage","% an alternative title"] +],[ + "start", + ["information.keyword","C:"], + ["information.argument.string.unquoted","Trad. "], + ["comment.line.percentage","% traditional"] +],[ + "start", + ["information.keyword","R:"], + ["information.argument.string.unquoted","DH "], + ["comment.line.percentage","% double hornpipe"] +],[ + "start", + ["information.keyword","M:"], + ["information.argument.string.unquoted","3/4 "], + ["comment.line.percentage","% meter"] +],[ + "start", + ["information.keyword","K:"], + ["information.argument.string.unquoted","G "], + ["comment.line.percentage","% key"] +],[ + "start", + ["pitch.constant.numeric","B"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","c"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","D"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator",":|"] +],[ + "start", + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["pitch.constant.numeric","g"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","c"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["pitch.constant.numeric","a"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator",":|"] +],[ + "start", + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","/2"], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","/2"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","c"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","/2"], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","/2"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","D"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator",":|"] +],[ + "start", + ["information.keyword","W:"], + ["information.argument.string.unquoted","Hey, the dusty miller, and his dusty coat;"] +],[ + "start", + ["information.keyword","W:"], + ["information.argument.string.unquoted","He will win a shilling, or he spend a groat."] +],[ + "start", + ["information.keyword","W:"], + ["information.argument.string.unquoted","Dusty was the coat, dusty was the colour;"] +],[ + "start", + ["information.keyword","W:"], + ["information.argument.string.unquoted","Dusty was the kiss, that I got frae the miller."] +],[ + "start" +],[ + "start", + ["information.keyword","X:"], + ["information.argument.string.unquoted","2"] +],[ + "start", + ["information.keyword","T:"], + ["information.argument.string.unquoted","Old Sir Simon the King"] +],[ + "start", + ["information.keyword","C:"], + ["information.argument.string.unquoted","Trad."] +],[ + "start", + ["information.keyword","S:"], + ["information.argument.string.unquoted","Offord MSS "], + ["comment.line.percentage","% from Offord manuscript"] +],[ + "start", + ["information.keyword","N:"], + ["information.argument.string.unquoted","see also Playford "], + ["comment.line.percentage","% reference note"] +],[ + "start", + ["information.keyword","M:"], + ["information.argument.string.unquoted","9/8"] +],[ + "start", + ["information.keyword","R:"], + ["information.argument.string.unquoted","SJ "], + ["comment.line.percentage","% slip jig"] +],[ + "start", + ["information.keyword","N:"], + ["information.argument.string.unquoted","originally in C "], + ["comment.line.percentage","% transcription note"] +],[ + "start", + ["information.keyword","K:"], + ["information.argument.string.unquoted","G"] +],[ + "start", + ["pitch.constant.numeric","D"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","D"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","F"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","D"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","E"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","E"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","F"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","E"], + ["text"," "], + ["pitch.constant.numeric","D"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator",":|"] +],[ + "start", + ["pitch.constant.numeric","D"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","D"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","D"], + ["barline.keyword.operator","|[1"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","E"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","E"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["text","["], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","G"], + ["text","] "], + ["pitch.constant.numeric","F"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","E"], + ["text"," "], + ["pitch.constant.numeric","D"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator",":|"], + ["text","\\ "], + ["comment.line.percentage","% no line-break in score"] +],[ + "start", + ["information.keyword","M:"], + ["information.argument.string.unquoted","12/8 "], + ["comment.line.percentage","% change of meter"] +],[ + "start", + ["barline.keyword.operator","[2"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","E"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","E"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","E"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["text","\\ "], + ["comment.line.percentage","% no line-break in score"] +],[ + "start", + ["information.keyword","M:"], + ["information.argument.string.unquoted","9/8 "], + ["comment.line.percentage","% change of meter"] +],[ + "start", + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","F"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","E"], + ["text"," "], + ["pitch.constant.numeric","D"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator","|]"] +],[ + "start" +],[ + "start", + ["information.keyword","X:"], + ["information.argument.string.unquoted","3"] +],[ + "start", + ["information.keyword","T:"], + ["information.argument.string.unquoted","William and Nancy"] +],[ + "start", + ["information.keyword","T:"], + ["information.argument.string.unquoted","New Mown Hay"] +],[ + "start", + ["information.keyword","T:"], + ["information.argument.string.unquoted","Legacy, The"] +],[ + "start", + ["information.keyword","C:"], + ["information.argument.string.unquoted","Trad."] +],[ + "start", + ["information.keyword","O:"], + ["information.argument.string.unquoted","England; Gloucs; Bledington "], + ["comment.line.percentage","% place of origin"] +],[ + "start", + ["information.keyword","B:"], + ["information.argument.string.unquoted","Sussex Tune Book "], + ["comment.line.percentage","% can be found in these books"] +],[ + "start", + ["information.keyword","B:"], + ["information.argument.string.unquoted","Mally's Cotswold Morris vol.1 2"] +],[ + "start", + ["information.keyword","D:"], + ["information.argument.string.unquoted","Morris On "], + ["comment.line.percentage","% can be heard on this record"] +],[ + "start", + ["information.keyword","P:"], + ["information.argument.string.unquoted","(AB)2(AC)2A "], + ["comment.line.percentage","% play the parts in this order"] +],[ + "start", + ["information.keyword","M:"], + ["information.argument.string.unquoted","6/8"] +],[ + "start", + ["information.keyword","K:"], + ["information.argument.string.unquoted","G "] +],[ + "start", + ["information.keyword.embedded","[P:"], + ["information.argument.string.unquoted","A]"], + ["text"," "], + ["pitch.constant.numeric","D"], + ["barline.keyword.operator","|"], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["string.quoted","\"C\""], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","e"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["string.quoted","\"D7\""], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["string.quoted","\"C\""], + ["pitch.constant.numeric","E"], + ["duration.constant.numeric","2"], + ["string.quoted","\"D7\""], + ["pitch.constant.numeric","F"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator",":|"] +],[ + "start", + ["information.keyword.embedded","[P:"], + ["information.argument.string.unquoted","B]"], + ["text"," "], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["string.quoted","\"C\""], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["pitch.constant.numeric","e"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["string.quoted","\"C\""], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["pitch.constant.numeric","e"], + ["text"," "], + ["string.quoted","\"D7\""], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","c"], + ["barline.keyword.operator","|"] +],[ + "start", + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["string.quoted","\"C\""], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","e"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["string.quoted","\"D7\""], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["string.quoted","\"C\""], + ["pitch.constant.numeric","E"], + ["duration.constant.numeric","2"], + ["string.quoted","\"D7\""], + ["pitch.constant.numeric","F"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator",":|"] +],[ + "start", + ["comment.line.percentage","% changes of meter, using inline fields"] +],[ + "start", + ["information.keyword.embedded","[T:"], + ["information.argument.string.unquoted","Slows]"], + ["information.keyword.embedded","[M:"], + ["information.argument.string.unquoted","4/4]"], + ["information.keyword.embedded","[L:"], + ["information.argument.string.unquoted","1/4]"], + ["information.keyword.embedded","[P:"], + ["information.argument.string.unquoted","C]"], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator","|"], + ["string.quoted","\"C\""], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","2"], + ["text"," "], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator","|"], + ["string.quoted","\"Em\""], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["text"," "], + ["string.quoted","\"A7\""], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator","|"], + ["string.quoted","\"D7\""], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator","|"], + ["text","\\"] +],[ + "start", + ["text"," "], + ["string.quoted","\"C\""], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator","|"], + ["information.keyword.embedded","[M:"], + ["information.argument.string.unquoted","3/8]"], + ["information.keyword.embedded","[L:"], + ["information.argument.string.unquoted","1/8]"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","2"], + ["text"," "], + ["pitch.constant.numeric","d"], + ["text"," "], + ["barline.keyword.operator","|"], + ["information.keyword.embedded","[M:"], + ["information.argument.string.unquoted","6/8]"], + ["text"," "], + ["string.quoted","\"C\""], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["pitch.constant.numeric","e"], + ["text"," "], + ["string.quoted","\"D7\""], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","c"], + ["barline.keyword.operator","|"] +],[ + "start", + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["string.quoted","\"C\""], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","e"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["string.quoted","\"D7\""], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["string.quoted","\"C\""], + ["pitch.constant.numeric","E"], + ["duration.constant.numeric","2"], + ["string.quoted","\"D7\""], + ["pitch.constant.numeric","F"], + ["text"," "], + ["string.quoted","\"G\""], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator",":|"] +],[ + "start" +],[ + "start", + ["information.keyword","X:"], + ["information.argument.string.unquoted","4"] +],[ + "start", + ["information.keyword","T:"], + ["information.argument.string.unquoted","South Downs Jig"] +],[ + "start", + ["information.keyword","R:"], + ["information.argument.string.unquoted","jig"] +],[ + "start", + ["information.keyword","S:"], + ["information.argument.string.unquoted","Robert Harbron"] +],[ + "start", + ["information.keyword","M:"], + ["information.argument.string.unquoted","6/8"] +],[ + "start", + ["information.keyword","L:"], + ["information.argument.string.unquoted","1/8"] +],[ + "start", + ["information.keyword","K:"], + ["information.argument.string.unquoted","G"] +],[ + "start", + ["barline.keyword.operator","|:"], + ["text"," "], + ["pitch.constant.numeric","d"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text"," "], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","3"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","E"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text"," "], + ["pitch.constant.numeric","D"], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text"," "], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","e"], + ["text"," "], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["barline.keyword.operator","|"] +],[ + "start", + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","3"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","E"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text"," "], + ["pitch.constant.numeric","D"], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text"," "], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","F"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","2"], + ["text"," "], + ["barline.keyword.operator",":|"] +],[ + "start", + ["pitch.constant.numeric","B"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","c"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text"," "], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","c"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text"," "], + ["information.keyword.embedded","[M:"], + ["information.argument.string.unquoted","9/8]"], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","3"], + ["text"," "], + ["barline.keyword.operator","|"] +],[ + "start", + ["information.keyword.embedded","[M:"], + ["information.argument.string.unquoted","6/8]"], + ["pitch.constant.numeric","D"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","F"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["duration.constant.numeric","3"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text"," "], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","D"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text"," "], + ["pitch.constant.numeric","D"], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["barline.keyword.operator","|1"], + ["text"," "], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","F"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","2"], + ["text"," "], + ["barline.keyword.operator",":|2"], + ["text"," "], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","F"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","3"], + ["text"," "], + ["barline.keyword.operator","|]"] +],[ + "start" +],[ + "start", + ["information.keyword","X:"], + ["information.argument.string.unquoted","5"] +],[ + "start", + ["information.keyword","T:"], + ["information.argument.string.unquoted","Atholl Brose"] +],[ + "start", + ["comment.line.percentage","% in this example, which reproduces Highland Bagpipe gracing,"] +],[ + "start", + ["comment.line.percentage","% the large number of grace notes mean that it is more convenient to be specific about"] +],[ + "start", + ["comment.line.percentage","% score line-breaks (using the $ symbol), rather than using code line breaks to indicate them"] +],[ + "start", + ["information.keyword","I:"], + ["information.argument.string.unquoted","linebreak $"] +],[ + "start", + ["information.keyword","K:"], + ["information.argument.string.unquoted","D"] +],[ + "start", + ["text","{"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["text","}"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","<"], + ["text","{"], + ["pitch.constant.numeric","e"], + ["text","}"], + ["pitch.constant.numeric","A"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["text","}"], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","A"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["text","}"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"] +],[ + "start", + ["text","{"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["text","}"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","<"], + ["text","{"], + ["pitch.constant.numeric","e"], + ["text","}"], + ["pitch.constant.numeric","A"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["text","}"], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","a"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","f"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"] +],[ + "start", + ["text","{"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["text","}"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","<"], + ["text","{"], + ["pitch.constant.numeric","e"], + ["text","}"], + ["pitch.constant.numeric","A"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["text","}"], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","A"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["text","}"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"] +],[ + "start", + ["text","{"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","/"], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","/"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric",">"], + ["text","{"], + ["pitch.constant.numeric","d"], + ["text","}"], + ["pitch.constant.numeric","B"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","G"], + ["text"," {"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","c"], + ["text","}"], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","B"], + ["barline.keyword.operator",":|"], + ["text","$"] +],[ + "start", + ["text","{"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","<"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","a"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","e"], + ["barline.keyword.operator","|"] +],[ + "start", + ["text","{"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","<"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","a"], + ["duration.constant.numeric","2"], + ["text"," {"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","G"], + ["text","}"], + ["pitch.constant.numeric","a"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"] +],[ + "start", + ["text","{"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","<"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","a"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","f"], + ["barline.keyword.operator","|"] +],[ + "start", + ["text","{"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","d"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","d"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","d"], + ["text","}"], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","<"], + ["text","{"], + ["pitch.constant.numeric","e"], + ["text","}"], + ["pitch.constant.numeric","G"], + ["text"," {"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","c"], + ["text","}"], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","B"], + ["barline.keyword.operator","|"] +],[ + "start", + ["text","{"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","<"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","a"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","e"], + ["barline.keyword.operator","|"] +],[ + "start", + ["text","{"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","<"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","a"], + ["duration.constant.numeric","2"], + ["text"," {"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","G"], + ["text","}"], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"] +],[ + "start", + ["text","{"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","<"], + ["text","{"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","G"], + ["text","}"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","a"], + ["text"," {"], + ["pitch.constant.numeric","f"], + ["text","}"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","e"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","f"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"] +],[ + "start", + ["text","{"], + ["pitch.constant.numeric","g"], + ["text","}"], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","/"], + ["pitch.constant.numeric","f"], + ["duration.constant.numeric","/"], + ["pitch.constant.numeric","g"], + ["text"," {"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","c"], + ["text","}"], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","c"], + ["text"," {"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","d"], + ["text","}"], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","<"], + ["text","{"], + ["pitch.constant.numeric","e"], + ["text","}"], + ["pitch.constant.numeric","G"], + ["text"," {"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","c"], + ["text","}"], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator","|]"] +],[ + "start" +],[ + "start", + ["information.keyword","X:"], + ["information.argument.string.unquoted","6"] +],[ + "start", + ["information.keyword","T:"], + ["information.argument.string.unquoted","Untitled Reel"] +],[ + "start", + ["information.keyword","C:"], + ["information.argument.string.unquoted","Trad."] +],[ + "start", + ["information.keyword","K:"], + ["information.argument.string.unquoted","D"] +],[ + "start", + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","g"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","a"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","b"], + ["text"," "], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","g"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","b"], + ["pitch.constant.numeric","g"], + ["text"," "], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","f"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric","2"], + ["text"," "], + ["pitch.constant.numeric","f"], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","g"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","f"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["text"," "], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator",":|"], + ["text","\\"] +],[ + "start", + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator",":|"] +],[ + "start", + ["information.keyword","K:"], + ["information.argument.string.unquoted","G"] +],[ + "start", + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","c"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","B"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","F"], + ["text"," "], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","E"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","c"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","B"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator",":|"] +],[ + "start" +],[ + "start", + ["information.keyword","X:"], + ["information.argument.string.unquoted","7"] +],[ + "start", + ["information.keyword","T:"], + ["information.argument.string.unquoted","Kitchen Girl"] +],[ + "start", + ["information.keyword","C:"], + ["information.argument.string.unquoted","Trad."] +],[ + "start", + ["information.keyword","K:"], + ["information.argument.string.unquoted","D"] +],[ + "start", + ["text","["], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","4"], + ["pitch.constant.numeric","a"], + ["duration.constant.numeric","4"], + ["text","] ["], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","4"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric","4"], + ["text","]"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","f"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","f"], + ["duration.constant.numeric","2"], + ["text"," "], + ["pitch.constant.numeric","g"], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","b"], + ["pitch.constant.numeric","a"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["text"," "], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","f"], + ["pitch.constant.numeric","g"], + ["barline.keyword.operator","|"] +],[ + "start", + ["pitch.constant.numeric","a"], + ["duration.constant.numeric","4"], + ["text"," "], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric","4"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","f"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","d"], + ["text"," "], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","f"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["text"," "], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","f"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","4"], + ["barline.keyword.operator",":|"] +],[ + "start", + ["information.keyword","K:"], + ["information.argument.string.unquoted","G"] +],[ + "start", + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","B"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","D"], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["text"," "], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","3"], + ["pitch.constant.numeric","f"], + ["text"," "], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","B"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","B"], + ["barline.keyword.operator","|"] +],[ + "start", + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["text"," "], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","c"], + ["text"," "], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","4"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","4"], + ["barline.keyword.operator",":|"] +],[ + "start" +],[ + "start", + ["comment.line.percentage","%abc-2.1"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","pagewidth 21cm"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","pageheight 29.7cm"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","topspace 0.5cm"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","topmargin 1cm"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","botmargin 0cm"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","leftmargin 1cm"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","rightmargin 1cm"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","titlespace 0cm"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","titlefont Times-Bold 32"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","subtitlefont Times-Bold 24"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","composerfont Times 16"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","vocalfont Times-Roman 14"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","staffsep 60pt"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","sysstaffsep 20pt"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","musicspace 1cm"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","vocalspace 5pt"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","measurenb 0"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","barsperstaff 5"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","scale 0.7"] +],[ + "start", + ["information.keyword","X:"], + ["information.argument.string.unquoted"," 1"] +],[ + "start", + ["information.keyword","T:"], + ["information.argument.string.unquoted"," Canzonetta a tre voci"] +],[ + "start", + ["information.keyword","C:"], + ["information.argument.string.unquoted"," Claudio Monteverdi (1567-1643)"] +],[ + "start", + ["information.keyword","M:"], + ["information.argument.string.unquoted"," C"] +],[ + "start", + ["information.keyword","L:"], + ["information.argument.string.unquoted"," 1/4"] +],[ + "start", + ["information.keyword","Q:"], + ["information.argument.string.unquoted"," \"Andante mosso\" 1/4 = 110"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","score [1 2 3]"] +],[ + "start", + ["information.keyword","V:"], + ["information.argument.string.unquoted"," 1 clef=treble name=\"Soprano\"sname=\"A\""] +],[ + "start", + ["information.keyword","V:"], + ["information.argument.string.unquoted"," 2 clef=treble name=\"Alto\" sname=\"T\""] +],[ + "start", + ["information.keyword","V:"], + ["information.argument.string.unquoted"," 3 clef=bass middle=d name=\"Tenor\" sname=\"B\""] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","MIDI program 1 75 % recorder"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","MIDI program 2 75"] +],[ + "start", + ["information.comment.line.percentage","%%"], + ["information.keyword.embedded","MIDI program 3 75"] +],[ + "start", + ["information.keyword","K:"], + ["information.argument.string.unquoted"," Eb"] +],[ + "start", + ["comment.line.percentage","% 1 - 4"] +],[ + "start", + ["information.keyword.embedded","[V:"], + ["information.argument.string.unquoted"," 1]"], + ["text"," "], + ["barline.keyword.operator","|:"], + ["pitch.constant.numeric","z"], + ["duration.constant.numeric","4"], + ["text"," "], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","z"], + ["duration.constant.numeric","4"], + ["text"," "], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","f"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","c"], + ["text"," "], + ["barline.keyword.operator","|"], + ["accent.constant.language","_"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","c"], + ["text"," "], + ["barline.keyword.operator","|"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," Son que-sti~i cre-spi cri-ni~e"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," Que-sti son gli~oc-chi che mi-"] +],[ + "start", + ["information.keyword.embedded","[V:"], + ["information.argument.string.unquoted"," 2]"], + ["text"," "], + ["barline.keyword.operator","|:"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","G"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","c"], + ["barline.keyword.operator","|"], + ["text","("], + ["pitch.constant.numeric","F"], + ["duration.constant.numeric","/"], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","/"], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","/"], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","/"], + ["text",")"], + ["pitch.constant.numeric","c"], + ["accent.constant.language","="], + ["pitch.constant.numeric","A"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["barline.keyword.operator","|"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," Son que-sti~i cre-spi cri-ni~e que - - - - sto~il vi-so e"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," Que-sti son~gli oc-chi che mi-ran - - - - do fi-so mi-"] +],[ + "start", + ["information.keyword.embedded","[V:"], + ["information.argument.string.unquoted"," 3]"], + ["text"," "], + ["barline.keyword.operator","|:"], + ["pitch.constant.numeric","z"], + ["duration.constant.numeric","4"], + ["text"," "], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","f"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","c"], + ["barline.keyword.operator","|"], + ["accent.constant.language","_"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","f"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text","("], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","/"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","/"], + ["accent.constant.language","_"], + ["pitch.constant.numeric","d"], + ["duration.constant.numeric","/"], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","/"], + ["text",")"], + ["pitch.constant.numeric","f"], + ["pitch.constant.numeric","f"], + ["barline.keyword.operator","|"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," Son que-sti~i cre-spi cri-ni~e que - - - - sto~il"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," Que-sti son~gli oc-chi che mi-ran - - - - do"] +],[ + "start", + ["comment.line.percentage","% 5 - 9"] +],[ + "start", + ["information.keyword.embedded","[V:"], + ["information.argument.string.unquoted"," 1]"], + ["text"," "], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","2"], + ["text"," "], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","3"], + ["pitch.constant.numeric","B"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","2"], + ["string.quoted","!fermata!"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","z"], + ["text"," "], + ["barline.keyword.operator","::"], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","4"], + ["barline.keyword.operator","|"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh,"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," ran-do fi-so, tut-to re-stai con-qui-so."] +],[ + "start", + ["information.keyword.embedded","[V:"], + ["information.argument.string.unquoted"," 2]"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","2"], + ["text"," "], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","F"], + ["text"," "], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","3"], + ["pitch.constant.numeric","F"], + ["barline.keyword.operator","|"], + ["accent.constant.language","="], + ["pitch.constant.numeric","E"], + ["duration.constant.numeric","2"], + ["string.quoted","!fermata!"], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","z"], + ["barline.keyword.operator","::"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","4"], + ["barline.keyword.operator","|"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh,"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," ran-do fi-so tut-to re-stai con-qui-so."] +],[ + "start", + ["information.keyword.embedded","[V:"], + ["information.argument.string.unquoted"," 3]"], + ["text"," ("], + ["pitch.constant.numeric","a"], + ["pitch.constant.numeric","g"], + ["duration.constant.numeric","/"], + ["pitch.constant.numeric","f"], + ["duration.constant.numeric","/"], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["text",")"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","A"], + ["accent.constant.language","_"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","3"], + ["pitch.constant.numeric","B"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","2"], + ["string.quoted","!fermata!"], + ["pitch.constant.numeric","c"], + ["pitch.constant.numeric","z"], + ["text"," "], + ["barline.keyword.operator","::"], + ["pitch.constant.numeric","A"], + ["duration.constant.numeric","4"], + ["barline.keyword.operator","|"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," vi - - - so ond' io ti-man-go~uc-ci-so. Deh,"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," fi - - - so tut-to re-stai con-qui-so."] +],[ + "start", + ["comment.line.percentage","% 10 - 15"] +],[ + "start", + ["information.keyword.embedded","[V:"], + ["information.argument.string.unquoted"," 1]"], + ["text"," "], + ["pitch.constant.numeric","f"], + ["accent.constant.language","_"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","e"], + ["pitch.constant.numeric","c"], + ["text"," "], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","B"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","z"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","F"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text","\\"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," dim-me-lo ben mi-o, che que-sto"], + ["text","\\"] +],[ + "start", + ["accent.constant.language","="], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","2"], + ["text"," "], + ["barline.keyword.operator","|1"], + ["pitch.constant.numeric","F"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","z"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator",":|2"], + ["pitch.constant.numeric","F"], + ["duration.constant.numeric","8"], + ["barline.keyword.operator","|]"], + ["text"," "], + ["comment.line.percentage","% more notes"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," sol de-si-o_. "], + ["comment.line.percentage","% more lyrics"] +],[ + "start", + ["information.keyword.embedded","[V:"], + ["information.argument.string.unquoted"," 2]"], + ["text"," "], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","A"], + ["text"," "], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","G"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","A"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","F"], + ["accent.constant.language","="], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["text"," "], + ["barline.keyword.operator","|"], + ["text","("], + ["pitch.constant.numeric","G"], + ["pitch.constant.numeric","F"], + ["duration.constant.numeric","3/2"], + ["accent.constant.language","="], + ["pitch.constant.numeric","E"], + ["duration.constant.numeric","//"], + ["pitch.constant.numeric","D"], + ["duration.constant.numeric","//"], + ["pitch.constant.numeric","E"], + ["text",")"], + ["barline.keyword.operator","|1"], + ["pitch.constant.numeric","F"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","z"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator",":|2"], + ["pitch.constant.numeric","F"], + ["duration.constant.numeric","8"], + ["barline.keyword.operator","|]"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," dim-me-lo ben mi-o, che que-sto sol de-si - - - - o_."] +],[ + "start", + ["information.keyword.embedded","[V:"], + ["information.argument.string.unquoted"," 3]"], + ["text"," "], + ["accent.constant.language","_"], + ["pitch.constant.numeric","d"], + ["pitch.constant.numeric","B"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric",">"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","e"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","A"], + ["pitch.constant.numeric","F"], + ["barline.keyword.operator","|"], + ["accent.constant.language","="], + ["pitch.constant.numeric","E"], + ["pitch.constant.numeric","F"], + ["pitch.constant.numeric","c"], + ["accent.constant.language","_"], + ["pitch.constant.numeric","d"], + ["barline.keyword.operator","|"], + ["pitch.constant.numeric","c"], + ["duration.constant.numeric","4"], + ["text"," "], + ["barline.keyword.operator","|1"], + ["pitch.constant.numeric","F"], + ["duration.constant.numeric","2"], + ["pitch.constant.numeric","z"], + ["duration.constant.numeric","2"], + ["barline.keyword.operator",":|2"], + ["pitch.constant.numeric","F"], + ["duration.constant.numeric","8"], + ["barline.keyword.operator","|]"] +],[ + "start", + ["information.keyword","w:"], + ["information.argument.string.unquoted"," dim-me-lo ben mi-o, che que-sto sol de-si-o_."] +]] \ No newline at end of file diff --git a/lib/ace/mode/abc.js b/lib/ace/mode/abc.js new file mode 100644 index 00000000..b6eb237a --- /dev/null +++ b/lib/ace/mode/abc.js @@ -0,0 +1,58 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2012, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +/* + THIS FILE WAS AUTOGENERATED BY mode.tmpl.js + */ + +define(function (require, exports, module) { + "use strict"; + + var oop = require("../lib/oop"); + var TextMode = require("./text").Mode; + var ABCHighlightRules = require("./abc_highlight_rules").ABCHighlightRules; +// TODO: pick appropriate fold mode + var FoldMode = require("./folding/cstyle").FoldMode; + + var Mode = function () { + this.HighlightRules = ABCHighlightRules; + this.foldingRules = new FoldMode(); + }; + oop.inherits(Mode, TextMode); + + (function () { + // this.lineCommentStart = ""%.*""; + // this.blockComment = {start: ""/*"", end: ""*/""}; + // Extra logic goes here. + this.$id = "ace/mode/abc" + }).call(Mode.prototype); + + exports.Mode = Mode; +}); \ No newline at end of file diff --git a/lib/ace/mode/abc_highlight_rules.js b/lib/ace/mode/abc_highlight_rules.js new file mode 100644 index 00000000..6ffe9c9b --- /dev/null +++ b/lib/ace/mode/abc_highlight_rules.js @@ -0,0 +1,114 @@ +/* This file was partially autogenerated from https://github.com/jimhawkridge/SublimeABC + + Modifications + + - more classes to express the abc semantic + - added syntax highlighting for Zupfnoter conventions (https://github.com/bwl21/zupfnoter) + - separate note pitch and note duration - even if it looks the same + + ***********************************************************************************************/ + + +define(function (require, exports, module) { + "use strict"; + + var oop = require("../lib/oop"); + var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + + var ABCHighlightRules = function () { + // regexp must not have capturing parentheses. Use (?:) instead. + // regexps are ordered -> the first match is used + + this.$rules = { + start: [ + { + token: ['zupfnoter.information.comment.line.percentage', 'information.keyword', 'in formation.keyword.embedded'], + regex: '(%%%%)(hn\\.[a-z]*)(.*)', + comment: 'Instruction Comment' + }, + { + token: ['information.comment.line.percentage', 'information.keyword.embedded'], + regex: '(%%)(.*)', + comment: 'Instruction Comment' + }, + + { + token: 'comment.line.percentage', + regex: '%.*', + comment: 'Comments' + }, + + { + token: 'barline.keyword.operator', + regex: '[\\[:]*[|:][|\\]:]*(?:\\[?[0-9]+)?|\\[[0-9]+', + comment: 'Bar lines' + }, + { + token: ['information.keyword.embedded', 'information.argument.string.unquoted'], + regex: '(\\[[A-Za-z]:)([^\\]]*\\])', + comment: 'embedded Header lines' + }, + { + token: ['information.keyword', 'information.argument.string.unquoted'], + regex: '^([A-Za-z]:)([^%\\\\]*)', + comment: 'Header lines' + }, + { + token: ['text', 'entity.name.function', 'string.unquoted', 'text'], + regex: '(\\[)([A-Z]:)(.*?)(\\])', + comment: 'Inline fields' + }, + { + token: ['accent.constant.language', 'pitch.constant.numeric', 'duration.constant.numeric'], + regex: '([\\^=_]*)([A-Ga-gz][,\']*)([0-9]*/*[><0-9]*)', + comment: 'Notes' + }, + { + token: 'zupfnoter.jumptarget.string.quoted', + regex: '[\\"!]\\^\\:.*?[\\"!]', + comment: 'Zupfnoter jumptarget' + }, { + token: 'zupfnoter.goto.string.quoted', + regex: '[\\"!]\\^\\@.*?[\\"!]', + comment: 'Zupfnoter goto' + }, + { + token: 'zupfnoter.annotation.string.quoted', + regex: '[\\"!]\\^\\!.*?[\\"!]', + comment: 'Zupfnoter annoation' + }, + { + token: 'zupfnoter.annotationref.string.quoted', + regex: '[\\"!]\\^\\#.*?[\\"!]', + comment: 'Zupfnoter annotation reference' + }, + { + token: 'chordname.string.quoted', + regex: '[\\"!]\\^.*?[\\"!]', + comment: 'abc chord' + }, + { + token: 'string.quoted', + regex: '[\\"!].*?[\\"!]', + comment: 'abc annotation' + } + + ] + }; + + // this.embedRules(JsonHighlightRules, "json-") + + this.normalizeRules(); + }; + + ABCHighlightRules.metaData = { + fileTypes: ['abc'], + name: 'ABC', + scopeName: 'text.abcnotation' + }; + + + oop.inherits(ABCHighlightRules, TextHighlightRules); + + exports.ABCHighlightRules = ABCHighlightRules; +}); diff --git a/lib/ace/snippets/abc.js b/lib/ace/snippets/abc.js new file mode 100644 index 00000000..da0448ef --- /dev/null +++ b/lib/ace/snippets/abc.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./abc.snippets"); +exports.scope = "abc"; + +}); diff --git a/lib/ace/snippets/abc.snippets b/lib/ace/snippets/abc.snippets new file mode 100644 index 00000000..11e2d735 --- /dev/null +++ b/lib/ace/snippets/abc.snippets @@ -0,0 +1,15 @@ +snippet zupfnoter.goto + "^@${1:target}@${2:some_id},${3:some_id}" + +snippet zupfnoter.annotation + "^@!{1:text}@${2:some_id},${3:some_id}" + +snippet zupfnoter.annotationref + "^#${1:target}" + +snippet zupfnoter.target + "^:${1:target}" + + +snippet zupfnoter.print + %%%%hn.print {"startpos": 20, "t":"Sopran, Alt", "v":[1,2], "s":[[1,2]], "f":[1], "sf":[2], "j":[1]} From 7da354d5f33202ab0d7dd78263e5fa220f7f03b7 Mon Sep 17 00:00:00 2001 From: Bernhard Weichel Date: Sun, 14 Dec 2014 23:40:47 +0100 Subject: [PATCH 102/315] fixed Uncaught TypeError: undefined is not a functionapp_config.js:147 (anonymous function)app_config.js:146 setDefaultValuesmode_creator.js:6 --- lib/ace/lib/app_config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ace/lib/app_config.js b/lib/ace/lib/app_config.js index 84b9e70c..bc5518d7 100644 --- a/lib/ace/lib/app_config.js +++ b/lib/ace/lib/app_config.js @@ -141,11 +141,11 @@ var AppConfig = function() { opts[name].value = value; } }; - + this.setDefaultValues = function(path, optionHash) { Object.keys(optionHash).forEach(function(key) { this.setDefaultValue(path, key, optionHash[key]); - }); + }, this); }; this.warn = warn; From 95eed254393eeda6079a0386d87e0fe2a6807024 Mon Sep 17 00:00:00 2001 From: Bernhard Weichel Date: Sun, 14 Dec 2014 23:53:52 +0100 Subject: [PATCH 103/315] small fix in the snippets --- lib/ace/lib/app_config.js | 2 +- lib/ace/snippets/abc.snippets | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ace/lib/app_config.js b/lib/ace/lib/app_config.js index bc5518d7..ead26a98 100644 --- a/lib/ace/lib/app_config.js +++ b/lib/ace/lib/app_config.js @@ -141,7 +141,7 @@ var AppConfig = function() { opts[name].value = value; } }; - + this.setDefaultValues = function(path, optionHash) { Object.keys(optionHash).forEach(function(key) { this.setDefaultValue(path, key, optionHash[key]); diff --git a/lib/ace/snippets/abc.snippets b/lib/ace/snippets/abc.snippets index 11e2d735..65b0fd65 100644 --- a/lib/ace/snippets/abc.snippets +++ b/lib/ace/snippets/abc.snippets @@ -1,8 +1,8 @@ snippet zupfnoter.goto - "^@${1:target}@${2:some_id},${3:some_id}" + "^@${1:target}@${2:distance}" snippet zupfnoter.annotation - "^@!{1:text}@${2:some_id},${3:some_id}" + "^@!{1:text}@${2:x_offset},${3:y_offset}" snippet zupfnoter.annotationref "^#${1:target}" From dafa24d5e18bbacd9decb2f5c8a7796b3b137ce1 Mon Sep 17 00:00:00 2001 From: Ryan Mehta Date: Mon, 15 Dec 2014 12:33:49 -0800 Subject: [PATCH 104/315] change variable char to character --- lib/ace/mouse/mouse_handler.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/ace/mouse/mouse_handler.js b/lib/ace/mouse/mouse_handler.js index 6b331eee..596d8503 100644 --- a/lib/ace/mouse/mouse_handler.js +++ b/lib/ace/mouse/mouse_handler.js @@ -3,7 +3,7 @@ * * Copyright (c) 2010, Ajax.org B.V. * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright @@ -14,7 +14,7 @@ * * Neither the name of Ajax.org B.V. nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -46,15 +46,15 @@ var MouseHandler = function(editor) { new DefaultHandlers(this); new DefaultGutterHandler(this); new DragdropHandler(this); - + var focusEditor = function(e) { - // because we have to call event.preventDefault() any window on ie and iframes + // because we have to call event.preventDefault() any window on ie and iframes // on other browsers do not get focus, so we have to call window.focus() here if (!document.hasFocus || !document.hasFocus()) window.focus(); editor.focus(); }; - + var mouseTarget = editor.renderer.getMouseEventTarget(); event.addListener(mouseTarget, "click", this.onMouseEvent.bind(this, "click")); event.addListener(mouseTarget, "mousemove", this.onMouseMove.bind(this, "mousemove")); @@ -85,12 +85,12 @@ var MouseHandler = function(editor) { editor.on("mousemove", function(e){ if (_self.state || _self.$dragDelay || !_self.$dragEnabled) return; - - var char = editor.renderer.screenToTextCoordinates(e.x, e.y); + + var character = editor.renderer.screenToTextCoordinates(e.x, e.y); var range = editor.session.selection.getRange(); var renderer = editor.renderer; - if (!range.isEmpty() && range.insideStart(char.row, char.column)) { + if (!range.isEmpty() && range.insideStart(character.row, character.column)) { renderer.setCursorStyle("default"); } else { renderer.setCursorStyle(""); From b5c9b7f3954e88647a25e92473ca12037c27e728 Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 19 Dec 2014 18:45:25 +0400 Subject: [PATCH 105/315] fix typo in IE mouse handler --- lib/ace/mouse/mouse_handler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/mouse/mouse_handler.js b/lib/ace/mouse/mouse_handler.js index 596d8503..26985862 100644 --- a/lib/ace/mouse/mouse_handler.js +++ b/lib/ace/mouse/mouse_handler.js @@ -64,7 +64,7 @@ var MouseHandler = function(editor) { event.addMultiMouseDownListener(editor.renderer.scrollBarH.inner, [400, 300, 250], this, "onMouseEvent"); if (useragent.isIE) { event.addListener(editor.renderer.scrollBarV.element, "mousedown", focusEditor); - event.addListener(editor.renderer.scrollBarH.element, "mousemove", focusEditor); + event.addListener(editor.renderer.scrollBarH.element, "mousedown", focusEditor); } } event.addMouseWheelListener(editor.container, this.onMouseWheel.bind(this, "mousewheel")); From ed5c38b7c87cece4de1acc17912aa3043dd0b11a Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 19 Dec 2014 18:50:15 +0400 Subject: [PATCH 106/315] update list of users --- index.html | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/index.html b/index.html index 73598f7b..a377c612 100644 --- a/index.html +++ b/index.html @@ -795,10 +795,10 @@ if (match) { Plunker
  • - - Application Craft -
  • + + Chrome Dev Editor +
  • @@ -838,7 +838,7 @@ if (match) { Inkling Habitat
  • - + Code Combat
  • "}; + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/xml_worker", "Worker"); + worker.attachToDocument(session.getDocument()); + + worker.on("error", function(e) { + session.setAnnotations(e.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + this.$id = "ace/mode/xml"; }).call(Mode.prototype); diff --git a/lib/ace/mode/xml/dom-parser.js b/lib/ace/mode/xml/dom-parser.js new file mode 100644 index 00000000..669cd985 --- /dev/null +++ b/lib/ace/mode/xml/dom-parser.js @@ -0,0 +1,262 @@ +define(function(require, exports, module) { +'use strict'; + +var XMLReader = require('./sax'), + DOMImplementation = require('./dom'); + +function DOMParser(options){ + this.options = options ||{locator:{}}; + +} +DOMParser.prototype.parseFromString = function(source,mimeType){ + var options = this.options; + var sax = new XMLReader(); + var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler + var errorHandler = options.errorHandler; + var locator = options.locator; + var defaultNSMap = options.xmlns||{}; + var entityMap = {'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"} + if(locator){ + domBuilder.setDocumentLocator(locator) + } + + sax.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator); + sax.domBuilder = options.domBuilder || domBuilder; + if(/\/x?html?$/.test(mimeType)){ + entityMap.nbsp = '\xa0'; + entityMap.copy = '\xa9'; + defaultNSMap['']= 'http://www.w3.org/1999/xhtml'; + } + if(source){ + sax.parse(source,defaultNSMap,entityMap); + }else{ + sax.errorHandler.error("invalid document source"); + } + return domBuilder.document; +} +function buildErrorHandler(errorImpl,domBuilder,locator){ + if(!errorImpl){ + if(domBuilder instanceof DOMHandler){ + return domBuilder; + } + errorImpl = domBuilder ; + } + var errorHandler = {} + var isCallback = errorImpl instanceof Function; + locator = locator||{} + function build(key){ + var fn = errorImpl[key]; + if(!fn){ + if(isCallback){ + fn = errorImpl.length == 2?function(msg){errorImpl(key,msg)}:errorImpl; + }else{ + var i=arguments.length; + while(--i){ + if(fn = errorImpl[arguments[i]]){ + break; + } + } + } + } + errorHandler[key] = fn && function(msg){ + fn(msg+_locator(locator), msg, locator); + }||function(){}; + } + build('warning','warn'); + build('error','warn','warning'); + build('fatalError','warn','warning','error'); + return errorHandler; +} +/** + * +ContentHandler+ErrorHandler + * +LexicalHandler+EntityResolver2 + * -DeclHandler-DTDHandler + * + * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler + * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2 + * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html + */ +function DOMHandler() { + this.cdata = false; +} +function position(locator,node){ + node.lineNumber = locator.lineNumber; + node.columnNumber = locator.columnNumber; +} +/** + * @see org.xml.sax.ContentHandler#startDocument + * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html + */ +DOMHandler.prototype = { + startDocument : function() { + this.document = DOMImplementation.createDocument(null, null, null); + if (this.locator) { + this.document.documentURI = this.locator.systemId; + } + }, + startElement:function(namespaceURI, localName, qName, attrs) { + var doc = this.document; + var el = doc.createElementNS(namespaceURI, qName||localName); + var len = attrs.length; + appendElement(this, el); + this.currentElement = el; + + this.locator && position(this.locator,el) + for (var i = 0 ; i < len; i++) { + var namespaceURI = attrs.getURI(i); + var value = attrs.getValue(i); + var qName = attrs.getQName(i); + var attr = doc.createAttributeNS(namespaceURI, qName); + if( attr.getOffset){ + position(attr.getOffset(1),attr) + } + attr.value = attr.nodeValue = value; +// Fork : сохраняем тип кавычки (" или ') + if (attrs[i].quotSymbol){ attr.quotSymbol = attrs[i].quotSymbol; } +// endFork + el.setAttributeNode(attr) + } + }, + endElement:function(namespaceURI, localName, qName) { + var current = this.currentElement + var tagName = current.tagName; + this.currentElement = current.parentNode; + }, + startPrefixMapping:function(prefix, uri) { + }, + endPrefixMapping:function(prefix) { + }, + processingInstruction:function(target, data) { + var ins = this.document.createProcessingInstruction(target, data); + this.locator && position(this.locator,ins) + appendElement(this, ins); + }, + ignorableWhitespace:function(ch, start, length) { + }, + characters:function(chars, start, length) { + chars = _toString.apply(this,arguments) + //console.log(chars) + if(this.currentElement && chars){ + if (this.cdata) { + var charNode = this.document.createCDATASection(chars); + this.currentElement.appendChild(charNode); + } else { + var charNode = this.document.createTextNode(chars); + this.currentElement.appendChild(charNode); + } + this.locator && position(this.locator,charNode) + } + }, + skippedEntity:function(name) { + }, + endDocument:function() { + this.document.normalize(); + }, + setDocumentLocator:function (locator) { + if(this.locator = locator){// && !('lineNumber' in locator)){ + locator.lineNumber = 0; + } + }, + //LexicalHandler + comment:function(chars, start, length) { + chars = _toString.apply(this,arguments) + var comm = this.document.createComment(chars); + this.locator && position(this.locator,comm) + appendElement(this, comm); + }, + + startCDATA:function() { + //used in characters() methods + this.cdata = true; + }, + endCDATA:function() { + this.cdata = false; + }, + + startDTD:function(name, publicId, systemId) { + var impl = this.document.implementation; + if (impl && impl.createDocumentType) { + var dt = impl.createDocumentType(name, publicId, systemId); + this.locator && position(this.locator,dt) + appendElement(this, dt); + } + }, + /** + * @see org.xml.sax.ErrorHandler + * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html + */ + warning:function(error) { + console.warn(error,_locator(this.locator)); + }, + error:function(error) { + console.error(error,_locator(this.locator)); + }, + fatalError:function(error) { + console.error(error,_locator(this.locator)); + throw error; + } +} +function _locator(l){ + if(l){ + return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']' + } +} +function _toString(chars,start,length){ + if(typeof chars == 'string'){ + return chars.substr(start,length) + }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)") + if(chars.length >= start+length || start){ + return new java.lang.String(chars,start,length)+''; + } + return chars; + } +} + +/* + * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html + * used method of org.xml.sax.ext.LexicalHandler: + * #comment(chars, start, length) + * #startCDATA() + * #endCDATA() + * #startDTD(name, publicId, systemId) + * + * + * IGNORED method of org.xml.sax.ext.LexicalHandler: + * #endDTD() + * #startEntity(name) + * #endEntity(name) + * + * + * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html + * IGNORED method of org.xml.sax.ext.DeclHandler + * #attributeDecl(eName, aName, type, mode, value) + * #elementDecl(name, model) + * #externalEntityDecl(name, publicId, systemId) + * #internalEntityDecl(name, value) + * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html + * IGNORED method of org.xml.sax.EntityResolver2 + * #resolveEntity(String name,String publicId,String baseURI,String systemId) + * #resolveEntity(publicId, systemId) + * #getExternalSubset(name, baseURI) + * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html + * IGNORED method of org.xml.sax.DTDHandler + * #notationDecl(name, publicId, systemId) {}; + * #unparsedEntityDecl(name, publicId, systemId, notationName) {}; + */ +"endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){ + DOMHandler.prototype[key] = function(){return null} +}) + +/* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */ +function appendElement (hander,node) { + if (!hander.currentElement) { + hander.document.appendChild(node); + } else { + hander.currentElement.appendChild(node); + } +}//appendChild and setAttributeNS are preformance key + +return { + DOMParser: DOMParser + }; +}); \ No newline at end of file diff --git a/lib/ace/mode/xml/dom.js b/lib/ace/mode/xml/dom.js new file mode 100644 index 00000000..8845f35c --- /dev/null +++ b/lib/ace/mode/xml/dom.js @@ -0,0 +1,1204 @@ +define(function(require, exports, module) { + +/* + * DOM Level 2 + * Object DOMException + * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html + * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html + */ + +function copy(src,dest){ + for(var p in src){ + dest[p] = src[p]; + } +} +/** +^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));? +^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));? + */ +function _extends(Class,Super){ + var pt = Class.prototype; + if(Object.create){ + var ppt = Object.create(Super.prototype) + pt.__proto__ = ppt; + } + if(!(pt instanceof Super)){ + function t(){}; + t.prototype = Super.prototype; + t = new t(); + copy(pt,t); + Class.prototype = pt = t; + } + if(pt.constructor != Class){ + if(typeof Class != 'function'){ + console.error("unknow Class:"+Class) + } + pt.constructor = Class + } +} +var htmlns = 'http://www.w3.org/1999/xhtml' ; +// Node Types +var NodeType = {} +var ELEMENT_NODE = NodeType.ELEMENT_NODE = 1; +var ATTRIBUTE_NODE = NodeType.ATTRIBUTE_NODE = 2; +var TEXT_NODE = NodeType.TEXT_NODE = 3; +var CDATA_SECTION_NODE = NodeType.CDATA_SECTION_NODE = 4; +var ENTITY_REFERENCE_NODE = NodeType.ENTITY_REFERENCE_NODE = 5; +var ENTITY_NODE = NodeType.ENTITY_NODE = 6; +var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7; +var COMMENT_NODE = NodeType.COMMENT_NODE = 8; +var DOCUMENT_NODE = NodeType.DOCUMENT_NODE = 9; +var DOCUMENT_TYPE_NODE = NodeType.DOCUMENT_TYPE_NODE = 10; +var DOCUMENT_FRAGMENT_NODE = NodeType.DOCUMENT_FRAGMENT_NODE = 11; +var NOTATION_NODE = NodeType.NOTATION_NODE = 12; + +// ExceptionCode +var ExceptionCode = {} +var ExceptionMessage = {}; +var INDEX_SIZE_ERR = ExceptionCode.INDEX_SIZE_ERR = ((ExceptionMessage[1]="Index size error"),1); +var DOMSTRING_SIZE_ERR = ExceptionCode.DOMSTRING_SIZE_ERR = ((ExceptionMessage[2]="DOMString size error"),2); +var HIERARCHY_REQUEST_ERR = ExceptionCode.HIERARCHY_REQUEST_ERR = ((ExceptionMessage[3]="Hierarchy request error"),3); +var WRONG_DOCUMENT_ERR = ExceptionCode.WRONG_DOCUMENT_ERR = ((ExceptionMessage[4]="Wrong document"),4); +var INVALID_CHARACTER_ERR = ExceptionCode.INVALID_CHARACTER_ERR = ((ExceptionMessage[5]="Invalid character"),5); +var NO_DATA_ALLOWED_ERR = ExceptionCode.NO_DATA_ALLOWED_ERR = ((ExceptionMessage[6]="No data allowed"),6); +var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7); +var NOT_FOUND_ERR = ExceptionCode.NOT_FOUND_ERR = ((ExceptionMessage[8]="Not found"),8); +var NOT_SUPPORTED_ERR = ExceptionCode.NOT_SUPPORTED_ERR = ((ExceptionMessage[9]="Not supported"),9); +var INUSE_ATTRIBUTE_ERR = ExceptionCode.INUSE_ATTRIBUTE_ERR = ((ExceptionMessage[10]="Attribute in use"),10); +//level2 +var INVALID_STATE_ERR = ExceptionCode.INVALID_STATE_ERR = ((ExceptionMessage[11]="Invalid state"),11); +var SYNTAX_ERR = ExceptionCode.SYNTAX_ERR = ((ExceptionMessage[12]="Syntax error"),12); +var INVALID_MODIFICATION_ERR = ExceptionCode.INVALID_MODIFICATION_ERR = ((ExceptionMessage[13]="Invalid modification"),13); +var NAMESPACE_ERR = ExceptionCode.NAMESPACE_ERR = ((ExceptionMessage[14]="Invalid namespace"),14); +var INVALID_ACCESS_ERR = ExceptionCode.INVALID_ACCESS_ERR = ((ExceptionMessage[15]="Invalid access"),15); + + +function DOMException(code, message) { + if(message instanceof Error){ + var error = message; + }else{ + error = this; + Error.call(this, ExceptionMessage[code]); + this.message = ExceptionMessage[code]; + if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException); + } + error.code = code; + if(message) this.message = this.message + ": " + message; + return error; +}; +DOMException.prototype = Error.prototype; +copy(ExceptionCode,DOMException) +/** + * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177 + * The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live. + * The items in the NodeList are accessible via an integral index, starting from 0. + */ +function NodeList() { +}; +NodeList.prototype = { + /** + * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive. + * @standard level1 + */ + length:0, + /** + * Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null. + * @standard level1 + * @param index unsigned long + * Index into the collection. + * @return Node + * The node at the indexth position in the NodeList, or null if that is not a valid index. + */ + item: function(index) { + return this[index] || null; + } +}; +function LiveNodeList(node,refresh){ + this._node = node; + this._refresh = refresh + _updateLiveList(this); +} +function _updateLiveList(list){ + var inc = list._node._inc || list._node.ownerDocument._inc; + if(list._inc != inc){ + var ls = list._refresh(list._node); + //console.log(ls.length) + __set__(list,'length',ls.length); + copy(ls,list); + list._inc = inc; + } +} +LiveNodeList.prototype.item = function(i){ + _updateLiveList(this); + return this[i]; +} + +_extends(LiveNodeList,NodeList); +/** + * + * Objects implementing the NamedNodeMap interface are used to represent collections of nodes that can be accessed by name. Note that NamedNodeMap does not inherit from NodeList; NamedNodeMaps are not maintained in any particular order. Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index, but this is simply to allow convenient enumeration of the contents of a NamedNodeMap, and does not imply that the DOM specifies an order to these Nodes. + * NamedNodeMap objects in the DOM are live. + * used for attributes or DocumentType entities + */ +function NamedNodeMap() { +}; + +function _findNodeIndex(list,node){ + var i = list.length; + while(i--){ + if(list[i] === node){return i} + } +} + +function _addNamedNode(el,list,newAttr,oldAttr){ + if(oldAttr){ + list[_findNodeIndex(list,oldAttr)] = newAttr; + }else{ + list[list.length++] = newAttr; + } + if(el){ + newAttr.ownerElement = el; + var doc = el.ownerDocument; + if(doc){ + oldAttr && _onRemoveAttribute(doc,el,oldAttr); + _onAddAttribute(doc,el,newAttr); + } + } +} +function _removeNamedNode(el,list,attr){ + var i = _findNodeIndex(list,attr); + if(i>=0){ + var lastIndex = list.length-1 + while(i0 || key == 'xmlns'){ +// return null; +// } + var i = this.length; + while(i--){ + var attr = this[i]; + if(attr.nodeName == key){ + return attr; + } + } + }, + setNamedItem: function(attr) { + var el = attr.ownerElement; + if(el && el!=this._ownerElement){ + throw new DOMException(INUSE_ATTRIBUTE_ERR); + } + var oldAttr = this.getNamedItem(attr.nodeName); + _addNamedNode(this._ownerElement,this,attr,oldAttr); + return oldAttr; + }, + /* returns Node */ + setNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR + var el = attr.ownerElement, oldAttr; + if(el && el!=this._ownerElement){ + throw new DOMException(INUSE_ATTRIBUTE_ERR); + } + oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName); + _addNamedNode(this._ownerElement,this,attr,oldAttr); + return oldAttr; + }, + + /* returns Node */ + removeNamedItem: function(key) { + var attr = this.getNamedItem(key); + _removeNamedNode(this._ownerElement,this,attr); + return attr; + + + },// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR + + //for level2 + removeNamedItemNS:function(namespaceURI,localName){ + var attr = this.getNamedItemNS(namespaceURI,localName); + _removeNamedNode(this._ownerElement,this,attr); + return attr; + }, + getNamedItemNS: function(namespaceURI, localName) { + var i = this.length; + while(i--){ + var node = this[i]; + if(node.localName == localName && node.namespaceURI == namespaceURI){ + return node; + } + } + return null; + } +}; +/** + * @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490 + */ +function DOMImplementation(/* Object */ features) { + this._features = {}; + if (features) { + for (var feature in features) { + this._features = features[feature]; + } + } +}; + +DOMImplementation.prototype = { + hasFeature: function(/* string */ feature, /* string */ version) { + var versions = this._features[feature.toLowerCase()]; + if (versions && (!version || version in versions)) { + return true; + } else { + return false; + } + }, + // Introduced in DOM Level 2: + createDocument:function(namespaceURI, qualifiedName, doctype){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR + var doc = new Document(); + doc.doctype = doctype; + if(doctype){ + doc.appendChild(doctype); + } + doc.implementation = this; + doc.childNodes = new NodeList(); + if(qualifiedName){ + var root = doc.createElementNS(namespaceURI,qualifiedName); + doc.appendChild(root); + } + return doc; + }, + // Introduced in DOM Level 2: + createDocumentType:function(qualifiedName, publicId, systemId){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR + var node = new DocumentType(); + node.name = qualifiedName; + node.nodeName = qualifiedName; + node.publicId = publicId; + node.systemId = systemId; + // Introduced in DOM Level 2: + //readonly attribute DOMString internalSubset; + + //TODO:.. + // readonly attribute NamedNodeMap entities; + // readonly attribute NamedNodeMap notations; + return node; + } +}; + + +/** + * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 + */ + +function Node() { +}; + +Node.prototype = { + firstChild : null, + lastChild : null, + previousSibling : null, + nextSibling : null, + attributes : null, + parentNode : null, + childNodes : null, + ownerDocument : null, + nodeValue : null, + namespaceURI : null, + prefix : null, + localName : null, + // Modified in DOM Level 2: + insertBefore:function(newChild, refChild){//raises + return _insertBefore(this,newChild,refChild); + }, + replaceChild:function(newChild, oldChild){//raises + this.insertBefore(newChild,oldChild); + if(oldChild){ + this.removeChild(oldChild); + } + }, + removeChild:function(oldChild){ + return _removeChild(this,oldChild); + }, + appendChild:function(newChild){ + return this.insertBefore(newChild,null); + }, + hasChildNodes:function(){ + return this.firstChild != null; + }, + cloneNode:function(deep){ + return cloneNode(this.ownerDocument||this,this,deep); + }, + // Modified in DOM Level 2: + normalize:function(){ + var child = this.firstChild; + while(child){ + var next = child.nextSibling; + if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){ + this.removeChild(next); + child.appendData(next.data); + }else{ + child.normalize(); + child = next; + } + } + }, + // Introduced in DOM Level 2: + isSupported:function(feature, version){ + return this.ownerDocument.implementation.hasFeature(feature,version); + }, + // Introduced in DOM Level 2: + hasAttributes:function(){ + return this.attributes.length>0; + }, + lookupPrefix:function(namespaceURI){ + var el = this; + while(el){ + var map = el._nsMap; + //console.dir(map) + if(map){ + for(var n in map){ + if(map[n] == namespaceURI){ + return n; + } + } + } + el = el.nodeType == 2?el.ownerDocument : el.parentNode; + } + return null; + }, + // Introduced in DOM Level 3: + lookupNamespaceURI:function(prefix){ + var el = this; + while(el){ + var map = el._nsMap; + //console.dir(map) + if(map){ + if(prefix in map){ + return map[prefix] ; + } + } + el = el.nodeType == 2?el.ownerDocument : el.parentNode; + } + return null; + }, + // Introduced in DOM Level 3: + isDefaultNamespace:function(namespaceURI){ + var prefix = this.lookupPrefix(namespaceURI); + return prefix == null; + } +}; + + +function _xmlEncoder(c){ + return c == '<' && '<' || + c == '>' && '>' || + c == '&' && '&' || + c == '"' && '"' || +// Fork : сохраняем тип кавычки (" или ') + c == '\'' && ''' || +// endFork + '&#'+c.charCodeAt()+';' +} + +// Fork : не реплейсим символьные коды +function replaceSpecialSymbols(string, symbolRegExp){ + var newString = string.replace(symbolRegExp,_xmlEncoder); + // нужно заменить & на & кроме случаев, когда & - начало символьного кода (напр., " или  ) + // заменяем в несколько этапов, сначала заменяем символьные коды на спец. конструкцию + newString = newString.replace(/&(\w+|#\d+);/g,'~HtmlCode::$1::endHtmlCode~'); + // после заменяем все &, которые не являются началом символьного кода + newString = newString.replace(/&/g,'&'); + // меняем спец. конструкции обратно на символьные коды + newString = newString.replace(/~HtmlCode::(\w+|#\d+)::endHtmlCode~/g,'&$1;'); + return newString; +} +// endFork + +copy(NodeType,Node); +copy(NodeType,Node.prototype); + +/** + * @param callback return true for continue,false for break + * @return boolean true: break visit; + */ +function _visitNode(node,callback){ + if(callback(node)){ + return true; + } + if(node = node.firstChild){ + do{ + if(_visitNode(node,callback)){return true} + }while(node=node.nextSibling) + } +} + + + +function Document(){ +} +function _onAddAttribute(doc,el,newAttr){ + doc && doc._inc++; + var ns = newAttr.namespaceURI ; + if(ns == 'http://www.w3.org/2000/xmlns/'){ + //update namespace + el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value + } +} +function _onRemoveAttribute(doc,el,newAttr,remove){ + doc && doc._inc++; + var ns = newAttr.namespaceURI ; + if(ns == 'http://www.w3.org/2000/xmlns/'){ + //update namespace + delete el._nsMap[newAttr.prefix?newAttr.localName:''] + } +} +function _onUpdateChild(doc,el,newChild){ + if(doc && doc._inc){ + doc._inc++; + //update childNodes + var cs = el.childNodes; + if(newChild){ + cs[cs.length++] = newChild; + }else{ + //console.log(1) + var child = el.firstChild; + var i = 0; + while(child){ + cs[i++] = child; + child =child.nextSibling; + } + cs.length = i; + } + } +} + +/** + * attributes; + * children; + * + * writeable properties: + * nodeValue,Attr:value,CharacterData:data + * prefix + */ +function _removeChild(parentNode,child){ + var previous = child.previousSibling; + var next = child.nextSibling; + if(previous){ + previous.nextSibling = next; + }else{ + parentNode.firstChild = next + } + if(next){ + next.previousSibling = previous; + }else{ + parentNode.lastChild = previous; + } + _onUpdateChild(parentNode.ownerDocument,parentNode); + return child; +} +/** + * preformance key(refChild == null) + */ +function _insertBefore(parentNode,newChild,nextChild){ + var cp = newChild.parentNode; + if(cp){ + cp.removeChild(newChild);//remove and update + } + if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){ + var newFirst = newChild.firstChild; + if (newFirst == null) { + return newChild; + } + var newLast = newChild.lastChild; + }else{ + newFirst = newLast = newChild; + } + var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild; + + newFirst.previousSibling = pre; + newLast.nextSibling = nextChild; + + + if(pre){ + pre.nextSibling = newFirst; + }else{ + parentNode.firstChild = newFirst; + } + if(nextChild == null){ + parentNode.lastChild = newLast; + }else{ + nextChild.previousSibling = newLast; + } + do{ + newFirst.parentNode = parentNode; + }while(newFirst !== newLast && (newFirst= newFirst.nextSibling)) + _onUpdateChild(parentNode.ownerDocument||parentNode,parentNode); + //console.log(parentNode.lastChild.nextSibling == null) + if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) { + newChild.firstChild = newChild.lastChild = null; + } + return newChild; +} +function _appendSingleChild(parentNode,newChild){ + var cp = newChild.parentNode; + if(cp){ + var pre = parentNode.lastChild; + cp.removeChild(newChild);//remove and update + var pre = parentNode.lastChild; + } + var pre = parentNode.lastChild; + newChild.parentNode = parentNode; + newChild.previousSibling = pre; + newChild.nextSibling = null; + if(pre){ + pre.nextSibling = newChild; + }else{ + parentNode.firstChild = newChild; + } + parentNode.lastChild = newChild; + _onUpdateChild(parentNode.ownerDocument,parentNode,newChild); + return newChild; + //console.log("__aa",parentNode.lastChild.nextSibling == null) +} +Document.prototype = { + //implementation : null, + nodeName : '#document', + nodeType : DOCUMENT_NODE, + doctype : null, + documentElement : null, + _inc : 1, + + insertBefore : function(newChild, refChild){//raises + if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){ + var child = newChild.firstChild; + while(child){ + var next = child.nextSibling; + this.insertBefore(child,refChild); + child = next; + } + return newChild; + } + if(this.documentElement == null && newChild.nodeType == 1){ + this.documentElement = newChild; + } + + return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild; + }, + removeChild : function(oldChild){ + if(this.documentElement == oldChild){ + this.documentElement = null; + } + return _removeChild(this,oldChild); + }, + // Introduced in DOM Level 2: + importNode : function(importedNode,deep){ + return importNode(this,importedNode,deep); + }, + // Introduced in DOM Level 2: + getElementById : function(id){ + var rtv = null; + _visitNode(this.documentElement,function(node){ + if(node.nodeType == 1){ + if(node.getAttribute('id') == id){ + rtv = node; + return true; + } + } + }) + return rtv; + }, + + //document factory method: + createElement : function(tagName){ + var node = new Element(); + node.ownerDocument = this; + node.nodeName = tagName; + node.tagName = tagName; + node.childNodes = new NodeList(); + var attrs = node.attributes = new NamedNodeMap(); + attrs._ownerElement = node; + return node; + }, + createDocumentFragment : function(){ + var node = new DocumentFragment(); + node.ownerDocument = this; + node.childNodes = new NodeList(); + return node; + }, + createTextNode : function(data){ + var node = new Text(); + node.ownerDocument = this; + node.appendData(data) + return node; + }, + createComment : function(data){ + var node = new Comment(); + node.ownerDocument = this; + node.appendData(data) + return node; + }, + createCDATASection : function(data){ + var node = new CDATASection(); + node.ownerDocument = this; + node.appendData(data) + return node; + }, + createProcessingInstruction : function(target,data){ + var node = new ProcessingInstruction(); + node.ownerDocument = this; + node.tagName = node.target = target; + node.nodeValue= node.data = data; + return node; + }, + createAttribute : function(name){ + var node = new Attr(); + node.ownerDocument = this; + node.name = name; + node.nodeName = name; + node.localName = name; + node.specified = true; + return node; + }, + createEntityReference : function(name){ + var node = new EntityReference(); + node.ownerDocument = this; + node.nodeName = name; + return node; + }, + // Introduced in DOM Level 2: + createElementNS : function(namespaceURI,qualifiedName){ + var node = new Element(); + var pl = qualifiedName.split(':'); + var attrs = node.attributes = new NamedNodeMap(); + node.childNodes = new NodeList(); + node.ownerDocument = this; + node.nodeName = qualifiedName; + node.tagName = qualifiedName; + node.namespaceURI = namespaceURI; + if(pl.length == 2){ + node.prefix = pl[0]; + node.localName = pl[1]; + }else{ + //el.prefix = null; + node.localName = qualifiedName; + } + attrs._ownerElement = node; + return node; + }, + // Introduced in DOM Level 2: + createAttributeNS : function(namespaceURI,qualifiedName){ + var node = new Attr(); + var pl = qualifiedName.split(':'); + node.ownerDocument = this; + node.nodeName = qualifiedName; + node.name = qualifiedName; + node.namespaceURI = namespaceURI; + node.specified = true; + if(pl.length == 2){ + node.prefix = pl[0]; + node.localName = pl[1]; + }else{ + //el.prefix = null; + node.localName = qualifiedName; + } + return node; + } +}; +_extends(Document,Node); + + +function Element() { + this._nsMap = {}; +}; +Element.prototype = { + nodeType : ELEMENT_NODE, + hasAttribute : function(name){ + return this.getAttributeNode(name)!=null; + }, + getAttribute : function(name){ + var attr = this.getAttributeNode(name); + return attr && attr.value || ''; + }, + getAttributeNode : function(name){ + return this.attributes.getNamedItem(name); + }, + setAttribute : function(name, value){ + var attr = this.ownerDocument.createAttribute(name); + attr.value = attr.nodeValue = "" + value; + this.setAttributeNode(attr) + }, + removeAttribute : function(name){ + var attr = this.getAttributeNode(name) + attr && this.removeAttributeNode(attr); + }, + + //four real opeartion method + appendChild:function(newChild){ + if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){ + return this.insertBefore(newChild,null); + }else{ + return _appendSingleChild(this,newChild); + } + }, + setAttributeNode : function(newAttr){ + return this.attributes.setNamedItem(newAttr); + }, + setAttributeNodeNS : function(newAttr){ + return this.attributes.setNamedItemNS(newAttr); + }, + removeAttributeNode : function(oldAttr){ + return this.attributes.removeNamedItem(oldAttr.nodeName); + }, + //get real attribute name,and remove it by removeAttributeNode + removeAttributeNS : function(namespaceURI, localName){ + var old = this.getAttributeNodeNS(namespaceURI, localName); + old && this.removeAttributeNode(old); + }, + + hasAttributeNS : function(namespaceURI, localName){ + return this.getAttributeNodeNS(namespaceURI, localName)!=null; + }, + getAttributeNS : function(namespaceURI, localName){ + var attr = this.getAttributeNodeNS(namespaceURI, localName); + return attr && attr.value || ''; + }, + setAttributeNS : function(namespaceURI, qualifiedName, value){ + var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName); + attr.value = attr.nodeValue = value; + this.setAttributeNode(attr) + }, + getAttributeNodeNS : function(namespaceURI, localName){ + return this.attributes.getNamedItemNS(namespaceURI, localName); + }, + + getElementsByTagName : function(tagName){ + return new LiveNodeList(this,function(base){ + var ls = []; + _visitNode(base,function(node){ + if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){ + ls.push(node); + } + }); + return ls; + }); + }, + getElementsByTagNameNS : function(namespaceURI, localName){ + return new LiveNodeList(this,function(base){ + var ls = []; + _visitNode(base,function(node){ + if(node !== base && node.nodeType === ELEMENT_NODE && node.namespaceURI === namespaceURI && (localName === '*' || node.localName == localName)){ + ls.push(node); + } + }); + return ls; + }); + } +}; +Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName; +Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS; + + +_extends(Element,Node); +function Attr() { +}; +Attr.prototype.nodeType = ATTRIBUTE_NODE; +_extends(Attr,Node); + + +function CharacterData() { +}; +CharacterData.prototype = { + data : '', + substringData : function(offset, count) { + return this.data.substring(offset, offset+count); + }, + appendData: function(text) { + text = this.data+text; + this.nodeValue = this.data = text; + this.length = text.length; + }, + insertData: function(offset,text) { + this.replaceData(offset,0,text); + + }, + appendChild:function(newChild){ + //if(!(newChild instanceof CharacterData)){ + throw new Error(ExceptionMessage[3]) + //} + return Node.prototype.appendChild.apply(this,arguments) + }, + deleteData: function(offset, count) { + this.replaceData(offset,count,""); + }, + replaceData: function(offset, count, text) { + var start = this.data.substring(0,offset); + var end = this.data.substring(offset+count); + text = start + text + end; + this.nodeValue = this.data = text; + this.length = text.length; + } +} +_extends(CharacterData,Node); +function Text() { +}; +Text.prototype = { + nodeName : "#text", + nodeType : TEXT_NODE, + splitText : function(offset) { + var text = this.data; + var newText = text.substring(offset); + text = text.substring(0, offset); + this.data = this.nodeValue = text; + this.length = text.length; + var newNode = this.ownerDocument.createTextNode(newText); + if(this.parentNode){ + this.parentNode.insertBefore(newNode, this.nextSibling); + } + return newNode; + } +} +_extends(Text,CharacterData); +function Comment() { +}; +Comment.prototype = { + nodeName : "#comment", + nodeType : COMMENT_NODE +} +_extends(Comment,CharacterData); + +function CDATASection() { +}; +CDATASection.prototype = { + nodeName : "#cdata-section", + nodeType : CDATA_SECTION_NODE +} +_extends(CDATASection,CharacterData); + + +function DocumentType() { +}; +DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE; +_extends(DocumentType,Node); + +function Notation() { +}; +Notation.prototype.nodeType = NOTATION_NODE; +_extends(Notation,Node); + +function Entity() { +}; +Entity.prototype.nodeType = ENTITY_NODE; +_extends(Entity,Node); + +function EntityReference() { +}; +EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE; +_extends(EntityReference,Node); + +function DocumentFragment() { +}; +DocumentFragment.prototype.nodeName = "#document-fragment"; +DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE; +_extends(DocumentFragment,Node); + + +function ProcessingInstruction() { +} +ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE; +_extends(ProcessingInstruction,Node); +function XMLSerializer(){} +XMLSerializer.prototype.serializeToString = function(node){ + var buf = []; + serializeToString(node,buf); + return buf.join(''); +} +Node.prototype.toString =function(){ + return XMLSerializer.prototype.serializeToString(this); +} +function serializeToString(node,buf){ + switch(node.nodeType){ + case ELEMENT_NODE: + var attrs = node.attributes; + var len = attrs.length; + var child = node.firstChild; + var nodeName = node.tagName; +// Fork : считаем, что у нас HTML-документ + var isHTML = true;//htmlns === node.namespaceURI +// endFork + buf.push('<',nodeName); + for(var i=0;i'); + //if is cdata child node + if(isHTML && /^script$/i.test(nodeName)){ + if(child){ + buf.push(child.data); + } + }else{ + while(child){ + serializeToString(child,buf); + child = child.nextSibling; + } + } + buf.push(''); + }else{ + buf.push('/>'); + } + return; + case DOCUMENT_NODE: + case DOCUMENT_FRAGMENT_NODE: + var child = node.firstChild; + while(child){ + serializeToString(child,buf); + child = child.nextSibling; + } + return; + case ATTRIBUTE_NODE: +// Fork : сохраняем тип кавычки (" или ') + аттрибут config всегда должен сохранять значение в одинарных кавычках ( config='{"caption":"Кнопка"}' ) + if (node.name === 'config' || (node.quotSymbol === '\'')){ + return buf.push(' ', node.name, '=\'', replaceSpecialSymbols(node.value + '', /[<']/g), '\''); + } +// endFork +// Fork : не реплейсим символьные коды + return buf.push(' ',node.name,'="',replaceSpecialSymbols(node.value + '', /[<"]/g),'"'); +// endFork + case TEXT_NODE: +// Fork : не реплейсим символьные коды + return buf.push(replaceSpecialSymbols(node.data,/[<]/g)); +// endFork + case CDATA_SECTION_NODE: + return buf.push( ''); + case COMMENT_NODE: + return buf.push( ""); + case DOCUMENT_TYPE_NODE: + var pubid = node.publicId; + var sysid = node.systemId; + buf.push(''); + }else if(sysid && sysid!='.'){ + buf.push(' SYSTEM "',sysid,'">'); + }else{ + var sub = node.internalSubset; + if(sub){ + buf.push(" [",sub,"]"); + } + buf.push(">"); + } + return; + case PROCESSING_INSTRUCTION_NODE: + return buf.push( ""); + case ENTITY_REFERENCE_NODE: + return buf.push( '&',node.nodeName,';'); + //case ENTITY_NODE: + //case NOTATION_NODE: + default: + buf.push('??',node.nodeName); + } +} +function importNode(doc,node,deep){ + var node2; + switch (node.nodeType) { + case ELEMENT_NODE: + node2 = node.cloneNode(false); + node2.ownerDocument = doc; + //var attrs = node2.attributes; + //var len = attrs.length; + //for(var i=0;i" + value + "", 'text/html'); + } catch (e) { + console.log("Error while parsing innerHTML " + e); + } + if (doc) { + ownNode = this.ownerDocument.importNode(doc.documentElement, true); + + while (this.firstChild) { + this.removeChild(this.firstChild); + } + while (ownNode.firstChild) { + this.appendChild(ownNode.firstChild); + } + } + } + }); + Object.defineProperty(Element.prototype, 'outerHTML', { + get: function () { + return this.toString(); + } + }); +// endFork + Object.defineProperty(LiveNodeList.prototype,'length',{ + get:function(){ + _updateLiveList(this); + return this.$$length; + } + }); + Object.defineProperty(Node.prototype,'textContent',{ + get:function(){ + return getTextContent(this); + }, + set:function(data){ + switch(this.nodeType){ + case 1: + case 11: + while(this.firstChild){ + this.removeChild(this.firstChild); + } + if(data || String(data)){ + this.appendChild(this.ownerDocument.createTextNode(data)); + } + break; + default: + //TODO: + this.data = data; + this.value = value; + this.nodeValue = data; + } + } + }) + + function getTextContent(node){ + switch(node.nodeType){ + case 1: + case 11: + var buf = []; + node = node.firstChild; + while(node){ + if(node.nodeType!==7 && node.nodeType !==8){ + buf.push(getTextContent(node)); + } + node = node.nextSibling; + } + return buf.join(''); + default: + return node.nodeValue; + } + } + __set__ = function(object,key,value){ + //console.log(value) + object['$$'+key] = value + } + } +}catch(e){//ie8 +} + +return new DOMImplementation(); +}); \ No newline at end of file diff --git a/lib/ace/mode/xml/sax.js b/lib/ace/mode/xml/sax.js new file mode 100644 index 00000000..89e82d4a --- /dev/null +++ b/lib/ace/mode/xml/sax.js @@ -0,0 +1,608 @@ +define(function(require, exports, module) { +'use strict'; + +//[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] +//[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] +//[5] Name ::= NameStartChar (NameChar)* +var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]///\u10000-\uEFFFF +var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\u00B7\u0300-\u036F\\ux203F-\u2040]"); +var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$'); +//var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/ +//var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',') + +//S_TAG, S_ATTR, S_EQ, S_V +//S_ATTR_S, S_E, S_S, S_C +var S_TAG = 0;//tag name offerring +var S_ATTR = 1;//attr name offerring +var S_ATTR_S=2;//attr name end and space offer +var S_EQ = 3;//=space? +var S_V = 4;//attr value(no quot value only) +var S_E = 5;//attr value end and no space(quot end) +var S_S = 6;//(attr value end || tag end ) && (space offer) +var S_C = 7;//closed el + +function XMLReader(){ + +} + +XMLReader.prototype = { + parse:function(source,defaultNSMap,entityMap){ + var domBuilder = this.domBuilder; + domBuilder.startDocument(); + _copy(defaultNSMap ,defaultNSMap = {}) + parse(source,defaultNSMap,entityMap, + domBuilder,this.errorHandler); + domBuilder.endDocument(); + } +} +function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){ + function fixedFromCharCode(code) { + // String.prototype.fromCharCode does not supports + // > 2 bytes unicode chars directly + if (code > 0xffff) { + code -= 0x10000; + var surrogate1 = 0xd800 + (code >> 10) + , surrogate2 = 0xdc00 + (code & 0x3ff); + + return String.fromCharCode(surrogate1, surrogate2); + } else { + return String.fromCharCode(code); + } + } + function entityReplacer(a){ + var k = a.slice(1,-1); + if(k in entityMap){ + return entityMap[k]; + }else if(k.charAt(0) === '#'){ + return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x'))) + }else{ + errorHandler.error('entity not found:'+a); + return a; + } + } + function appendText(end){//has some bugs +// Fork : не реплейсим символьные коды + var xt = source.substring(start,end);//.replace(/&#?\w+;/g,entityReplacer); +// endFork + locator&&position(start); + domBuilder.characters(xt,0,end-start); + start = end + } + function position(start,m){ + while(start>=endPos && (m = linePattern.exec(source))){ + startPos = m.index; + endPos = startPos + m[0].length; + locator.lineNumber++; + //console.log('line++:',locator,startPos,endPos) + } + locator.columnNumber = start-startPos+1; + } + var startPos = 0; + var endPos = 0; + var linePattern = /.+(?:\r\n?|\n)|.*$/g + var locator = domBuilder.locator; + + var parseStack = [{currentNSMap:defaultNSMapCopy}] + var closeMap = {}; + var start = 0; + while(true){ + var i = source.indexOf('<',start); + if(i<0){ + if(!source.substr(start).match(/^\s*$/)){ + var doc = domBuilder.document; + var text = doc.createTextNode(source.substr(start)); + doc.appendChild(text); + domBuilder.currentElement = text; + } + return; + } + if(i>start){ + appendText(i); + } + switch(source.charAt(i+1)){ + case '/': + var end = source.indexOf('>',i+3); + var tagName = source.substring(i+2,end); + if (parseStack.length > 1) { + var config = parseStack.pop(); + } else { + errorHandler.fatalError("end tag name not found for: "+tagName); + break; + } + var localNSMap = config.localNSMap; + + if(config.tagName != tagName){ + errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName ); + } + domBuilder.endElement(config.uri,config.localName,tagName); + if(localNSMap){ + for(var prefix in localNSMap){ + domBuilder.endPrefixMapping(prefix) ; + } + } + end++; + break; + // end elment + case '?':// + locator&&position(i); + end = parseInstruction(source,i,domBuilder); + break; + case '!':// 0){ +// Fork : не реплейсим символьные коды + value = source.slice(start,p);//.replace(/&#?\w+;/g,entityReplacer); +// endFork +// Fork : сохраняем тип кавычки (" или ') + el.add(attrName,value,start-1, c); +// endFork + s = S_E; + }else{ + //fatalError: no end quot match + throw new Error('attribute value no end \''+c+'\' match'); + } + }else if(s == S_V){ +// Fork : не реплейсим символьные коды + value = source.slice(start,p);//.replace(/&#?\w+;/g,entityReplacer); +// endFork + //console.log(attrName,value,start,p) +// Fork : сохраняем тип кавычки (" или ') + el.add(attrName,value,start, c); +// endFork + //console.dir(el) + errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!'); + start = p+1; + s = S_E + }else{ + //fatalError: no equal before + throw new Error('attribute value must after "="'); + } + break; + case '/': + switch(s){ + case S_TAG: + el.setTagName(source.slice(start,p)); + case S_E: + case S_S: + case S_C: + s = S_C; + el.closed = true; + case S_V: + case S_ATTR: + case S_ATTR_S: + break; + //case S_EQ: + default: + throw new Error("attribute invalid close char('/')") + } + break; + case ''://end document + //throw new Error('unexpected end of input') + errorHandler.error('unexpected end of input'); + case '>': + switch(s){ + case S_TAG: + el.setTagName(source.slice(start,p)); + case S_E: + case S_S: + case S_C: + break;//normal + case S_V://Compatible state + case S_ATTR: + value = source.slice(start,p); + if(value.slice(-1) === '/'){ + el.closed = true; + value = value.slice(0,-1) + } + case S_ATTR_S: + if(s === S_ATTR_S){ + value = attrName; + } + if(s == S_V){ + errorHandler.warning('attribute "'+value+'" missed quot(")!!'); +// Fork : не реплейсим символьные коды + el.add(attrName,value/*.replace(/&#?\w+;/g,entityReplacer)*/,start) +// endFork + }else{ + errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!') + el.add(value,value,start) + } + break; + case S_EQ: + throw new Error('attribute value missed!!'); + } +// console.log(tagName,tagNamePattern,tagNamePattern.test(tagName)) + return p; + /*xml space '\x20' | #x9 | #xD | #xA; */ + case '\u0080': + c = ' '; + default: + if(c<= ' '){//space + switch(s){ + case S_TAG: + el.setTagName(source.slice(start,p));//tagName + s = S_S; + break; + case S_ATTR: + attrName = source.slice(start,p) + s = S_ATTR_S; + break; + case S_V: +// Fork : не реплейсим символьные коды + var value = source.slice(start,p);//.replace(/&#?\w+;/g,entityReplacer); +// endFork + errorHandler.warning('attribute "'+value+'" missed quot(")!!'); + el.add(attrName,value,start) + case S_E: + s = S_S; + break; + //case S_S: + //case S_EQ: + //case S_ATTR_S: + // void();break; + //case S_C: + //ignore warning + } + }else{//not space +//S_TAG, S_ATTR, S_EQ, S_V +//S_ATTR_S, S_E, S_S, S_C + switch(s){ + //case S_TAG:void();break; + //case S_ATTR:void();break; + //case S_V:void();break; + case S_ATTR_S: + errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead!!') + el.add(attrName,attrName,start); + start = p; + s = S_ATTR; + break; + case S_E: + errorHandler.warning('attribute space is required"'+attrName+'"!!') + case S_S: + s = S_ATTR; + start = p; + break; + case S_EQ: + s = S_V; + start = p; + break; + case S_C: + throw new Error("elements closed character '/' and '>' must be connected to"); + } + } + } + p++; + } +} +/** + * @return end of the elementStartPart(end of elementEndPart for selfClosed el) + */ +function appendElement(el,domBuilder,parseStack){ + var tagName = el.tagName; + var localNSMap = null; + var currentNSMap = parseStack[parseStack.length-1].currentNSMap; + var i = el.length; + while(i--){ + var a = el[i]; + var qName = a.qName; + var value = a.value; + var nsp = qName.indexOf(':'); + if(nsp>0){ + var prefix = a.prefix = qName.slice(0,nsp); + var localName = qName.slice(nsp+1); + var nsPrefix = prefix === 'xmlns' && localName + }else{ + localName = qName; + prefix = null + nsPrefix = qName === 'xmlns' && '' + } + //can not set prefix,because prefix !== '' + a.localName = localName ; + //prefix == null for no ns prefix attribute + if(nsPrefix !== false){//hack!! + if(localNSMap == null){ + localNSMap = {} + //console.log(currentNSMap,0) + _copy(currentNSMap,currentNSMap={}) + //console.log(currentNSMap,1) + } + currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value; + a.uri = 'http://www.w3.org/2000/xmlns/' + domBuilder.startPrefixMapping(nsPrefix, value) + } + } + var i = el.length; + while(i--){ + a = el[i]; + var prefix = a.prefix; + if(prefix){//no prefix attribute has no namespace + if(prefix === 'xml'){ + a.uri = 'http://www.w3.org/XML/1998/namespace'; + }if(prefix !== 'xmlns'){ + a.uri = currentNSMap[prefix] + + //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)} + } + } + } + var nsp = tagName.indexOf(':'); + if(nsp>0){ + prefix = el.prefix = tagName.slice(0,nsp); + localName = el.localName = tagName.slice(nsp+1); + }else{ + prefix = null;//important!! + localName = el.localName = tagName; + } + //no prefix element has default namespace + var ns = el.uri = currentNSMap[prefix || '']; + domBuilder.startElement(ns,localName,tagName,el); + //endPrefixMapping and startPrefixMapping have not any help for dom builder + //localNSMap = null + if(el.closed){ + domBuilder.endElement(ns,localName,tagName); + if(localNSMap){ + for(prefix in localNSMap){ + domBuilder.endPrefixMapping(prefix) + } + } + }else{ + el.currentNSMap = currentNSMap; + el.localNSMap = localNSMap; + parseStack.push(el); + } +} +function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){ + if(/^(?:script|textarea)$/i.test(tagName)){ + var elEndStart = source.indexOf('',elStartEnd); + var text = source.substring(elStartEnd+1,elEndStart); + if(/[&<]/.test(text)){ + if(/^script$/i.test(tagName)){ + //if(!/\]\]>/.test(text)){ + //lexHandler.startCDATA(); + domBuilder.characters(text,0,text.length); + //lexHandler.endCDATA(); + return elEndStart; + //} + }//}else{//text area +// Fork : не реплейсим символьные коды + // text = text.replace(/&#?\w+;/g,entityReplacer); +// endFork + domBuilder.characters(text,0,text.length); + return elEndStart; + //} + + } + } + return elStartEnd+1; +} +function fixSelfClosed(source,elStartEnd,tagName,closeMap){ + //if(tagName in closeMap){ + var pos = closeMap[tagName]; + if(pos == null){ + //console.log(tagName) + pos = closeMap[tagName] = source.lastIndexOf('') + } + return pos',start+4); + //append comment source.substring(4,end)//|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|/=|%=|\\+=|\\-=|&=|\\^=|,|;' }, @@ -106,11 +106,11 @@ var RustHighlightRules = function() { { token: 'meta.preprocessor.source.rust', regex: '\\b\\w\\(\\w\\)*!|#\\[[\\w=\\(\\)_]+\\]\\b' }, { token: 'constant.numeric.integer.source.rust', - regex: '\\b(?:[0-9][0-9_]*|[0-9][0-9_]*(?:u|u8|u16|u32|u64)|[0-9][0-9_]*(?:i|i8|i16|i32|i64))\\b' }, + regex: '\\b(?:[0-9][0-9_]*|[0-9][0-9_]*(?:u|us|u8|u16|u32|u64)|[0-9][0-9_]*(?:i|is|i8|i16|i32|i64))\\b' }, { token: 'constant.numeric.hex.source.rust', - regex: '\\b(?:0x[a-fA-F0-9_]+|0x[a-fA-F0-9_]+(?:u|u8|u16|u32|u64)|0x[a-fA-F0-9_]+(?:i|i8|i16|i32|i64))\\b' }, + regex: '\\b(?:0x[a-fA-F0-9_]+|0x[a-fA-F0-9_]+(?:u|us|u8|u16|u32|u64)|0x[a-fA-F0-9_]+(?:i|is|i8|i16|i32|i64))\\b' }, { token: 'constant.numeric.binary.source.rust', - regex: '\\b(?:0b[01_]+|0b[01_]+(?:u|u8|u16|u32|u64)|0b[01_]+(?:i|i8|i16|i32|i64))\\b' }, + regex: '\\b(?:0b[01_]+|0b[01_]+(?:u|us|u8|u16|u32|u64)|0b[01_]+(?:i|is|i8|i16|i32|i64))\\b' }, { token: 'constant.numeric.float.source.rust', regex: '[0-9][0-9_]*(?:f32|f64|f)|[0-9][0-9_]*[eE][+-]=[0-9_]+|[0-9][0-9_]*[eE][+-]=[0-9_]+(?:f32|f64|f)|[0-9][0-9_]*\\.[0-9_]+|[0-9][0-9_]*\\.[0-9_]+(?:f32|f64|f)|[0-9][0-9_]*\\.[0-9_]+%[eE][+-]=[0-9_]+|[0-9][0-9_]*\\.[0-9_]+%[eE][+-]=[0-9_]+(?:f32|f64|f)' }, { token: 'comment.line.documentation.source.rust', From 3fe1383cdc3cbf8af378ede0c05afb5446f15acf Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Wed, 28 Jan 2015 10:53:42 -0800 Subject: [PATCH 159/315] [xml] ensure tag name starts with letter --- lib/ace/mode/xml_highlight_rules.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/ace/mode/xml_highlight_rules.js b/lib/ace/mode/xml_highlight_rules.js index 5bb1086b..91da0e70 100644 --- a/lib/ace/mode/xml_highlight_rules.js +++ b/lib/ace/mode/xml_highlight_rules.js @@ -35,6 +35,9 @@ var oop = require("../lib/oop"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var XmlHighlightRules = function(normalize) { + + var tagRegex = "[a-zA-Z][-_a-zA-Z0-9]*"; + this.$rules = { start : [ {token : "string.cdata.xml", regex : "<\\!\\[CDATA\\[", next : "cdata"}, @@ -44,7 +47,7 @@ var XmlHighlightRules = function(normalize) { }, { token : ["punctuation.instruction.xml", "keyword.instruction.xml"], - regex : "(<\\?)([-_a-zA-Z0-9]+)", next : "processing_instruction", + regex : "(<\\?)(" + tagRegex + ")", next : "processing_instruction", }, {token : "comment.xml", regex : "<\\!--", next : "comment"}, { @@ -60,7 +63,7 @@ var XmlHighlightRules = function(normalize) { xml_decl : [{ token : "entity.other.attribute-name.decl-attribute-name.xml", - regex : "(?:[-_a-zA-Z0-9]+:)?[-_a-zA-Z0-9]+" + regex : "(?:" + tagRegex + ":)?" + tagRegex + "" }, { token : "keyword.operator.decl-attribute-equals.xml", regex : "=" @@ -96,7 +99,7 @@ var XmlHighlightRules = function(normalize) { next: "pop" }, { token : ["punctuation.markup-decl.xml", "keyword.markup-decl.xml"], - regex : "(<\\!)([-_a-zA-Z0-9]+)", + regex : "(<\\!)(" + tagRegex + ")", push : [{ token : "text", regex : "\\s+" @@ -132,7 +135,7 @@ var XmlHighlightRules = function(normalize) { tag : [{ token : ["meta.tag.punctuation.tag-open.xml", "meta.tag.punctuation.end-tag-open.xml", "meta.tag.tag-name.xml"], - regex : "(?:(<)|(", next : "start"} @@ -166,7 +169,7 @@ var XmlHighlightRules = function(normalize) { attributes: [{ token : "entity.other.attribute-name.xml", - regex : "(?:[-_a-zA-Z0-9]+:)?[-_a-zA-Z0-9]+" + regex : "(?:" + tagRegex + ":)?" + tagRegex + "" }, { token : "keyword.operator.attribute-equals.xml", regex : "=" From c8404712484293e3241dbec1c8dbd801e92c325c Mon Sep 17 00:00:00 2001 From: Tyler Long Date: Thu, 29 Jan 2015 14:47:57 +0800 Subject: [PATCH 160/315] XAML is XML https://msdn.microsoft.com/en-us/library/cc295302.aspx --- lib/ace/ext/modelist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index db2d2f80..69aa8972 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -159,7 +159,7 @@ var supportedModes = { Velocity: ["vm"], Verilog: ["v|vh|sv|svh"], VHDL: ["vhd|vhdl"], - XML: ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl"], + XML: ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml"], XQuery: ["xq"], YAML: ["yaml|yml"], // Add the missing mode "Django" to ext-modelist From 3e32d5bf7e1cf83585cfba7184d45aa1b607210b Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 26 Jan 2015 18:38:51 +0400 Subject: [PATCH 161/315] workaround for vim cursor getting stuck on folded lines --- lib/ace/keyboard/vim.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/ace/keyboard/vim.js b/lib/ace/keyboard/vim.js index 7312821f..0641897f 100644 --- a/lib/ace/keyboard/vim.js +++ b/lib/ace/keyboard/vim.js @@ -2396,6 +2396,15 @@ dom.importCssString(".normal-mode .ace_cursor{\ (line > last && cur.line == last)) { return; } + // /ace patch + var fold = cm.ace.session.getFoldAt(line, endCh); + if (fold) { + if (motionArgs.forward) + line = fold.end.row + 1; + else + line = fold.start.row - 1; + } + // /ace patche if (motionArgs.toFirstChar){ endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line)); vim.lastHPos = endCh; From 42b43b1fbe22c2c584c6b71685e699fd67aae2c9 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 29 Jan 2015 19:41:40 +0400 Subject: [PATCH 162/315] fix highlighting of indented bash heredocs --- lib/ace/mode/sh_highlight_rules.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/mode/sh_highlight_rules.js b/lib/ace/mode/sh_highlight_rules.js index 9dd9aa33..9d32055a 100644 --- a/lib/ace/mode/sh_highlight_rules.js +++ b/lib/ace/mode/sh_highlight_rules.js @@ -104,7 +104,7 @@ var ShHighlightRules = function() { token : "keyword.operator" }, { stateName: "heredoc", - regex : "(<<)(\\s*)(['\"`]?)([\\w\\-]+)(['\"`]?)", + regex : "(<<-?)(\\s*)(['\"`]?)([\\w\\-]+)(['\"`]?)", onMatch : function(value, currentState, stack) { var next = value[2] == '-' ? "indentedHeredoc" : "heredoc"; var tokens = value.split(this.splitRegex); From 703a5394e3f29a7273070dfd7b5888fc54566432 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 3 Feb 2015 17:42:17 +0400 Subject: [PATCH 163/315] toggle fold commands must work for all selections --- lib/ace/commands/default_commands.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/ace/commands/default_commands.js b/lib/ace/commands/default_commands.js index d018e8bd..e941806b 100644 --- a/lib/ace/commands/default_commands.js +++ b/lib/ace/commands/default_commands.js @@ -97,24 +97,28 @@ exports.commands = [{ name: "fold", bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"), exec: function(editor) { editor.session.toggleFold(false); }, + multiSelectAction: "forEach", scrollIntoView: "center", readOnly: true }, { name: "unfold", bindKey: bindKey("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"), exec: function(editor) { editor.session.toggleFold(true); }, + multiSelectAction: "forEach", scrollIntoView: "center", readOnly: true }, { name: "toggleFoldWidget", bindKey: bindKey("F2", "F2"), exec: function(editor) { editor.session.toggleFoldWidget(); }, + multiSelectAction: "forEach", scrollIntoView: "center", readOnly: true }, { name: "toggleParentFoldWidget", bindKey: bindKey("Alt-F2", "Alt-F2"), exec: function(editor) { editor.session.toggleFoldWidget(true); }, + multiSelectAction: "forEach", scrollIntoView: "center", readOnly: true }, { From d9e4b52ee12ce5972dadae36171eaed8bf9d0eb2 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 5 Feb 2015 15:57:24 +0400 Subject: [PATCH 164/315] fix alt-e at the last error --- lib/ace/ext/error_marker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/ext/error_marker.js b/lib/ace/ext/error_marker.js index 05d50498..5dbe3d2e 100644 --- a/lib/ace/ext/error_marker.js +++ b/lib/ace/ext/error_marker.js @@ -62,7 +62,7 @@ function findAnnotations(session, row, dir) { if (i < 0) i = -i - 1; - if (i >= annotations.length - 1) + if (i >= annotations.length) i = dir > 0 ? 0 : annotations.length - 1; else if (i === 0 && dir < 0) i = annotations.length - 1; From 388f0235b77a8951aec18f2ff08eade7dcb4985e Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 12 Feb 2015 19:45:43 +0400 Subject: [PATCH 165/315] fix #2348 packaged require breaks node-webkit --- build_support/mini_require.js | 87 +++++++++++++++-------------------- 1 file changed, 37 insertions(+), 50 deletions(-) diff --git a/build_support/mini_require.js b/build_support/mini_require.js index 88937f35..1ecbb78b 100644 --- a/build_support/mini_require.js +++ b/build_support/mini_require.js @@ -38,69 +38,62 @@ var ACE_NAMESPACE = ""; -var global = (function() { - return this; -})(); +var global = (function() { return this; })(); +if (!global && typeof window != "undefined") global = window; // strict mode if (!ACE_NAMESPACE && typeof requirejs !== "undefined") return; -var _define = function(module, deps, payload) { - if (typeof module !== 'string') { - if (_define.original) - _define.original.apply(window, arguments); +var define = function(module, deps, payload) { + if (typeof module !== "string") { + if (define.original) + define.original.apply(this, arguments); else { - console.error('dropping module because define wasn\'t a string.'); + console.error("dropping module because define wasn\'t a string."); console.trace(); } return; } - if (arguments.length == 2) payload = deps; - - if (!_define.modules) { - _define.modules = {}; - _define.payloads = {}; + if (!define.modules[module]) { + define.payloads[module] = payload; + define.modules[module] = null; } - - _define.payloads[module] = payload; - _define.modules[module] = null; }; +define.modules = {}; +define.payloads = {}; + /** * Get at functionality define()ed using the function above */ var _require = function(parentId, module, callback) { - if (Object.prototype.toString.call(module) === "[object Array]") { + if (typeof module === "string") { + var payload = lookup(parentId, module); + if (payload != undefined) { + callback && callback(); + return payload; + } + } else if (Object.prototype.toString.call(module) === "[object Array]") { var params = []; for (var i = 0, l = module.length; i < l; ++i) { var dep = lookup(parentId, module[i]); - if (!dep && _require.original) - return _require.original.apply(window, arguments); + if (dep == undefined && require.original) + return; params.push(dep); } - if (callback) { - callback.apply(null, params); - } + return callback && callback.apply(null, params) || true; } - else if (typeof module === 'string') { - var payload = lookup(parentId, module); - if (!payload && _require.original) - return _require.original.apply(window, arguments); +}; - if (callback) { - callback(); - } - - return payload; - } - else { - if (_require.original) - return _require.original.apply(window, arguments); - } +var require = function(module, callback) { + var packagedModule = _require("", module, callback); + if (packagedModule == undefined && require.original) + return require.original.apply(this, arguments); + return packagedModule; }; var normalizeModule = function(parentId, moduleName) { @@ -119,7 +112,6 @@ var normalizeModule = function(parentId, moduleName) { moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); } } - return moduleName; }; @@ -128,12 +120,11 @@ var normalizeModule = function(parentId, moduleName) { * definition function if needed. */ var lookup = function(parentId, moduleName) { - moduleName = normalizeModule(parentId, moduleName); - var module = _define.modules[moduleName]; + var module = define.modules[moduleName]; if (!module) { - module = _define.payloads[moduleName]; + module = define.payloads[moduleName]; if (typeof module === 'function') { var exports = {}; var mod = { @@ -149,19 +140,15 @@ var lookup = function(parentId, moduleName) { var returnValue = module(req, exports, mod); exports = returnValue || mod.exports; - _define.modules[moduleName] = exports; - delete _define.payloads[moduleName]; + define.modules[moduleName] = exports; + delete define.payloads[moduleName]; } - module = _define.modules[moduleName] = exports || module; + module = define.modules[moduleName] = exports || module; } return module; }; function exportAce(ns) { - var require = function(module, callback) { - return _require("", module, callback); - }; - var root = global; if (ns) { if (!global[ns]) @@ -170,13 +157,13 @@ function exportAce(ns) { } if (!root.define || !root.define.packaged) { - _define.original = root.define; - root.define = _define; + define.original = root.define; + root.define = define; root.define.packaged = true; } if (!root.require || !root.require.packaged) { - _require.original = root.require; + require.original = root.require; root.require = require; root.require.packaged = true; } From 0b20e4dc1d0ae1c04b08f90bec878d8565c087d5 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 12 Feb 2015 19:46:21 +0400 Subject: [PATCH 166/315] fix #2351 Minification fails on Windows --- Makefile.dryice.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Makefile.dryice.js b/Makefile.dryice.js index f6f4b42f..0ce7c657 100755 --- a/Makefile.dryice.js +++ b/Makefile.dryice.js @@ -307,6 +307,7 @@ function buildAceModuleInternal(opts, callback) { ignore: opts.ignore || [], withRequire: false, basepath: ACE_HOME, + transforms: [normalizeLineEndings], afterRead: [optimizeTextModules] }, write); } @@ -407,6 +408,10 @@ function getLoadedFileList(options, callback, result) { callback(Object.keys(deps)); } +function normalizeLineEndings(module) { + module.source = module.source.replace(/\r\n/g, "\n"); +} + function optimizeTextModules(sources) { var textModules = {}; return sources.filter(function(pkg) { @@ -452,10 +457,10 @@ function optimizeTextModules(sources) { if (/\.css$/.test(pkg.id)) { // remove unnecessary whitespace from css input = input.replace(/\n\s+/g, "\n"); - input = '"' + input.replace(/\r?\n/g, '\\\n') + '"'; + input = '"' + input.replace(/\n/g, '\\\n') + '"'; } else { // but don't break other files! - input = '"' + input.replace(/\r?\n/g, '\\n\\\n') + '"'; + input = '"' + input.replace(/\n/g, '\\n\\\n') + '"'; } textModules[pkg.id] = input; } From b0475ce3e4aa6dc0daa3913a0c439a17c59c4f35 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 16 Feb 2015 14:27:22 +0000 Subject: [PATCH 167/315] Added C++11 tokens to highlighting rules --- lib/ace/mode/c_cpp_highlight_rules.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ace/mode/c_cpp_highlight_rules.js b/lib/ace/mode/c_cpp_highlight_rules.js index b5a29799..9d2f33dc 100644 --- a/lib/ace/mode/c_cpp_highlight_rules.js +++ b/lib/ace/mode/c_cpp_highlight_rules.js @@ -18,13 +18,13 @@ var c_cppHighlightRules = function() { var storageType = ( "asm|__asm__|auto|bool|_Bool|char|_Complex|double|enum|float|" + "_Imaginary|int|long|short|signed|struct|typedef|union|unsigned|void|" + - "class|wchar_t|template" + "class|wchar_t|template|char16_t|char32_t" ); var storageModifiers = ( "const|extern|register|restrict|static|volatile|inline|private|" + "protected|public|friend|explicit|virtual|export|mutable|typename|" + - "constexpr|new|delete" + "constexpr|new|delete|alignas|alignof|decltype|noexcept|thread_local" ); var keywordOperators = ( @@ -33,7 +33,7 @@ var c_cppHighlightRules = function() { ); var builtinConstants = ( - "NULL|true|false|TRUE|FALSE" + "NULL|true|false|TRUE|FALSE|nullptr" ); var keywordMapper = this.$keywords = this.createKeywordMapper({ From 16b542aea4c0fa584d2af5633976158c3c58d335 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 18 Feb 2015 23:17:05 +0400 Subject: [PATCH 168/315] reduce crazy large negative top value on hidden textarea (fixes #2362) --- lib/ace/keyboard/textinput.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ace/keyboard/textinput.js b/lib/ace/keyboard/textinput.js index faf73a4a..38fe0923 100644 --- a/lib/ace/keyboard/textinput.js +++ b/lib/ace/keyboard/textinput.js @@ -51,7 +51,7 @@ var TextInput = function(parentNode, host) { text.setAttribute("spellcheck", false); text.style.opacity = "0"; - if (useragent.isOldIE) text.style.top = "-100px"; + if (useragent.isOldIE) text.style.top = "-1000px"; parentNode.insertBefore(text, parentNode.firstChild); var PLACEHOLDER = "\x01\x01"; @@ -77,7 +77,7 @@ var TextInput = function(parentNode, host) { }); this.focus = function() { text.style.position = "fixed"; - text.style.top = "-10000000px"; + text.style.top = "-1000px"; text.focus(); setTimeout(function() { text.style.position = ""; From 4bc34f4eae5a45c00e7e5d94f25ebe7439aa7ce3 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 18 Feb 2015 23:26:22 +0400 Subject: [PATCH 169/315] fix #2341 do not use ace_editor id for the default style --- lib/ace/virtual_renderer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index 484ebb5e..5696745c 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -46,7 +46,7 @@ var FontMetrics = require("./layer/font_metrics").FontMetrics; var EventEmitter = require("./lib/event_emitter").EventEmitter; var editorCss = require("./requirejs/text!./css/editor.css"); -dom.importCssString(editorCss, "ace_editor"); +dom.importCssString(editorCss, "ace_editor.css"); /** * The class that is responsible for drawing everything you see on the screen! From b3da9336eed368b5a23bb86b731caee1b43768cd Mon Sep 17 00:00:00 2001 From: Soonho Kong Date: Mon, 23 Feb 2015 07:01:43 -0500 Subject: [PATCH 170/315] add 'lean' mode for Lean Theorem Prover files --- lib/ace/ext/modelist.js | 2 +- lib/ace/mode/lean.js | 101 ++++++++++++ lib/ace/mode/lean_highlight_rules.js | 224 +++++++++++++++++++++++++++ lib/ace/snippets/lean.js | 7 + lib/ace/snippets/lean.snippets | 0 5 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 lib/ace/mode/lean.js create mode 100644 lib/ace/mode/lean_highlight_rules.js create mode 100644 lib/ace/snippets/lean.js create mode 100644 lib/ace/snippets/lean.snippets diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index 69aa8972..fba3a245 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -99,6 +99,7 @@ var supportedModes = { JSX: ["jsx"], Julia: ["jl"], LaTeX: ["tex|latex|ltx|bib"], + Lean: ["lean|hlean"], LESS: ["less"], Liquid: ["liquid"], Lisp: ["lisp"], @@ -192,4 +193,3 @@ module.exports = { }; }); - diff --git a/lib/ace/mode/lean.js b/lib/ace/mode/lean.js new file mode 100644 index 00000000..e421f2b5 --- /dev/null +++ b/lib/ace/mode/lean.js @@ -0,0 +1,101 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var leanHighlightRules = require("./lean_highlight_rules").leanHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var Range = require("../range").Range; +// TODO(soonhok): figure out behavior and foldmode +// var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; +// var CStyleFoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + this.HighlightRules = leanHighlightRules; + + this.$outdent = new MatchingBraceOutdent(); + // this.$behaviour = new CstyleBehaviour(); + // this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.lineCommentStart = "--"; + this.blockComment = {start: "/-", end: "-/"}; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + var tokenizedLine = this.getTokenizer().getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + var endState = tokenizedLine.state; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start") { + var match = line.match(/^.*[\{\(\[]\s*$/); + if (match) { + indent += tab; + } + } else if (state == "doc-start") { + if (endState == "start") { + return ""; + } + var match = line.match(/^\s*(\/?)\*/); + if (match) { + if (match[1]) { + indent += " "; + } + indent += "- "; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.$id = "ace/mode/lean"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); diff --git a/lib/ace/mode/lean_highlight_rules.js b/lib/ace/mode/lean_highlight_rules.js new file mode 100644 index 00000000..d5f9a67c --- /dev/null +++ b/lib/ace/mode/lean_highlight_rules.js @@ -0,0 +1,224 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules; +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var leanHighlightRules = function() { + + var keywordControls = ( + ["import", "tactic_hint", "protected", "find_decl", + "private", "opaque", "definition", "renaming", "hiding", "exposing", + "parameter", "parameters", "begin", "proof", "qed", "conjecture", "premise", "premises", + "constant", "constants", "example", "attribute", "local", + "hypothesis", "lemma", "corollary", "variable", "variables", "print", + "theorem", "context", "open", "as", "export", "axiom", "inductive", + "with", "structure", "record", "universe", "universes", "alias", "help", "environment", + "options", "precedence", "postfix", "prefix", "calc_trans", + "calc_subst", "calc_refl", "infix", "infixl", "infixr", "notation", + "eval", "check", "exit", "end", "using", "namespace", + "section", "set_option", "omit", "classes", "instances", "coercions", "raw", + "add_rewrite", "extends", "calc", "have", "obtains", "show", "by", "in", "let", + "forall", "fun", "exists", "if", "then", "else", "assume", "match", + "take", "obtain", "from", "axioms", "fields"].join("|") + ); + + var storageType = ( + ["Prop", "Type", "Type'", "Type₊", "Type₁", "Type₂", "Type₃"].join("|") + ); + + var storageModifiers = ( + "\\[(" + + ["persistent", "notation", "parsing-only", "visible", "instance", "class", "prefix", "axioms", "fields", + "multiple-instances", "classes", "instances", "coercions", "options", "trust", + "coercion", "reducible", "irreducible", "raw"].join("|") + + ")\\]" + ); + + var keywordOperators = ( + [].join("|") + ); + + var builtinConstants = ( + "NULL|true|false|TRUE|FALSE" + ); + + var keywordMapper = this.$keywords = this.createKeywordMapper({ + "keyword.control" : keywordControls, + "storage.type" : storageType, + "keyword.operator" : keywordOperators, + "variable.language": "sorry", + "constant.language": builtinConstants + }, "identifier"); + + var identifierRe = "[A-Za-z_\u03b1-\u03ba\u03bc-\u03fb\u1f00-\u1ffe\u2100-\u214f][A-Za-z0-9_'\u03b1-\u03ba\u03bc-\u03fb\u1f00-\u1ffe\u2070-\u2079\u207f-\u2089\u2090-\u209c\u2100-\u214f]*"; + var operatorRe = new RegExp(["#", "@", "->", "∼", "↔", "/", "==", "=", ":=", "<->", + "/\\", "\\/", "∧", "∨", "≠", "<", ">", "≤", "≥", "¬", + "<=", ">=", "⁻¹", "⬝", "▸", "\\+", "\\*", "-", "/", + "λ", "→", "∃", "∀", ":="].join("|")); + // regexp must not have capturing parentheses. Use (?:) instead. + // regexps are ordered -> the first match is used + + this.$rules = { + "start" : [ + { + token : "comment", // single line comment "--" + regex : "--.*$" + }, + DocCommentHighlightRules.getStartRule("doc-start"), + { + token : "comment", // multi line comment "/-" + regex : "\\/-", + next : "comment" + }, { + token : "string", // single line + regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + }, { + token : "string", // multi line string start + regex : '["].*\\\\$', + next : "qqstring" + }, { + token : "string", // single line + regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" + }, { + token : "string", // multi line string start + regex : "['].*\\\\$", + next : "qstring" + }, { + token : "constant.numeric", // hex + regex : "0[xX][0-9a-fA-F]+(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b" + }, { + token : "constant.numeric", // float + regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b" + }, { + token : "storage.modifier", + regex : storageModifiers + }, { + token : "keyword", // pre-compiler directives + regex : "#\\s*(?:include|import|pragma|line|define|undef|if|ifdef|else|elif|ifndef)\\b", + next : "directive" + }, { + token : "keyword", // special case pre-compiler directive + regex : "(?:#\\s*endif)\\b" + }, { + token : keywordMapper, + regex : identifierRe + }, { + token : "operator", + regex : operatorRe + }, { + token : "punctuation.operator", + regex : "\\?|\\:|\\,|\\;|\\." + }, { + token : "paren.lparen", + regex : "[[({]" + }, { + token : "paren.rparen", + regex : "[\\])}]" + }, { + token : "text", + regex : "\\s+" + } + ], + "comment" : [ + { + token : "comment", // closing comment + regex : ".*?-\\/", + next : "start" + }, { + token : "comment", // comment spanning whole line + regex : ".+" + } + ], + "qqstring" : [ + { + token : "string", + regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"', + next : "start" + }, { + token : "string", + regex : '.+' + } + ], + "qstring" : [ + { + token : "string", + regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'", + next : "start" + }, { + token : "string", + regex : '.+' + } + ], + "directive" : [ + { + token : "constant.other.multiline", + regex : /\\/ + }, + { + token : "constant.other.multiline", + regex : /.*\\/ + }, + { + token : "constant.other", + regex : "\\s*<.+?>", + next : "start" + }, + { + token : "constant.other", // single line + regex : '\\s*["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]', + next : "start" + }, + { + token : "constant.other", // single line + regex : "\\s*['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']", + next : "start" + }, + // "\" implies multiline, while "/" implies comment + { + token : "constant.other", + regex : /[^\\\/]+/, + next : "start" + } + ] + }; + + this.embedRules(DocCommentHighlightRules, "doc-", + [ DocCommentHighlightRules.getEndRule("start") ]); +}; + +oop.inherits(leanHighlightRules, TextHighlightRules); + +exports.leanHighlightRules = leanHighlightRules; +}); diff --git a/lib/ace/snippets/lean.js b/lib/ace/snippets/lean.js new file mode 100644 index 00000000..a3c01639 --- /dev/null +++ b/lib/ace/snippets/lean.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./lean.snippets"); +exports.scope = "lean"; + +}); diff --git a/lib/ace/snippets/lean.snippets b/lib/ace/snippets/lean.snippets new file mode 100644 index 00000000..e69de29b From 7572a9543e0f09a69f84029f3a2ac576dde1db53 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 24 Feb 2015 18:42:03 +0400 Subject: [PATCH 171/315] update syntax docs --- index.html | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/index.html b/index.html index 9e05ed68..e2440eb1 100644 --- a/index.html +++ b/index.html @@ -470,7 +470,6 @@ var fonts = lang.arrayToMap(
    this.$rules = {
         "start" : [ {
             token : "text",
    -        merge : true,
             regex : "<\\!\\[CDATA\\[",
             next : "cdata"
         },
    @@ -480,13 +479,7 @@ var fonts = lang.arrayToMap(
             regex : "\\]\\]>",
             next : "start"
         }, {
    -        token : "text",
    -        merge : true,
    -        regex : "\\s+"
    -    }, {
    -        token : "text",
    -        merge : true,
    -        regex : ".+"
    +        defaultToken : "text"
         } ]
     };

    In this extremly short sample, we're defining some highlighting rules for when Ace detectes a <![CDATA tag. When one is encountered, the tokenizer moves from start into the cdata state. It remains there, applying the text token to any string it encounters. Finally, when it hits a closing ]> symbol, it returns to the start state and continues to tokenize anything else.

    From 5ce334e930f8c2f97e45993ed7ac10baf43da2cb Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 24 Feb 2015 18:49:59 +0400 Subject: [PATCH 172/315] update CONTRIBUTING.md --- CONTRIBUTING.md | 15 ++++----------- doc/Contributor_License_Agreement-v2.pdf | Bin 89761 -> 0 bytes ...porate_Contributor_License_Agreement-v2.pdf | Bin 376398 -> 0 bytes 3 files changed, 4 insertions(+), 11 deletions(-) delete mode 100644 doc/Contributor_License_Agreement-v2.pdf delete mode 100644 doc/Corporate_Contributor_License_Agreement-v2.pdf diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c44edcb0..062af59c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,16 +7,9 @@ Feel free to fork and improve/enhance Ace any way you want. If you feel that the There are two versions of the agreement: -1. [The Individual CLA](https://github.com/ajaxorg/ace/raw/master/doc/Contributor_License_Agreement-v2.pdf): use this version if you're working on an ajax.org in your spare time, or can clearly claim ownership of copyright in what you'll be submitting. -2. [The Corporate CLA](https://github.com/ajaxorg/ace/raw/master/doc/Corporate_Contributor_License_Agreement-v2.pdf): have your corporate lawyer review and submit this if your company is going to be contributing to ajax.org projects +1. [The Individual CLA](https://docs.google.com/a/c9.io/forms/d/1MfmfrxqD_PNlNsuK0lC2KSelRLxGLGfh_wEcG0ijVvo/viewform): use this version if you're working on the Cloud9 SDK or open source projects in your spare time, or can clearly claim ownership of copyright in what you'll be submitting. +2. [The Corporate CLA](https://docs.google.com/a/c9.io/forms/d/1vFejn4111GdnCNuQ6BfnJDaxdsUEMD4KCo1ayovAfu0/viewform): have your corporate lawyer review and submit this if your company is going to be contributing to the Cloud9 SDK and/or open source projects. -If you want to contribute to an ajax.org project please print the CLA and fill it out and sign it. Then either send it by snail mail or fax to us or send it back scanned (or as a photo) by email. +If you want to contribute to the Cloud9 SDK and/or open source projects please go to the online form, fill it out and submit it. -Email: ace+cla@c9.io - -Fax: +31 (0) 206388953 - -Address: Ajax.org B.V. - Keizersgracht 241 - 1016 EA, Amsterdam - the Netherlands \ No newline at end of file +Happy coding, Cloud9 diff --git a/doc/Contributor_License_Agreement-v2.pdf b/doc/Contributor_License_Agreement-v2.pdf deleted file mode 100644 index 1c4baa870a07e67cffbbc63ac897c57a0d1ca44b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89761 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

    M;`=Vk&NS|}T3~YZ}xH5?<?dH?gt0B?qUk6# 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


    1wW7;3||sc1?0IL%t=DIFzp@>c@>ItW*nzoru6P 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 WIsu2*UmGv%=43&lq!g7GL;8Q((E}&| diff --git a/doc/Corporate_Contributor_License_Agreement-v2.pdf b/doc/Corporate_Contributor_License_Agreement-v2.pdf deleted file mode 100644 index dbeaf37cc5dea9f57f673a748c97486ec62fd870..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 376398 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%0AY3il;Q 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 + + + + + + +

      + +
      + + + \ No newline at end of file diff --git a/lib/ace/lib/event.js b/lib/ace/lib/event.js index 16805ce2..57924056 100644 --- a/lib/ace/lib/event.js +++ b/lib/ace/lib/event.js @@ -326,13 +326,14 @@ exports.addCommandKeyListener = function(el, callback) { }); if (!pressedKeys) { - pressedKeys = Object.create(null); - addListener(window, "focus", function(e) { - pressedKeys = Object.create(null); - }); + resetPressedKeys(); + addListener(window, "focus", resetPressedKeys); } } }; +function resetPressedKeys(e) { + pressedKeys = Object.create(null); +} if (window.postMessage && !useragent.isOldIE) { var postMessageId = 1; From 3ce8d76c8943ad424e1821819e48fffd60768ac5 Mon Sep 17 00:00:00 2001 From: Phill Campbell Date: Mon, 27 Apr 2015 18:49:12 +0100 Subject: [PATCH 284/315] Expose ClipboardEvent in editor paste event --- lib/ace/editor.js | 4 ++-- lib/ace/keyboard/textinput.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index f00f74f6..19d4b84e 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -920,12 +920,12 @@ var Editor = function(renderer, session) { * * **/ - this.onPaste = function(text) { + this.onPaste = function(text, event) { // todo this should change when paste becomes a command if (this.$readOnly) return; - var e = {text: text}; + var e = {text: text, event: event}; this._signal("paste", e); text = e.text; if (!this.inMultiSelectMode || this.inVirtualSelectionMode) { diff --git a/lib/ace/keyboard/textinput.js b/lib/ace/keyboard/textinput.js index 0bd57eed..4a2bb72c 100644 --- a/lib/ace/keyboard/textinput.js +++ b/lib/ace/keyboard/textinput.js @@ -306,7 +306,7 @@ var TextInput = function(parentNode, host) { var data = handleClipboardData(e); if (typeof data == "string") { if (data) - host.onPaste(data); + host.onPaste(data, e); if (useragent.isIE) setTimeout(resetSelection); event.preventDefault(e); From d080fe51d4433c9217bc40acbbc5876843254e7a Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 28 Apr 2015 19:01:24 +0400 Subject: [PATCH 285/315] fix #2468 error in strict mode --- lib/ace/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/config.js b/lib/ace/config.js index 34bf50fd..fe9312fd 100644 --- a/lib/ace/config.js +++ b/lib/ace/config.js @@ -39,7 +39,7 @@ var AppConfig = require("./lib/app_config").AppConfig; module.exports = exports = new AppConfig(); var global = (function() { - return this; + return this || typeof window != "undefined" && window; })(); var options = { From e72f1d833751756fdb237a35ff0a9549487bf0bf Mon Sep 17 00:00:00 2001 From: Alex Gilding Date: Tue, 28 Apr 2015 20:24:13 +0100 Subject: [PATCH 286/315] Add indentation for Scheme Just copied over the Clojure indentation rules to Scheme and changed the keywords to suit the language, so that Scheme programs can be automatically indented too --- lib/ace/mode/scheme.js | 77 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/lib/ace/mode/scheme.js b/lib/ace/mode/scheme.js index aa462a10..2360b3da 100644 --- a/lib/ace/mode/scheme.js +++ b/lib/ace/mode/scheme.js @@ -39,15 +39,92 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; var SchemeHighlightRules = require("./scheme_highlight_rules").SchemeHighlightRules; +var MatchingParensOutdent = require("./matching_parens_outdent").MatchingParensOutdent; var Mode = function() { this.HighlightRules = SchemeHighlightRules; + this.$outdent = new MatchingParensOutdent(); }; oop.inherits(Mode, TextMode); (function() { this.lineCommentStart = ";"; + this.minorIndentFunctions = ["define", "lambda", "define-macro", "define-syntax", "syntax-rules", "define-record-type", "define-structure"]; + + this.$toIndent = function(str) { + return str.split('').map(function(ch) { + if (/\s/.exec(ch)) { + return ch; + } else { + return ' '; + } + }).join(''); + }; + + this.$calculateIndent = function(line, tab) { + var baseIndent = this.$getIndent(line); + var delta = 0; + var isParen, ch; + // Walk back from end of line, find matching braces + for (var i = line.length - 1; i >= 0; i--) { + ch = line[i]; + if (ch === '(') { + delta--; + isParen = true; + } else if (ch === '(' || ch === '[' || ch === '{') { + delta--; + isParen = false; + } else if (ch === ')' || ch === ']' || ch === '}') { + delta++; + } + if (delta < 0) { + break; + } + } + if (delta < 0 && isParen) { + // Were more brackets opened than closed and was a ( left open? + i += 1; + var iBefore = i; + var fn = ''; + while (true) { + ch = line[i]; + if (ch === ' ' || ch === '\t') { + if(this.minorIndentFunctions.indexOf(fn) !== -1) { + return this.$toIndent(line.substring(0, iBefore - 1) + tab); + } else { + return this.$toIndent(line.substring(0, i + 1)); + } + } else if (ch === undefined) { + return this.$toIndent(line.substring(0, iBefore - 1) + tab); + } + fn += line[i]; + i++; + } + } else if(delta < 0 && !isParen) { + // Were more brackets openend than closed and was it not a (? + return this.$toIndent(line.substring(0, i+1)); + } else if(delta > 0) { + // Mere more brackets closed than opened? Outdent. + baseIndent = baseIndent.substring(0, baseIndent.length - tab.length); + return baseIndent; + } else { + // Were they nicely matched? Just indent like line before. + return baseIndent; + } + }; + + this.getNextLineIndent = function(state, line, tab) { + return this.$calculateIndent(line, tab); + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; this.$id = "ace/mode/scheme"; }).call(Mode.prototype); From a61d304cbb348432fa3c71099ffa3809ccabd3ee Mon Sep 17 00:00:00 2001 From: Brian Jordan Date: Thu, 30 Apr 2015 17:14:16 -0700 Subject: [PATCH 287/315] Remove unused variable `EditSession` --- lib/ace/autocomplete/popup.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/ace/autocomplete/popup.js b/lib/ace/autocomplete/popup.js index a151c746..ead0c47c 100644 --- a/lib/ace/autocomplete/popup.js +++ b/lib/ace/autocomplete/popup.js @@ -31,7 +31,6 @@ define(function(require, exports, module) { "use strict"; -var EditSession = require("../edit_session").EditSession; var Renderer = require("../virtual_renderer").VirtualRenderer; var Editor = require("../editor").Editor; var Range = require("../range").Range; From cd8099b0ad952c916f512b2309d82920da388103 Mon Sep 17 00:00:00 2001 From: Brian Jordan Date: Thu, 30 Apr 2015 17:38:19 -0700 Subject: [PATCH 288/315] Remove unused parameter `mutateData` & add ;s --- lib/ace/autocomplete.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index 7e5674ae..d3b41b65 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -142,7 +142,7 @@ var Autocomplete = function() { // we have to check if activeElement is a child of popup because // on IE preventDefault doesn't stop scrollbar from being focussed var el = document.activeElement; - var text = this.editor.textInput.getElement() + var text = this.editor.textInput.getElement(); if (el != text && ( !this.popup || el.parentNode != this.popup.container ) && el != this.tooltipNode && e.relatedTarget != this.tooltipNode && e.relatedTarget != text @@ -349,7 +349,7 @@ var Autocomplete = function() { doc = selected; if (typeof doc == "string") - doc = {docText: doc} + doc = {docText: doc}; if (!doc || !(doc.docHTML || doc.docText)) return this.hideDocTooltip(); this.showDocTooltip(doc); @@ -416,7 +416,7 @@ Autocomplete.startCommand = { bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space" }; -var FilteredList = function(array, filterText, mutateData) { +var FilteredList = function(array, filterText) { this.all = array; this.filtered = array; this.filterText = filterText || ""; From ad22b71cfe9293dda3fe1c689299d08580f29441 Mon Sep 17 00:00:00 2001 From: Brian Jordan Date: Fri, 1 May 2015 10:56:08 -0700 Subject: [PATCH 289/315] Update comment, add missing semicolon [ci skip] --- lib/ace/edit_session.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 3e941375..7296dc34 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -151,7 +151,7 @@ var EditSession = function(text, mode) { this.$foldData = []; this.$foldData.toString = function() { return this.join("\n"); - } + }; this.on("changeFold", this.onChangeFold.bind(this)); this.$onChange = this.onChange.bind(this); @@ -679,10 +679,10 @@ var EditSession = function(text, mode) { }; /** - * Returns an array containing the IDs of all the markers, either front or back. + * Returns an object containing the all of the markers, either front or back. * @param {Boolean} inFront If `true`, indicates you only want front markers; `false` indicates only back markers * - * @returns {Array} + * @returns {Object} **/ this.getMarkers = function(inFront) { return inFront ? this.$frontMarkers : this.$backMarkers; From 9323a2616b07d97d2288d1aecd55791b8866b9d9 Mon Sep 17 00:00:00 2001 From: Joey Payne Date: Mon, 4 May 2015 22:54:09 -0600 Subject: [PATCH 290/315] Added support for nim programming language. --- lib/ace/ext/modelist.js | 1 + lib/ace/ext/themelist.js | 1 + lib/ace/mode/nim.js | 113 ++++++++++ lib/ace/mode/nim_highlight_rules.js | 238 +++++++++++++++++++++ lib/ace/snippets/mask.js | 7 + lib/ace/snippets/mask.snippets | 0 lib/ace/snippets/nim.js | 7 + lib/ace/snippets/nim.snippets | 130 +++++++++++ lib/ace/theme/the_night_after_tomorrow.css | 139 ++++++++++++ lib/ace/theme/the_night_after_tomorrow.js | 39 ++++ 10 files changed, 675 insertions(+) create mode 100644 lib/ace/mode/nim.js create mode 100644 lib/ace/mode/nim_highlight_rules.js create mode 100644 lib/ace/snippets/mask.js create mode 100644 lib/ace/snippets/mask.snippets create mode 100644 lib/ace/snippets/nim.js create mode 100644 lib/ace/snippets/nim.snippets create mode 100644 lib/ace/theme/the_night_after_tomorrow.css create mode 100644 lib/ace/theme/the_night_after_tomorrow.js diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index 7a5a1e9c..5ab899a5 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -117,6 +117,7 @@ var supportedModes = { MUSHCode: ["mc|mush"], MySQL: ["mysql"], Nix: ["nix"], + Nim: ["nim"], ObjectiveC: ["m|mm"], OCaml: ["ml|mli"], Pascal: ["pas|p"], diff --git a/lib/ace/ext/themelist.js b/lib/ace/ext/themelist.js index 2350a2e2..0df76b02 100644 --- a/lib/ace/ext/themelist.js +++ b/lib/ace/ext/themelist.js @@ -73,6 +73,7 @@ var themeData = [ ["Solarized Dark" ,"solarized_dark" , "dark"], ["Terminal" ,"terminal" , "dark"], ["Tomorrow Night" ,"tomorrow_night" , "dark"], + ["The Night After Tomorrow" ,"the_night_after_tomorrow" , "dark"], ["Tomorrow Night Blue" ,"tomorrow_night_blue" , "dark"], ["Tomorrow Night Bright","tomorrow_night_bright" , "dark"], ["Tomorrow Night 80s" ,"tomorrow_night_eighties" , "dark"], diff --git a/lib/ace/mode/nim.js b/lib/ace/mode/nim.js new file mode 100644 index 00000000..cbf48ef2 --- /dev/null +++ b/lib/ace/mode/nim.js @@ -0,0 +1,113 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var NimHighlightRules = require("./nim_highlight_rules").NimHighlightRules; +var NimFoldMode = require("./folding/pythonic").FoldMode; +var Range = require("../range").Range; + +var Mode = function() { + this.HighlightRules = NimHighlightRules; + this.foldingRules = new NimFoldMode("\\:|="); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.lineCommentStart = "#"; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + var tokenizedLine = this.getTokenizer().getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start") { + var match = line.match(/^.*[\{\(\[\:=]\s*$/); + if (match) { + indent += tab; + } + } + + return indent; + }; + + var outdents = { + "discard": 1, + "return": 1, + "raise": 1, + "break": 1, + "continue": 1 + }; + + this.checkOutdent = function(state, line, input) { + if (input !== "\r\n" && input !== "\r" && input !== "\n") + return false; + + var tokens = this.getTokenizer().getLineTokens(line.trim(), state).tokens; + + if (!tokens) + return false; + + // ignore trailing comments + do { + var last = tokens.pop(); + } while (last && (last.type == "comment" || (last.type == "text" && last.value.match(/^\s+$/)))); + + if (!last) + return false; + + return (last.type == "keyword" && outdents[last.value]); + }; + + this.autoOutdent = function(state, doc, row) { + // outdenting in python is slightly different because it always applies + // to the next line and only of a new line is inserted + + row += 1; + var indent = this.$getIndent(doc.getLine(row)); + var tab = doc.getTabString(); + if (indent.slice(-tab.length) == tab) + doc.remove(new Range(row, indent.length-tab.length, row, indent.length)); + }; + + this.$id = "ace/mode/nim"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); diff --git a/lib/ace/mode/nim_highlight_rules.js b/lib/ace/mode/nim_highlight_rules.js new file mode 100644 index 00000000..e762a636 --- /dev/null +++ b/lib/ace/mode/nim_highlight_rules.js @@ -0,0 +1,238 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ +/* + * TODO: nim delimiters + */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; +var num_suffix = "(\'[Ff]32|\'[Ff]64|\'[IiUu]8|\'[IiUu]16|\'[IiUu]32|\'[IiUu]64)"; + +var NimHighlightRules = function() { + + var keywords = ( + "addr|and|as|asm|atomic|bind|block|break|case|cast|const|continue|" + + "converter|defer|discard|distinct|div|do|elif|else|end|enum|except|" + + "export|finally|for|from|func|generic|if|import|in|include|interface|" + + "is|isnot|iterator|let|macro|method|mixin|mod|nil|not|notin|object|of|" + + "or|out|proc|ptr|raise|ref|return|shl|shr|static|template|try|tuple|" + + "type|using|var|when|while|with|without|xor|yield" + ); + + var builtinConstants = ( + "true|false|nil|NotImplemented|Ellipsis" + ); + + var storageType = ( + "string|seq|array|expr|stmt|typed|untyped|any|auto|bool|cdouble|cfloat|"+ + "cchar|clongdouble|clong|clonglong|cshort|csize|cstring|cstringarray|"+ + "culong|culonglong|cushort|guarded|natural|openarray|ordinal|pointer|"+ + "range|set|shared|static|typedesc|varargs|void" + ); + + var builtinFunctions = ( + "defined|declared|declaredInScope|echo|$" + ); + + //var futureReserved = ""; + var keywordMapper = this.createKeywordMapper({ + "invalid.deprecated": "debugger", + "support.function": builtinFunctions, + //"invalid.illegal": futureReserved, + "constant.language": builtinConstants, + "storage.type" : storageType, + "keyword": keywords + }, "identifier"); + + var strPre = "(?:r|R)?"; + + var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))"; + var octInteger = "(?:0[o]?[0-7]+)"; + var hexInteger = "(?:0[xX][\\dA-Fa-f]+)"; + var binInteger = "(?:0[bB][01]+)"; + var integer = "(?:" + decimalInteger + "|" + octInteger + "|" + hexInteger + "|" + binInteger + ")"; + + var exponent = "(?:[eE][+-]?\\d+)"; + var fraction = "(?:\\.\\d+)"; + var intPart = "(?:\\d+)"; + var pointFloat = "(?:(?:" + intPart + "?" + fraction + ")|(?:" + intPart + "\\.))"; + var exponentFloat = "(?:(?:" + pointFloat + "|" + intPart + ")" + exponent + ")"; + var floatNumber = "(?:" + exponentFloat + "|" + pointFloat + ")"; + + var stringEscape = "\\\\(x[0-9A-Fa-f]{2}|[0-7]{3}|[\\\\abfnrtv'\"]|U[0-9A-Fa-f]{8}|u[0-9A-Fa-f]{4})"; + + this.$rules = { + "start" : [ { + token : "comment", + regex : "#.*$" + }, { + token : "keyword", + regex : "(proc|method|temdplate|macro|macromethod|converter|func|iterator) ", + next : "qproc_name" + }, { + token : "storage.type", + regex : "(c|cu|u)?int(8|16|32|64)?", + }, { + token : "storage.type", + regex : "(c|cu|u|cs)?char", + }, { + token : "storage.type", + regex : "float(32|64)?", + }, { + token : "docstring", + regex : "##.*$" + }, { + token : "string", // multi line """ string start + regex : strPre + '"{3}', + next : "qqstring3" + }, { + token : "string", // " string + regex : strPre + '"(?=.)', + next : "qqstring" + }, { + token : "string", // multi line ''' string start + regex : strPre + "'{3}", + next : "qstring3" + }, { + token : "backtick", // ` string + regex : strPre + "`(?=.)", + next : "qxstring" + }, { + token : "string", // ' string + regex : strPre + "'(?=.)", + next : "qstring" + }, { + token : "constant.numeric", // imaginary + regex : "(?:" + floatNumber + "|\\d+)[jJ]\\b" + }, { + token : "constant.numeric", // float + regex : floatNumber + }, { + token : "constant.numeric", // long integer + regex : integer + "[lL]\\b" + }, { + token : "constant.numeric", // integer + regex : integer + "\\b" + }, { + token : keywordMapper, + regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b" + }, { + token : "keyword.operator", + regex : "\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|=" + }, { + token : "paren.lparen", + regex : "[\\[\\(\\{]" + }, { + token : "paren.rparen", + regex : "[\\]\\)\\}]" + }, { + token : "text", + regex : "\\s+" + } ], + "qqstring3" : [ { + token : "constant.language.escape", + regex : stringEscape + }, { + token : "string", // multi line """ string end + regex : '"{3}', + next : "start" + }, { + defaultToken : "string" + } ], + "qstring3" : [ { + token : "constant.language.escape", + regex : stringEscape + }, { + token : "string", // multi line ''' string end + regex : "'{3}", + next : "start" + }, { + defaultToken : "string" + } ], + "qqstring" : [{ + token : "constant.language.escape", + regex : stringEscape + }, { + token : "string", + regex : "\\\\$", + next : "qqstring" + }, { + token : "string", + regex : '"|$', + next : "start" + }, { + defaultToken: "string" + }], + "qstring" : [{ + token : "constant.language.escape", + regex : stringEscape + }, { + token : "string", + regex : "\\\\$", + next : "qstring" + }, { + token : "string", + regex : "'|$", + next : "start" + }, { + defaultToken: "string" + }], + "qxstring" : [{ + token : "constant.language.escape", + regex : stringEscape + }, { + token : "backtick", + regex : "\\\\$", + next : "qxstring" + }, { + token : "backtick", + regex : "`|$", + next : "start" + }, { + defaultToken: "backtick" + }], + "qproc_name":[{ + token : "proc_name", + regex : "\\w+", + },{ + token : "start_bracket", + regex : "(\\(|=|$)", + next : "start" + }], + }; +}; + +oop.inherits(NimHighlightRules, TextHighlightRules); + +exports.NimHighlightRules = NimHighlightRules; +}); diff --git a/lib/ace/snippets/mask.js b/lib/ace/snippets/mask.js new file mode 100644 index 00000000..7fbca678 --- /dev/null +++ b/lib/ace/snippets/mask.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./mask.snippets"); +exports.scope = "mask"; + +}); diff --git a/lib/ace/snippets/mask.snippets b/lib/ace/snippets/mask.snippets new file mode 100644 index 00000000..e69de29b diff --git a/lib/ace/snippets/nim.js b/lib/ace/snippets/nim.js new file mode 100644 index 00000000..6e6d02bb --- /dev/null +++ b/lib/ace/snippets/nim.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./nim.snippets"); +exports.scope = "nim"; + +}); diff --git a/lib/ace/snippets/nim.snippets b/lib/ace/snippets/nim.snippets new file mode 100644 index 00000000..a8a20a00 --- /dev/null +++ b/lib/ace/snippets/nim.snippets @@ -0,0 +1,130 @@ +snippet #! + #!/usr/bin/env nim +snippet imp + import ${1:module} +snippet from + from ${1:package} import ${2:module} +# Module Docstring +snippet docs + ## File: ${1:FILENAME:file_name} + ## Author: ${2:author} + ## Description: ${3} +snippet wh + while ${1:condition}: + ${2:# TODO: write code...} +# dowh - does the same as do...while in other languages +snippet dowh + while true: + ${1:# TODO: write code...} + if ${2:condition}: + break +snippet with + with ${1:expr} as ${2:var}: + ${3:# TODO: write code...} +# New Function +snippet proc + proc ${1:fname}(${2:`indent('.') ? 'self' : ''`}): ${3: return type} = + ##${4:docstring for $1} + ${5:# TODO: write code...} +snippet deff + def ${1:fname}(${2:`indent('.') ? 'self' : ''`}): + ${3:# TODO: write code...} +# New Method +snippet defs + def ${1:mname}(self, ${2:arg}): + ${3:# TODO: write code...} +# New Property +snippet property + def ${1:foo}(): + doc = "${2:The $1 property.}" + def fget(self): + ${3:return self._$1} + def fset(self, value): + ${4:self._$1 = value} +# Ifs +snippet if + if ${1:condition}: + ${2:# TODO: write code...} +snippet el + else: + ${1:# TODO: write code...} +snippet ei + elif ${1:condition}: + ${2:# TODO: write code...} +# For +snippet for + for ${1:item} in ${2:items}: + ${3:# TODO: write code...} +# Encodes +snippet cutf8 + # -*- coding: utf-8 -*- +snippet clatin1 + # -*- coding: latin-1 -*- +snippet cascii + # -*- coding: ascii -*- +# Lambda +snippet ld + ${1:var} = lambda ${2:vars} : ${3:action} +snippet . + self. +snippet try Try/Except + try: + ${1:# TODO: write code...} + except ${2:Exception}, ${3:e}: + ${4:raise $3} +snippet try Try/Except/Else + try: + ${1:# TODO: write code...} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + else: + ${5:# TODO: write code...} +snippet try Try/Except/Finally + try: + ${1:# TODO: write code...} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + finally: + ${5:# TODO: write code...} +snippet try Try/Except/Else/Finally + try: + ${1:# TODO: write code...} + except ${2:Exception}, ${3:e}: + ${4:raise $3} + else: + ${5:# TODO: write code...} + finally: + ${6:# TODO: write code...} +# if __name__ == '__main__': +snippet ifmain + if isMainModule: + ${1:main()} +snippet " + ## ${1:doc} +# test function/method +snippet test + def test_${1:description}(${2:self}): + ${3:# TODO: write code...} +# test case +snippet testcase + class ${1:ExampleCase}(unittest.TestCase): + + def test_${2:description}(self): + ${3:# TODO: write code...} +#getopt +snippet getopt + try: + # Short option syntax: "hv:" + # Long option syntax: "help" or "verbose=" + opts, args = getopt.getopt(sys.argv[1:], "${1:short_options}", [${2:long_options}]) + + except getopt.GetoptError, err: + # Print debug info + print str(err) + ${3:error_action} + + for option, argument in opts: + if option in ("-h", "--help"): + ${4} + elif option in ("-v", "--verbose"): + verbose = argument diff --git a/lib/ace/theme/the_night_after_tomorrow.css b/lib/ace/theme/the_night_after_tomorrow.css new file mode 100644 index 00000000..48d2602c --- /dev/null +++ b/lib/ace/theme/the_night_after_tomorrow.css @@ -0,0 +1,139 @@ +.ace-tomorrow-night .ace_gutter { + background: #25282c; + color: #C5C8C6 +} + +.ace-tomorrow-night .ace_print-margin { + width: 1px; + background: #25282c +} + +.ace-tomorrow-night { + background-color: #1D1F21; + color: #C5C8C6 +} + +.ace-tomorrow-night .ace_cursor { + color: #FFFFFF +} + +.ace-tomorrow-night .ace_marker-layer .ace_selection { + background: #373B41 +} + +.ace-tomorrow-night.ace_multiselect .ace_selection.ace_start { + box-shadow: 0 0 3px 0px #1D1F21; + border-radius: 2px +} + +.ace-tomorrow-night .ace_marker-layer .ace_step { + background: rgb(102, 82, 0) +} + +.ace-tomorrow-night .ace_marker-layer .ace_bracket { + margin: -1px 0 0 -1px; + border: 1px solid #4B4E55 +} + +.ace-tomorrow-night .ace_marker-layer .ace_active-line { + background: #282A2E +} + +.ace-tomorrow-night .ace_gutter-active-line { + background-color: #282A2E +} + +.ace-tomorrow-night .ace_marker-layer .ace_selected-word { + border: 1px solid #373B41 +} + +.ace-tomorrow-night .ace_invisible { + color: #4B4E55 +} + +.ace-tomorrow-night .ace_keyword, +.ace-tomorrow-night .ace_meta, +.ace-tomorrow-night .ace_support.ace_type { + color: #C4A400 +} + +.ace-tomorrow-night .ace_storage, +.ace-tomorrow-night .ace_storage.ace_type { + color: #327FD7 +} + +.ace-tomorrow-night .ace_keyword.ace_operator { + color: #8ABEB7 +} + +.ace-tomorrow-night .ace_constant.ace_language{ + color: #934B9F +} + +.ace-tomorrow-night .ace_constant.ace_character, +.ace-tomorrow-night .ace_constant.ace_numeric, +.ace-tomorrow-night .ace_keyword.ace_other.ace_unit, +.ace-tomorrow-night .ace_support.ace_constant, +.ace-tomorrow-night .ace_variable.ace_parameter { + color: #37BC9B +} + +.ace-tomorrow-night .ace_constant.ace_other { + color: #CED1CF +} + +.ace-tomorrow-night .ace_invalid { + color: #CED2CF; + background-color: #DF5F5F +} + +.ace-tomorrow-night .ace_invalid.ace_deprecated { + color: #CED2CF; + background-color: #B798BF +} + +.ace-tomorrow-night .ace_fold { + background-color: #62A5D6; + border-color: #C5C8C6 +} + +.ace-tomorrow-night .ace_entity.ace_name.ace_function, +.ace-tomorrow-night .ace_support.ace_function, +.ace-tomorrow-night .ace_variable { + color: #62A5D6 +} + +.ace-tomorrow-night .ace_support.ace_class, +.ace-tomorrow-night .ace_support.ace_type { + color: #F0C674 +} + +.ace-tomorrow-night .ace_heading, +.ace-tomorrow-night .ace_markup.ace_heading, +.ace-tomorrow-night .ace_string { + color: #CD0000 +} + +.ace-tomorrow-night .ace_proc_name { + color: #04939A +} + +.ace-tomorrow-night .ace_backtick { + color: #1DAA49 +} + +.ace-tomorrow-night .ace_entity.ace_name.ace_tag, +.ace-tomorrow-night .ace_entity.ace_other.ace_attribute-name, +.ace-tomorrow-night .ace_meta.ace_tag, +.ace-tomorrow-night .ace_string.ace_regexp, +.ace-tomorrow-night .ace_variable { + color: #FFFFFF +} + +.ace-tomorrow-night .ace_comment { + color: #3465A4 +} + +.ace-tomorrow-night .ace_indent-guide { + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHB3d/8PAAOIAdULw8qMAAAAAElFTkSuQmCC) right repeat-y +} diff --git a/lib/ace/theme/the_night_after_tomorrow.js b/lib/ace/theme/the_night_after_tomorrow.js new file mode 100644 index 00000000..3108e2a9 --- /dev/null +++ b/lib/ace/theme/the_night_after_tomorrow.js @@ -0,0 +1,39 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-tomorrow-night"; +exports.cssText = require("../requirejs/text!./the_night_after_tomorrow.css"); + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); From ef4537a09981f142b11a79b47c6e242e04bd2a80 Mon Sep 17 00:00:00 2001 From: Brian Jordan Date: Tue, 5 May 2015 09:07:46 -0700 Subject: [PATCH 291/315] Update edit_session.js Fix extra `the` --- lib/ace/edit_session.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 7296dc34..f9b43a76 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -679,7 +679,7 @@ var EditSession = function(text, mode) { }; /** - * Returns an object containing the all of the markers, either front or back. + * Returns an object containing all of the markers, either front or back. * @param {Boolean} inFront If `true`, indicates you only want front markers; `false` indicates only back markers * * @returns {Object} From 0abd9ec30e4bc6225cb01b62e34cc5ba1fd23b1f Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 11 Oct 2014 02:38:06 +0400 Subject: [PATCH 292/315] rounded corners for selections --- lib/ace/css/editor.css | 27 ++++++++++++ lib/ace/layer/marker.js | 51 ++++++++++++----------- lib/ace/theme/clouds.css | 1 - lib/ace/theme/clouds_midnight.css | 1 - lib/ace/theme/cobalt.css | 1 - lib/ace/theme/dawn.css | 1 - lib/ace/theme/idle_fingers.css | 1 - lib/ace/theme/katzenmilch.css | 1 - lib/ace/theme/kr_theme.css | 1 - lib/ace/theme/merbivore.css | 1 - lib/ace/theme/merbivore_soft.css | 1 - lib/ace/theme/mono_industrial.css | 1 - lib/ace/theme/monokai.css | 1 - lib/ace/theme/pastel_on_dark.css | 1 - lib/ace/theme/solarized_dark.css | 1 - lib/ace/theme/solarized_light.css | 1 - lib/ace/theme/terminal.css | 1 - lib/ace/theme/textmate.css | 1 - lib/ace/theme/tomorrow.css | 1 - lib/ace/theme/tomorrow_night.css | 1 - lib/ace/theme/tomorrow_night_blue.css | 1 - lib/ace/theme/tomorrow_night_bright.css | 1 - lib/ace/theme/tomorrow_night_eighties.css | 1 - lib/ace/theme/twilight.css | 1 - lib/ace/theme/vibrant_ink.css | 1 - lib/ace/theme/xcode.css | 1 - 26 files changed, 54 insertions(+), 48 deletions(-) diff --git a/lib/ace/css/editor.css b/lib/ace/css/editor.css index cef995c8..87eb67b3 100644 --- a/lib/ace/css/editor.css +++ b/lib/ace/css/editor.css @@ -422,3 +422,30 @@ position: absolute; z-index: 8; } + +/* +styles = [] +for (var i = 1; i < 16; i++) { + styles.push(".ace_br" + i + "{" + ( + ["top-left", "top-right", "bottom-right", "bottom-left"] + ).map(function(x, j) { + return i & (1< next, row == end), + layerConfig, row == end ? 0 : 1, extraStyle); } }; @@ -136,7 +137,7 @@ var Marker = function(parentEl) { extraStyle = extraStyle || ""; stringBuilder.push( - "
      Date: Wed, 20 May 2015 19:48:01 +0400 Subject: [PATCH 299/315] update changelog --- ChangeLog.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index e9c41e4c..3077d171 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,5 +1,16 @@ +Version 1.2.0-pre + +* New Features + - Indented soft wrap (danyaPostfactum) + +* API Changes + - unified delta types `{start, end, action, lines}` (Alden Daniels https://github.com/ajaxorg/ace/pull/1745) + - "change" event listeners on session and editor get delta objects directly + 2015.04.03 Version 1.1.9 + - Small Enhancements and Bugfixes + 2014.11.08 Version 1.1.8 * API Changes From fe96eef206b15b88f6bd8d6364b3980ede970472 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 10 Mar 2015 20:14:36 +0400 Subject: [PATCH 300/315] fix require for paths ending with .js in the worker --- lib/ace/worker/worker.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ace/worker/worker.js b/lib/ace/worker/worker.js index 928000dd..7a047584 100644 --- a/lib/ace/worker/worker.js +++ b/lib/ace/worker/worker.js @@ -69,7 +69,8 @@ window.require = function(parentId, id) { if (!window.require.tlns) return console.log("unable to load " + id); chunks[0] = window.require.tlns[chunks[0]] || chunks[0]; - var path = chunks.join("/") + ".js"; + var path = chunks.join("/"); + if (path.slice(-3) != ".js") path += ".js"; window.require.id = id; importScripts(path); From af5c7a9c3b44da1a64517bd8d5e4a07df32d20ba Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 22 May 2015 02:34:30 +0400 Subject: [PATCH 301/315] improve require support in worker --- lib/ace/worker/worker.js | 83 +++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/lib/ace/worker/worker.js b/lib/ace/worker/worker.js index 7a047584..28fc0fe2 100644 --- a/lib/ace/worker/worker.js +++ b/lib/ace/worker/worker.js @@ -1,8 +1,9 @@ "no use strict"; ;(function(window) { -if (typeof window.window != "undefined" && window.document) { +if (typeof window.window != "undefined" && window.document) + return; +if (window.require && window.define) return; -} window.console = function() { var msgs = Array.prototype.slice.call(arguments, 0); @@ -19,6 +20,7 @@ window.ace = window; window.onerror = function(message, file, line, col, err) { postMessage({type: "error", data: { message: message, + data: err.data, file: file, line: line, col: col, @@ -37,7 +39,7 @@ window.normalizeModule = function(parentId, moduleName) { var base = parentId.split("/").slice(0, -1).join("/"); moduleName = (base ? base + "/" : "") + moduleName; - while(moduleName.indexOf(".") !== -1 && previous != moduleName) { + while (moduleName.indexOf(".") !== -1 && previous != moduleName) { var previous = moduleName; moduleName = moduleName.replace(/^\.\//, "").replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); } @@ -46,7 +48,7 @@ window.normalizeModule = function(parentId, moduleName) { return moduleName; }; -window.require = function(parentId, id) { +window.require = function require(parentId, id) { if (!id) { id = parentId; parentId = null; @@ -64,18 +66,36 @@ window.require = function(parentId, id) { } return module.exports; } - - var chunks = id.split("/"); + if (!window.require.tlns) return console.log("unable to load " + id); - chunks[0] = window.require.tlns[chunks[0]] || chunks[0]; - var path = chunks.join("/"); + + var path = resolveModuleId(id, window.require.tlns); if (path.slice(-3) != ".js") path += ".js"; window.require.id = id; + window.require.modules[id] = {}; // prevent infinite loop on broken modules importScripts(path); return window.require(parentId, id); }; +function resolveModuleId(id, paths) { + var testPath = id, tail = ""; + while (testPath) { + var alias = paths[testPath]; + if (typeof alias == "string") { + return alias + tail; + } else if (alias) { + return alias.location.replace(/\/*$/, "/") + (tail || alias.main || alias.name); + } else if (alias === false) { + return ""; + } + var i = testPath.lastIndexOf("/"); + if (i === -1) break; + tail = testPath.substr(i) + tail; + testPath = testPath.slice(0, i); + } + return id; +} window.require.modules = {}; window.require.tlns = {}; @@ -101,9 +121,9 @@ window.define = function(id, deps, factory) { } if (!deps.length) - // If there is no dependencies, we inject 'require', 'exports' and - // 'module' as dependencies, to provide CommonJS compatibility. - deps = ['require', 'exports', 'module']; + // If there is no dependencies, we inject "require", "exports" and + // "module" as dependencies, to provide CommonJS compatibility. + deps = ["require", "exports", "module"]; var req = function(childId) { return window.require(id, childId); @@ -114,16 +134,16 @@ window.define = function(id, deps, factory) { factory: function() { var module = this; var returnExports = factory.apply(this, deps.map(function(dep) { - switch(dep) { - // Because 'require', 'exports' and 'module' aren't actual - // dependencies, we must handle them seperately. - case 'require': return req; - case 'exports': return module.exports; - case 'module': return module; - // But for all other dependencies, we can just go ahead and - // require them. - default: return req(dep); - } + switch (dep) { + // Because "require", "exports" and "module" aren't actual + // dependencies, we must handle them seperately. + case "require": return req; + case "exports": return module.exports; + case "module": return module; + // But for all other dependencies, we can just go ahead and + // require them. + default: return req(dep); + } })); if (returnExports) module.exports = returnExports; @@ -132,9 +152,10 @@ window.define = function(id, deps, factory) { }; }; window.define.amd = {}; - +require.tlns = {}; window.initBaseUrls = function initBaseUrls(topLevelNamespaces) { - require.tlns = topLevelNamespaces; + for (var i in topLevelNamespaces) + require.tlns[i] = topLevelNamespaces[i]; }; window.initSender = function initSender() { @@ -174,21 +195,23 @@ var sender = window.sender = null; window.onmessage = function(e) { var msg = e.data; - if (msg.command) { + if (msg.event && sender) { + sender._signal(msg.event, msg.data); + } + else if (msg.command) { if (main[msg.command]) main[msg.command].apply(main, msg.args); + else if (window[msg.command]) + window[msg.command].apply(window, msg.args); else throw new Error("Unknown command:" + msg.command); } - else if (msg.init) { - initBaseUrls(msg.tlns); + else if (msg.init) { + window.initBaseUrls(msg.tlns); require("ace/lib/es5-shim"); - sender = window.sender = initSender(); + sender = window.sender = window.initSender(); var clazz = require(msg.module)[msg.classname]; main = window.main = new clazz(sender); - } - else if (msg.event && sender) { - sender._signal(msg.event, msg.data); } }; })(this); \ No newline at end of file From a799a4086f1e9e9912c110e9c329b4101a4047af Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 25 Apr 2015 03:02:08 +0400 Subject: [PATCH 302/315] fix quote pairing for "\n" --- lib/ace/mode/behaviour/behaviour_test.js | 10 ++++++++++ lib/ace/mode/behaviour/cstyle.js | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/ace/mode/behaviour/behaviour_test.js b/lib/ace/mode/behaviour/behaviour_test.js index 9dc27bf8..245edf99 100644 --- a/lib/ace/mode/behaviour/behaviour_test.js +++ b/lib/ace/mode/behaviour/behaviour_test.js @@ -144,6 +144,16 @@ module.exports = { exec("selectleft", 1); exec("insertstring", 1, '"'); assert.equal(editor.getValue(), '("foo")'); + + editor.setValue("", 1); + exec("selectleft", 1); + exec("insertstring", 1, '"'); + assert.equal(editor.getValue(), '""'); + exec("insertstring", 1, '\\'); + exec("insertstring", 1, 'n'); + exec("insertstring", 1, '"'); + assert.equal(editor.getValue(), '"\\n"'); + }, "test: xml": function() { editor = new Editor(new MockRenderer()); diff --git a/lib/ace/mode/behaviour/cstyle.js b/lib/ace/mode/behaviour/cstyle.js index a1dce91e..dd1b0d14 100644 --- a/lib/ace/mode/behaviour/cstyle.js +++ b/lib/ace/mode/behaviour/cstyle.js @@ -269,8 +269,8 @@ var CstyleBehaviour = function() { if (leftChar == "\\" && token && /escape/.test(token.type)) return null; - var stringBefore = token && /string/.test(token.type); - var stringAfter = !rightToken || /string/.test(rightToken.type); + var stringBefore = token && /string|escape/.test(token.type); + var stringAfter = !rightToken || /string|escape/.test(rightToken.type); var pair; if (rightChar == quote) { From 2e2d9bcdc9fa97b7b30e51dd0b864911c33e115c Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 26 Apr 2015 21:27:25 +0400 Subject: [PATCH 303/315] add more php extensions --- lib/ace/ext/modelist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index 7a5a1e9c..6bc79c8b 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -122,7 +122,7 @@ var supportedModes = { Pascal: ["pas|p"], Perl: ["pl|pm"], pgSQL: ["pgsql"], - PHP: ["php|phtml"], + PHP: ["php|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp"], Powershell: ["ps1"], Praat: ["praat|praatscript|psc|proc"], Prolog: ["plg|prolog"], From 5705a7c2c1090605877b8fdf7e9a7a9ee782d257 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 30 Apr 2015 03:55:19 +0400 Subject: [PATCH 304/315] fix toggle comments in handlebars mode --- lib/ace/mode/handlebars.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/ace/mode/handlebars.js b/lib/ace/mode/handlebars.js index 3f2e7179..164ad43f 100644 --- a/lib/ace/mode/handlebars.js +++ b/lib/ace/mode/handlebars.js @@ -13,7 +13,6 @@ var Mode = function() { HtmlMode.call(this); this.HighlightRules = HandlebarsHighlightRules; this.$behaviour = new HtmlBehaviour(); - this.foldingRules = new HtmlFoldMode(); }; @@ -21,7 +20,7 @@ var Mode = function() { oop.inherits(Mode, HtmlMode); (function() { - this.blockComment = {start: "{!--", end: "--}"}; + this.blockComment = {start: "{{!--", end: "--}}"}; this.$id = "ace/mode/handlebars"; }).call(Mode.prototype); From dc7643db8df6611de25b5ce37468ee233fee5ff2 Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 22 May 2015 21:57:13 +0400 Subject: [PATCH 305/315] better invisible tabs (fixes #2109) --- lib/ace/layer/text.js | 7 +++---- lib/ace/layer/text_test.js | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/ace/layer/text.js b/lib/ace/layer/text.js index a105768d..01afb9f3 100644 --- a/lib/ace/layer/text.js +++ b/lib/ace/layer/text.js @@ -52,7 +52,7 @@ var Text = function(parentEl) { this.EOL_CHAR_LF = "\xAC"; this.EOL_CHAR_CRLF = "\xa4"; this.EOL_CHAR = this.EOL_CHAR_LF; - this.TAB_CHAR = "\u2192"; //"\u21E5"; + this.TAB_CHAR = "\u2014"; //"\u21E5"; this.SPACE_CHAR = "\xB7"; this.$padding = 0; @@ -128,8 +128,7 @@ var Text = function(parentEl) { for (var i = 1; i < tabSize + 1; i++) { if (this.showInvisibles) { tabStr.push("" - + this.TAB_CHAR - + lang.stringRepeat(" ", i - 1) + + lang.stringRepeat(this.TAB_CHAR, i) + ""); } else { tabStr.push(lang.stringRepeat(" ", i)); @@ -145,7 +144,7 @@ var Text = function(parentEl) { spaceClass = " ace_invisible_space"; tabClass = " ace_invisible_tab"; var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize); - var tabContent = this.TAB_CHAR + lang.stringRepeat(" ", this.tabSize - 1); + var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize); } else{ var spaceContent = lang.stringRepeat(" ", this.tabSize); var tabContent = spaceContent; diff --git a/lib/ace/layer/text_test.js b/lib/ace/layer/text_test.js index e3403ca4..3946ec66 100644 --- a/lib/ace/layer/text_test.js +++ b/lib/ace/layer/text_test.js @@ -91,7 +91,7 @@ module.exports = { var EOL = "" + textLayer.EOL_CHAR + ""; var SPACE = function(i) {return Array(i+1).join(" ")} var DOT = function(i) {return Array(i+1).join(textLayer.SPACE_CHAR)} - var TAB = function(i) {return textLayer.TAB_CHAR + SPACE(i-1)} + var TAB = function(i) {return Array(i+1).join(textLayer.TAB_CHAR)} function testRender(results) { for (var i = results.length; i--; ) { var stringBuilder = []; From 386c508042e80aeab4fb388816babee9f74466ce Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 22 May 2015 22:14:15 +0400 Subject: [PATCH 306/315] convert paste into command --- lib/ace/commands/default_commands.js | 12 ++++++++++++ lib/ace/editor.js | 13 +++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/ace/commands/default_commands.js b/lib/ace/commands/default_commands.js index f1e267c1..de14df85 100644 --- a/lib/ace/commands/default_commands.js +++ b/lib/ace/commands/default_commands.js @@ -423,6 +423,12 @@ exports.commands = [{ exec: function() {}, passEvent: true, readOnly: true +}, { + name: "copy", + exec: function(editor) { + // placeholder for replay macro + }, + readOnly: true }, // commands disabled in readOnly mode @@ -439,6 +445,12 @@ exports.commands = [{ }, scrollIntoView: "cursor", multiSelectAction: "forEach" +}, { + name: "paste", + exec: function(editor, args) { + editor.$handlePaste(args); + }, + scrollIntoView: "cursor" }, { name: "removeline", bindKey: bindKey("Ctrl-D", "Command-D"), diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 22b43dd2..5da8a961 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -916,13 +916,15 @@ var Editor = function(renderer, session) { * **/ this.onPaste = function(text, event) { - // todo this should change when paste becomes a command - if (this.$readOnly) - return; - var e = {text: text, event: event}; + this.commands.exec("paste", this, e); + }; + + this.$handlePaste = function(e) { + if (typeof e == "string") + e = {text: e}; this._signal("paste", e); - text = e.text; + var text = e.text; if (!this.inMultiSelectMode || this.inVirtualSelectionMode) { this.insert(text); } else { @@ -940,7 +942,6 @@ var Editor = function(renderer, session) { this.session.insert(range.start, lines[i]); } } - this.renderer.scrollCursorIntoView(); }; this.execCommand = function(command, args) { From 2a089863e24472836116a32973852af4a66d7f1e Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 18 May 2015 16:24:10 +0400 Subject: [PATCH 307/315] fix highlighting of line-height:1.5 in less mode --- lib/ace/mode/less_highlight_rules.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/mode/less_highlight_rules.js b/lib/ace/mode/less_highlight_rules.js index d39bdeae..a0162765 100644 --- a/lib/ace/mode/less_highlight_rules.js +++ b/lib/ace/mode/less_highlight_rules.js @@ -231,7 +231,7 @@ var LessHighlightRules = function() { regex: "\\.[a-z0-9-_]+" }, { token: "variable.language", - regex: ":[a-z0-9-_]+" + regex: ":[a-z_][a-z0-9-_]*" }, { token: "constant", regex: "[a-z0-9-_]+" From 9f57989043842d906e88e6744da952ac55101260 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 27 May 2015 19:56:28 +0400 Subject: [PATCH 308/315] fix highlighting of tables in Gherkin mode --- lib/ace/mode/_test/tokens_gherkin.json | 40 ++++++++-------- lib/ace/mode/gherkin_highlight_rules.js | 62 +++++++++++++------------ 2 files changed, 53 insertions(+), 49 deletions(-) diff --git a/lib/ace/mode/_test/tokens_gherkin.json b/lib/ace/mode/_test/tokens_gherkin.json index d16ffc6c..173d9798 100644 --- a/lib/ace/mode/_test/tokens_gherkin.json +++ b/lib/ace/mode/_test/tokens_gherkin.json @@ -56,34 +56,34 @@ ],[ "start", ["text"," "], - ["comment","| "], - ["string","start "], - ["comment","| "], - ["string","eat "], - ["comment","| "], - ["string","left "], + ["comment","|"], + ["string"," start "], + ["comment","|"], + ["string"," eat "], + ["comment","|"], + ["string"," left "], ["comment","|"] ],[ "start", ["text"," "], - ["comment","| "], - ["string"," 12 "], - ["comment","| "], - ["string"," 5 "], - ["comment","| "], - ["string"," 7 "], + ["comment","|"], + ["string"," 12 "], + ["comment","|"], + ["string"," 5 "], + ["comment","|"], + ["string"," 7 "], ["comment","|"] ],[ "start", ["text"," "], - ["comment","| "], - ["string"," 20 "], - ["comment","| "], - ["string"," 5 "], - ["comment","| "], - ["string"," 15 "], - ["comment","| "], - ["string"," "] + ["comment","|"], + ["string"," 20 "], + ["comment","|"], + ["string"," 5 "], + ["comment","|"], + ["string"," 15 "], + ["comment","|"], + ["string"," "] ],[ "start" ],[ diff --git a/lib/ace/mode/gherkin_highlight_rules.js b/lib/ace/mode/gherkin_highlight_rules.js index d54db204..04ce877c 100644 --- a/lib/ace/mode/gherkin_highlight_rules.js +++ b/lib/ace/mode/gherkin_highlight_rules.js @@ -36,18 +36,18 @@ var stringEscape = "\\\\(x[0-9A-Fa-f]{2}|[0-7]{3}|[\\\\abfnrtv'\"]|U[0-9A-Fa-f] var GherkinHighlightRules = function() { - // need to include constant ints + // need to include constant ints this.$rules = { - start : [{ + start : [{ token: 'constant.numeric', regex: "(?:(?:[1-9]\\d*)|(?:0))" - }, { - token : "comment", - regex : "#.*$" - }, { - token : "keyword", - regex : "Feature:|Background:|Scenario:|Scenario\ Outline:|Examples:|Given|When|Then|And|But|\\*", - }, { + }, { + token : "comment", + regex : "#.*$" + }, { + token : "keyword", + regex : "Feature:|Background:|Scenario:|Scenario\ Outline:|Examples:|Given|When|Then|And|But|\\*", + }, { token : "string", // multi line """ string start regex : '"{3}', next : "qqstring3" @@ -56,22 +56,22 @@ var GherkinHighlightRules = function() { regex : '"', next : "qqstring" }, { - token : "comment", - regex : "@[A-Za-z0-9]+", - next : "start" + token : "comment", + regex : "@[A-Za-z0-9]+", + next : "start" }, { - token : "comment", - regex : "<.+>" + token : "comment", + regex : "<.+>" }, { - token : "comment", - regex : "\\| ", - next : "table-item" + token : "comment", + regex : "\\|(?=.)", + next : "table-item" }, { - token : "comment", - regex : "\\|$", - next : "start" + token : "comment", + regex : "\\|$", + next : "start" }], - "qqstring3" : [ { + "qqstring3" : [ { token : "constant.language.escape", regex : stringEscape }, { @@ -81,7 +81,7 @@ var GherkinHighlightRules = function() { }, { defaultToken : "string" }], - "qqstring" : [{ + "qqstring" : [{ token : "constant.language.escape", regex : stringEscape }, { @@ -96,15 +96,19 @@ var GherkinHighlightRules = function() { defaultToken: "string" }], "table-item" : [{ + token : "comment", + regex : /$/, + next : "start" + }, { + token : "comment", + regex : /\|/ + }, { token : "string", - regex : "[A-Za-z0-9 ]*", - next : "start" - }], + regex : /\\./ + }, { + defaultToken : "string" + }] }; - - - //new TextHighlightRules().getRules(); - } oop.inherits(GherkinHighlightRules, TextHighlightRules); From 8c1d0ab7cffb7d7efc2b49e5ec15ab9da92c18f1 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 28 May 2015 13:56:33 +0400 Subject: [PATCH 309/315] fix autocomplete blur handler --- lib/ace/autocomplete.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index d3b41b65..331c2001 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -143,9 +143,10 @@ var Autocomplete = function() { // on IE preventDefault doesn't stop scrollbar from being focussed var el = document.activeElement; var text = this.editor.textInput.getElement(); - if (el != text && ( !this.popup || el.parentNode != this.popup.container ) - && el != this.tooltipNode && e.relatedTarget != this.tooltipNode - && e.relatedTarget != text + var fromTooltip = e.relatedTarget && e.relatedTarget == this.tooltipNode; + var container = this.popup && this.popup.container; + if (el != text && el.parentNode != container && !fromTooltip + && el != this.tooltipNode && e.relatedTarget != text ) { this.detach(); } From abdc4c7510e413ce072ba59c11d93b4ec4c0f26e Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Fri, 29 May 2015 09:55:02 -0600 Subject: [PATCH 310/315] Fix invalid syntax in autoresize.html The options literal had a duplicate key. --- demo/autoresize.html | 1 - 1 file changed, 1 deletion(-) diff --git a/demo/autoresize.html b/demo/autoresize.html index ef4cbe04..b0464ecd 100644 --- a/demo/autoresize.html +++ b/demo/autoresize.html @@ -49,7 +49,6 @@ require(["ace/ace"], function(ace) { var editor = ace.edit("editor3"); editor.setOptions({ - maxLines: 100, autoScrollEditorIntoView: true, maxLines: 8 }); From 446e3e1bf9fa5346100324b1e870329493bda1ef Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 31 May 2015 16:48:35 +0400 Subject: [PATCH 311/315] fix #2522 Popup position is off when gutter isn't shown --- demo/kitchen-sink/dev_util.js | 2 +- lib/ace/autocomplete.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/kitchen-sink/dev_util.js b/demo/kitchen-sink/dev_util.js index 8dab857c..f466285d 100644 --- a/demo/kitchen-sink/dev_util.js +++ b/demo/kitchen-sink/dev_util.js @@ -39,7 +39,7 @@ function warn() { s.shift(); // remove the getter s = s.join("\n"); // allow easy access to ace in console, but not in ace code - if (!/at Object.InjectedScript.|@debugger eval|snippets:\/{3}/.test(s)) { + if (!/at Object.InjectedScript.|@debugger eval|snippets:\/{3}|\(:\d+:\d+\)/.test(s)) { console.error("trying to access to global variable"); } } diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index d3b41b65..caef17ca 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -100,7 +100,7 @@ var Autocomplete = function() { var rect = editor.container.getBoundingClientRect(); pos.top += rect.top - renderer.layerConfig.offset; pos.left += rect.left - editor.renderer.scrollLeft; - pos.left += renderer.$gutterLayer.gutterWidth; + pos.left += renderer.gutterWidth; this.popup.show(pos, lineHeight); } else if (keepPopupPosition && !prefix) { From 1514d5f374b1b295894f5f911cb8e0ebbda0febe Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 31 May 2015 17:06:32 +0400 Subject: [PATCH 312/315] fix #2483 Exception on ctrl-alt-shift-click when $enableJumpToDef is true --- lib/ace/mouse/multi_select_handler.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ace/mouse/multi_select_handler.js b/lib/ace/mouse/multi_select_handler.js index 45704b39..649043fa 100644 --- a/lib/ace/mouse/multi_select_handler.js +++ b/lib/ace/mouse/multi_select_handler.js @@ -83,7 +83,7 @@ function onMouseDown(e) { var selectionMode; if (editor.$mouseHandler.$enableJumpToDef) { if (ctrl && alt || accel && alt) - selectionMode = "add"; + selectionMode = shift ? "block" : "add"; else if (alt && editor.$blockSelectEnabled) selectionMode = "block"; } else { @@ -117,7 +117,7 @@ function onMouseDown(e) { if (shift) { oldRange = null; - range = selection.ranges[0]; + range = selection.ranges[0] || range; editor.removeSelectionMarker(range); } editor.once("mouseup", function() { From 2249d06337d561508eebcf00966a011cbef061f1 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 31 May 2015 17:41:34 +0400 Subject: [PATCH 313/315] fix #2484 Hard-coded characterWidth in static_highlight.js and remove dependence on mockdom --- demo/static-highlighter/server.js | 17 +++++++++++------ lib/ace/ext/static_highlight.js | 10 +++++----- lib/ace/lib/dom.js | 8 +++++--- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/demo/static-highlighter/server.js b/demo/static-highlighter/server.js index 0878fec2..ea8361d4 100644 --- a/demo/static-highlighter/server.js +++ b/demo/static-highlighter/server.js @@ -2,15 +2,13 @@ * Simple node.js server, which generates the synax highlighted version of itself * using the Ace modes and themes on the server and serving a static web page. */ -// $' + // include ace search path and modules require("amd-loader"); -// load jsdom, which is required by Ace -require("../../lib/ace/test/mockdom"); - var http = require("http"); var fs = require("fs"); +var resolve = require("path").resolve; // load the highlighter and the desired mode and theme var highlighter = require("../../lib/ace/ext/static_highlight"); @@ -20,15 +18,22 @@ var theme = require("../../lib/ace/theme/twilight"); var port = process.env.PORT || 2222; http.createServer(function(req, res) { + var url = req.url; + var path = /[^#?\x00]*/.exec(url)[0]; + var root = resolve(__dirname + "/../../").replace(/\\/g, "/"); + path = resolve(root + "/" + path).replace(/\\/g, "/"); + if (path.indexOf(root + "/") != 0) + path = __filename; res.writeHead(200, {"Content-Type": "text/html; charset=utf-8"}); - fs.readFile(__dirname + "/../../build/src/ace.js", "utf8", function(err, data) { + fs.readFile(path, "utf8", function(err, data) { + if (err) data = err.message; var highlighted = highlighter.render(data, new JavaScriptMode(), theme); res.end( '\n' + '\n' + - highlighted.html + + highlighted.html + '' ); }); diff --git a/lib/ace/ext/static_highlight.js b/lib/ace/ext/static_highlight.js index b2287f15..2acb3ac5 100644 --- a/lib/ace/ext/static_highlight.js +++ b/lib/ace/ext/static_highlight.js @@ -37,6 +37,10 @@ var baseStyles = require("../requirejs/text!./static.css"); var config = require("../config"); var dom = require("../lib/dom"); +var SimpleTextLayer = function() { + this.config = {}; +}; +SimpleTextLayer.prototype = TextLayer.prototype; var highlight = function(el, opts, callback) { var m = el.className.match(/lang-(\w+)/); @@ -149,12 +153,8 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) { session.setUseWorker(false); session.setMode(mode); - var textLayer = new TextLayer(document.createElement("div")); + var textLayer = new SimpleTextLayer(); textLayer.setSession(session); - textLayer.config = { - characterWidth: 10, - lineHeight: 20 - }; session.setValue(input); diff --git a/lib/ace/lib/dom.js b/lib/ace/lib/dom.js index ef2f7caa..2cbfe23e 100644 --- a/lib/ace/lib/dom.js +++ b/lib/ace/lib/dom.js @@ -91,6 +91,11 @@ exports.toggleCssClass = function(el, name) { return add; }; +if (typeof document == "undefined") { + exports.importCssString = function() {}; + return; +} + /* * Add or remove a CSS class from the list of classes on the given node * depending on the value of include @@ -173,9 +178,6 @@ exports.getInnerHeight = function(element) { }; -if (typeof document == "undefined") - return; - if (window.pageYOffset !== undefined) { exports.getPageScrollTop = function() { return window.pageYOffset; From 3f31ca57ed5b31443e0874dd40e15f2990d552b2 Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 1 Jun 2015 01:06:39 +0400 Subject: [PATCH 314/315] fix typo --- static.js | 3 ++- tool/mode_creator.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/static.js b/static.js index a711715e..3b75c2b6 100755 --- a/static.js +++ b/static.js @@ -21,7 +21,7 @@ http.createServer(function(req, res) { if (req.method == "PUT") { if (!allowSave) return error(res, 404, "Saving not allowed pass --allow-save to enable"); - save(req, res, filename); + return save(req, res, filename); } fs.exists(filename, function(exists) { @@ -86,6 +86,7 @@ function save(req, res, filePath) { } res.statusCode = 200; res.end("OK"); + console.log("saved ", filePath); }); } diff --git a/tool/mode_creator.js b/tool/mode_creator.js index 7a2aea59..44aa67d0 100644 --- a/tool/mode_creator.js +++ b/tool/mode_creator.js @@ -126,8 +126,8 @@ function handleSaveResult(err, editor) { return log( "Write access to this file is disabled.\n"+ "To enable saving your changes to disk, clone the Ace repository\n"+ - "and run the included web server with the --allow-write option\n"+ - "`node static.js --allow-write` or `static.py --puttable=*`" + "and run the included web server with the --allow-save option\n"+ + "`node static.js --allow-save` or `static.py --puttable=*`" ); } editor.session.getUndoManager().markClean(); From 6cec0b28b2d8f7a41b8e16242bbb170ae5fab87d Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 1 Jun 2015 13:50:32 +0400 Subject: [PATCH 315/315] improve tmlanguage importer --- tool/lib.js | 105 +++++++++++++++++++++++++++++++++++++++++++-- tool/tmlanguage.js | 4 +- 2 files changed, 104 insertions(+), 5 deletions(-) diff --git a/tool/lib.js b/tool/lib.js index 8809595c..3d57b6e0 100644 --- a/tool/lib.js +++ b/tool/lib.js @@ -14,8 +14,16 @@ exports.parsePlist = function(xmlOrJSON, callback) { }); } else { try { - xmlOrJSON = xmlOrJSON.replace(/^\s*\/\/.*/gm, ""); - json = JSON.parse(xmlOrJSON) + xmlOrJSON = xmlOrJSON.replace( + /("(?:\\.|[^"])*")|(?:,\s*)+([\]\}])|(\w+)\s*:|([\]\}]\s*[\[\{])|(\/\/.*|\/\*(?:[^\*]|\*(?=[^\/]))*?\*\/)/g, + function(_, str, extraComma, noQuote, missingComma, comment) { + if (comment) + return ""; + if (missingComma) + return missingComma[0] + "," + missingComma.slice(1); + return str || extraComma || '"' + noQuote + '":'; + }); + json = JSON.parse(xmlOrJSON); } catch(e) { json = cson.parse(xmlOrJSON); } @@ -24,10 +32,101 @@ exports.parsePlist = function(xmlOrJSON, callback) { return json; }; + exports.formatJSON = function(object, initialIndent) { - return util.inspect(object, false, 40).replace(/^/gm, initialIndent||""); + return JSON.stringify(object, null, 4).replace(/^/gm, initialIndent||""); }; +exports.formatJS = function(object, initialIndent) { + return formatJS(object, 4, initialIndent); +}; + +function formatJS(object, indent, initialIndent) { + if (typeof indent == "number") + indent = Array(indent + 1).join(" "); + + function $format(buffer, totalIndent, state, o) { + if (typeof o != "object" || !o) { + if (typeof o == "string") + buffer.push(JSON.stringify(o)); + else + buffer.push("" + o); + } + else if (Array.isArray(o)) { + buffer.push("[") + + var len = totalIndent.length + var oneLine = true; + for (var i = 0; i < o.length; i++) { + if (typeof o[i] == "string") { + len += o[i].length + 2 + } else if (!o[i]) { + len += (o[i] + "").length + } else { + oneLine = false; + break; + } + len += 2; + if (len > 60) { + oneLine = false; + break; + } + } + + for (var i = 0; i < o.length; i++) { + if (o[i] && typeof o[i] == "object") { + $format(buffer, totalIndent, state, o[i]); + if (i < o.length - 1) + buffer.push(", "); + } else { + if (oneLine) + i && buffer.push(" "); + else + buffer.push("\n", totalIndent + indent) + $format(buffer, totalIndent + indent, state, o[i]); + if (i < o.length - 1) + buffer.push(","); + } + + } + if (!oneLine && buffer[buffer.length - 1] != "}") + buffer.push("\n" + totalIndent) + buffer.push("]") + } + else { + var keys = Object.keys(o); + buffer.push("{", "\n"); + for (var i = 0; i < keys.length; i++) { + buffer.push(totalIndent + indent); + if (/^\w+$/.test(keys[i])) + buffer.push(keys[i]); + else + buffer.push(JSON.stringify(keys[i])); + buffer.push(": ") + + if (keys[i] == "regex" && typeof o[keys[i]] == "string") { + try { + var re = new RegExp(o[keys[i]]); + buffer.push("/" + re.source.replace(/\\.|\//g, function(f) { + return f.length == 1 ? "\\" + f : f; + }) + "/"); + } catch(e) { + $format(buffer, totalIndent + indent, state, o[keys[i]]); + } + } else { + $format(buffer, totalIndent + indent, state, o[keys[i]]); + } + + if (i < keys.length - 1) + buffer.push(",", "\n"); + } + buffer.push("\n", totalIndent, "}"); + } + } + var buffer = []; + $format(buffer, initialIndent || "", {}, object); + return buffer.join(""); +} exports.fillTemplate = function(template, replacements) { return template.replace(/%(.+?)%/g, function(str, m) { diff --git a/tool/tmlanguage.js b/tool/tmlanguage.js index 0e458330..b5d8b851 100644 --- a/tool/tmlanguage.js +++ b/tool/tmlanguage.js @@ -662,10 +662,10 @@ function convertTmLanguage(name, langStr) { var languageHighlightRules = lib.fillTemplate(modeHighlightTemplate, { language: languageNameSanitized, - languageTokens: lib.formatJSON(patterns, " ").trim(), + languageTokens: lib.formatJS(patterns, " ").trim(), uuid: language.uuid, name: name, - metaData: lib.formatJSON(language, " ").trim() + metaData: lib.formatJS(language, "").trim() }); if (devMode) {

      )Ja9B?HWlU8jVl-9%VI+hAC!AC^;fQmdw2w5$ap9Ud4MmNazt zXN!C6LQ*%mM~&Nf?tj+Uz3*^q&beC?&Lq8Um-x2B?InRF6Hlg0J`(rVX3yoP1O4u0 z-pNU;trj(x<~LW1OIx%Hcl*zD&3VH)e^g98#xe7MpNt-V-2Ze?NPc!sZ*_yRLs4F( z@C_BsUG>wXb*KMp^)GMizdXyo_;05kz{~E9V|V^>FnONM!>N0(zxKsXD|R{u#Ab>r zTS_bHTbkN?+dHNG5)GECMk$3?hc-^I1D6Im%?qA}UakRglDk#y(d7eQ*n};&Ph9GJ z508Gad)6$w`*YkfFc8ebmj}@%yFHri@?f6xz4@3Z#x~_WyQCF1k#>niIi2c?w%+dE zF0HJOsNtvviwc@`PmHX8-1mY;Anw#KNJ7&pCw;wl(QfY#PDU&^lf2L&ZR)wSX^uHF z-9%HI^Re{FbeFvG_8A!aW_fvMIp6u#Il=F4wWwX&f~i~4#n9VDJ@jN~lhAjYf-TTA zZHVFkGOA5rYIO8V6lyfZi{wOPAX_eF%{g{;$+=i2@1KibWSczC?#^uc`_mmBO>=pK zM@CEGmNnijXRLef825b0n@%}nJw*SoPaEr!^|t-Pf1bTP%_DRA>F_U)yMOq@=EL@$ zSyhdVeZ%$bJ$(|niuQ^N8_V;^a8&vK4@PFSvAIrWlxjZw4`yU^w|XXrIAqte^UsGU zm-(c*jHA0HUPIGep1*M9PuOR-dp_E4o?)5%&1jZKU_W07At#>Q6+)(`6YhZRG8-IRRcfJ7As4Bdih4nq4J zQ6)mKgSSnugj0=HFCSJ652CgN9f)PL>s%}+m;s|_Sg%y+hX$$T8EQ9uJMjkwQOUGQ zRpX#x^)J`wolKl+n?24h=N*SU3uUV9{e?$@H`rdX22Zv=lF5QgMYagUXU;9tEtm>%ap^Us$O$3D$6%EckY%m(+`{)Yf zXzIsl^w?qq*P)9kR#&s89}Ayy=Jq(7w0F)v#&EFLe@=s%|E_J8g)a|_Hr6f!uiRLt zoHtITPPR{_~$PfZ=B12+ok+<`{KXZj4ZbAQ&cs5Kt9 zLPXuwg9JVv13jIzbV{rX12-@_RW7=H0sQZ0Y85^gO@~yAUadnRS^E>}CjS)q?$M}e zXH%xyq|or}oeAgek3E@}U$HS}P?Bf{@In$3tzPI_r57vh+#-=n4D&W-7(l-F>H*!lqNx|y$B*ZD<>>vHe zeqZ_)*2Yj0e`PaspSh|xpZR^c`pv7%H!{b>8Qj!-_`)4lSaaTr#OZY6%I- zYPI%CPAnT1OGy`OhFwEaSix1om}d zK^gBF8isRJdVTM);H0T*PyTJ?z9nZu=h=pjJs3D{i^s$tZNEKw!8<-Ly|$ycsj;=Y zQKuTz4ND}0x~d*B$I5%A-F+~xg>4K|w4A@4Od4}I_?OGk<>lqQ;(B>|7i#^EPVL|j z$tY~Pm?C=Tt39u+cYOC~$mFweV-8(@;|H5DUmab(&Bo*U-GZvt(z5E>iW&lkcQZra zdEmP@GBwB| zEPsFAb;x4)|XB9Sf_74uwX;_4J=0CyIlw9<3 zDF!H!`YxHMRsPw2=LtWaer=WQ+|!8*-Ll8qWxe+E<9|4nz2;Q;zwFB1^r(Hyp}_L; zPQ;uur*3`Zl)CHk<5aPeMw%$YMY=Qn5O%uGV={qece7h9$>8cZk)T6!dS$)U-yB~xPxr^XcFnHVbo zTDo9!$&|$hCYtjnn(`iuw>=zdnWjmZ{@Tj#JU#c#b(=Cv50{;)s%zf$+nehX=!O80#yM2`2;2mV7{7*>KQ;M*~y;>cl=2bDFfBFn#fn> zk^KdTyn016LJp~JwTEu7J{-A;GquJgl)Fcl1S~m>t#W`NXMAklg!r8Cx8!2;Fr5lq zTuvgM(WOE0r4KE(JsP?BFH5%UDy=+Qf2p#vva^+gzxu?AGmls+7ZZIFsii_KZ~+~* z8|&^a`g~QFy|~T(mbLc3qSie&|Kr)86mB`tnt8J2Z0ptfPGKrT9ARaI=G$`#Gwd_1 z_Wv_)cu2c{a!lcb*uwE~!*%yZXFU=6*`H%Kpgrv^IC{FOruAZ-g4AMR^kNqVzV?Id z_T?$Ze-*vyfmh%AwRzJ=$pYu?$4@lZS9M%!WZ{5&EH7Q`YHaL0bh_!i#Js6b zYrd;l7yM$v$G-Fx^%h#DI8}hfn(of7 z9u{G@=TvD>GlB82?_6 z6y|DE0>UITOHe@gU%Ys+si~>4vGIcPG!OC+hld}DFHwVUffb3}K%0axRp#F*E~u2t zlt~tkI#dwDg@1g2FgfbrP1%P-1_=^V!X<2>Toh22_r^EL%5lPQQob<`#UU?J;E@#p z17V}gky^MhM;XFT@>i-r@?T;)1cUOVrZVcrOl62HrrH1`4=FW|%0e{|+6GJKPKArn zF8zgmbA<_H#E{)m-}kGSPao1JPFrF_n|6yX^Ivjcd_u)|Q}%dc`uNzK;P~OXkhmQB zct}ic(2{b$gbFuvsc%g2v^dM-y6ry+`{3i`(j(_CR92n8*woy|1UyPGrGgltSqr3= z>VraFpK|)jrQVhcoDRxamaB?teiXeWWX>AaK&Q@M_hZf4m*3pDyP`7xRCQHrR}0&F zgc`!hEls_bJ5RRRe;2)Rx-L0{={sdkZhAYuip29`O%kSe=}>zx^1?i;xi|Xo~x;;?&@X%pWQR!;1IUG z9BQ#Y^3vOnnRiW%%N!qT9VYQaW5#kqSmuK>KhwXTSa#@WP5s$RosA3{puVfK{c;Bu z#rES>tqB|Re1H1Nea{=G|22&D_)qp`+YTH%TY2ux@q^urOz7yXY~K+z!nep=v4Dyb zvlhx(ls&9jh{|H3;3y1v3k3}_V- zFDxtU_S)w5nl5|nnjP=#s|fzxf`{k6|4sdl`wjc10C`JG0^&=&qVqw(;g^@l^ptVY zd5;=){5tlt^b_^x8k^5moo;Qt(2ETTBKJB{i!#dd#s%sP_kl&s_OL=7wl?{J+3!CR zpT!~b-&mO98C&ANxQN`x$AQ$@49J6H3#he#_%gci__%bj5*?pSL4xA*#xBm|J#m?B z%F?{432BpzNe?gHGflI>^Tnm#T=?eZ{Db=}`6p}Z+pk{3{E~Ga2vyn+%|{Nx@%;ND zwJN|7)W~zB`d~05AsQgQ>EnnL60eCSlakm0WJqvSa~y6h4jE5P4TzC`3PN6FJ=g<1 zP|L5-!&gHlk3t-p=k`E2Zl9R;V4S6vWSRIo06SXa;`e7nKQ%Mv^Nndo3J%sDIeOvT@t%&x%Y9<@01LH7HpjJr)bBoK+&L{a z4V`P4#1n0jDS!HcoNv9dIr{zGg$E9wIDfpRs}|#=M)vxmvtQ||JbJ9Dp>xen+c*C> zf9#L{`iF?6+j2{{rKY9lW*$FY(Oh$^=VF!Myt4OALOf$RYDxei`jOZ!$6Nf(uPD^1 zb@m_X*FPS;ds0j`Q`P~CD}0sq!?1zaC%L0hXjt4-&hwn<_m9SAO)21 zWeTz?`H5tyVz8L%zA1U+&KN@ua`+Z5$y&oND^U%Rsi|at6&}PI{ig>RN7uP#XN8yj zs_PHcPoMYJc>Oj%bEbE6QDA(9zcD{ZoB3dD&J=y>ICDW@bZKC8$yl@EqKksfUpUNZ zWH=Fsh8i`+oHfOq5n#yjiMIJKsql@-57MQg2>&pAZPdr9`wPz;JXwFbvH`{G_rtgE@HzV*trvwilZ=|_H&u;YH??qGeYXGH3w@03r~Cf>hbJ4i(<|i>$?tn zM_YYWZC#7~-3=*E%`+w`3Q@(0qeqS%tUPnr-rLN)M0Y!@n*Cdo00u0)L29L%u(xN4 zL7ZL3pDYBh3HLo)!+*!_9v`|5142J@fv2g^KfcT_+7@KCOi!={8#1|qGa#mfRnBpy zen*1|q?su#N)03e(Z)uD)XCFh(wJx+9kD<7t-~HM*0JUcs{XMBD_?zc`%dfe>gMj2 z&c4oGT8U`PUnx?PczcH^?4=Gdp9?D*uGnp7T5NS!UV44&m3<#uqkqFpZ|^G=+QLci#rMus*BQ=QVKB};gVhX@dS`l>x{-?1mcKmG2qTwhI^ zo2ek^%~PZGHlNshCbUD$852xt6HFN)rfjM#$ZVw^apTO^;Aq>}X!<@iRYWDS1jDBL zhvG6PFWNYL?y5;ICOk3wjki+{?#wGXU0c(DoNRAX>f$OZib~BW#0b2Wy_)yG<0IuW zc!a2z2#W_`Qsq2S8WGJi^z64II!nLA3z@7;gf~Bd1;E*z;)M!25_3tG5|N7|syh0i zN5T++AlH{Fzr+Wa)CBQ3@<(#X@qHswL!nCKjir{q@`e(Cl8PWZ$td!Yk0bq#c{%#| zgoh9!^OYo$dc;qN3?~rsR7MRTMpftKS2A&#noL0^0(sORBZ>i^-`PLu*9e>r*?W5J z7n-itT(kdwhEJ4NzHR{fp@$O|1?A9_YA2&oc-C>g3j%k=WGYg zw=&J!-GhHd38>dN`5N!)E z*#gb^SlA+7rfQRZzC7j4oN5lBxX_02$Cd8Z_O>qjkyiVULqD7v`uY7!EKmyp!*o+j zsSnLv@!ayQ&lx}1Q+V>&`L@ai&Oo=H>b9G=AOFqkc~c_xO)%zi<1=gV{stxqv+rA; zGtrbZG5qr%CG0WpKa*F-Ngej~ix{D`+gr}tdm5OK$I`yOy|bdJ^FT{q$=T*Zr|M3h zs;psCOI>wGYZLRF)QjMO!iV-gd&MRDW3RnC&6pe*Z5bxzGTL~vHE{mE`(9levwBZK z#i5$o%8ss9j?z+Em7iYaO`!T!y+hL!4GdlG?T7?+V3A7b1wjeNuR$=vvvwAJI zd83_~If|`dirzNSNVv^6UNjFp{7E1`5rJp~QUq+4D2{i$)jh%LnUEI{mo+gu84IrO z&tJPfr=k4pmGg~P8Pc$efr$tO2>N>oot@{-cA4uyBesMw5yS|yslBhJ^=jeSmRA<9 zV-EaV5uZH}oklNki>vTjax^fGIUE~9#GtsM;P_%3{$P`ZP9YtA2LyymzA*>9W6OOL z3VdR-rYy4sMr{B7lC&4s6ojqLwpI32UA%@c=(xm85zu^5lN4{SsG}}_0;Du_2Hq*hWSEGj?Nnw zokJhN1J8MnkItH4&SEBq`7tQRKG5GJ@EYu%V$6KhxI5sPm~XydeBw{9y!qL-G+WWJ z)8}gI>)Jazup*Q4RuRi8I^Xf?kX*RUw`?I29cbrhSP0>pKK&qZ9rC2y9^$PgBI8Kl z;H`!a@Bjy(5^JE4p%zAAov`?lj~YI-M@>O({3JdgJI6m&@B(pwCz&`o@;Pt$CuyRD z4nej?@BkMPD}Os7`ipdOc7sqm47$=+sDQq_O8>8-h9@)&_h(tj&62 z{?0k?6>Hv2FFYYm>1=8ze+aRQ32qulmx68p+?C60S7B30Z0ga+^`Ac&pB${)&!M2G z`5{It+eQM+#VmiL!TIYm*;n=VbtUg-o;^_6)!EINBtri^)^2|?A@PB*4HGrHAyuN- zaNbi)$@k5C>-psypEtd~-FoauUH6$5`+;Wr>-(yI8k0UHJk4WKmY)g3p#uTY)<8qr zxVQ|LsNKO!b0;p&o*1>`e-`gcNIqM5{^~{43yw^|ZoIp}-q(y>9E<4HJ$*I3_UeX? z3-uQ-UZ`zts--J*UhY8BN(KlpU}>_?e&C}0ky&p~GN$>*;|dp&sTS0i^{Ftv`8U4m80JJdQeE4I=Y%JHa9fZUTkh`Z4s+WNG-YFjjEvcB0e17 z{HX{OQbGN110bsG_K(Zj9$K{i0Yk=EO%_VAoO_`q2*&^~4veyG?Sd0_)iXtJ1gh|yqIAN%NQE_P=gsQ%fkxR5{VABft@ z#1V7#PKNxkv9{ot9EMo_F%+;s3|cVXG6BZ2Dc)NG>n)@5Q&5ELu=@{Nw}JP!TZC{%1^5MBUG z1J>x*lgzo(G`swtUCJqTZzSfd+`Kc_l5^(dk-FOR2rjfC$!Q}+kXlWjtmSeo)v5yA zjr0!|GBi?C1!~doQ*huCm}blXH-_eznxk4ZP&nXGe^Mh4s5mtO;}9OlCIJT^V=$za zACfFcO|7XYuk!8AdJw`=0$*yshN^Y0*Z%i6ci$hjE=0dGASRm$F@FqqO~t{+!XQ(A zfRHvg0tk<&axB*2CA=t%UYx}7ldtB zCEk%K?9m>l&z=}pg!J$-6|lPJZ^{kP?ftG{$DiW1CgxY3x^U%eeeZ$l?mb63e`(sp zzR~G18NudkMCCBuWMj%h^H)B#Wb?Dps}oDA4m8@W=XyU%Kl^j-ru!Er28XBl=?eqm z#O7H)Qyxe?)|BEOli_7d35w2~9FsXMa_0|?JK}d8!+86`B`kNjeF!5rZYe^{UTwuJ z7D?KJ=;h#<4q@MWr31?|WZaEN&9UJiHPgsqNHA>rsTA*py9Xe37kR*86{(dyZOqX3 za*A^=QlcBFMQ4{ih!&zc>P0pfHAG3Js~5H0Za>~@|J!@X4@YjnVBTMw#qf#CK4?Fp zwL}*xO~UFEYjtCbH%3+_>tvm9A;x@~nMb^Ec=%I>6M<+R@m3~Gf<@c2`ovj0<8iq@ zak;Sfftc(E7j64-=!Ol}rbFlZT05`xw2Q3)%0|QfUP2KDbiIGN`!IL{7Zs$wo)%X< zqp`x$@^j4v^;bjwurT<=x9&5gfP-AT0{jI==lYv1zGkbpIUna|vZBm_edA4;I6QO^ zScK`F7qeAydA{b?gJtjkW78;<7bxc+E!F^zSZ8=-qXX74~UT{Lrq*CI8Zy# zASXS9Ul@mCAk@*;af!gXUi;A&yJ1^J@Pf^rnsj#MV>$v%(`E38-5ED)R6%rVeTG=G zFy=xwgJF6!HG**|L*glO);;j@(r4q=rX8$I%Cr=e6jz=*#Tupx({P9?;JMDKf204Q zinc*Jr?o>c_=xOfLR%H-13ao^R>M`9e^ZYdP4(QEg8CC41iqY9CpFLk9qqRHc4v_q zn1&u%MvCA_^Kkq_ATQ;=0c`qF*M&K)8HPDj4!EjOoVV5fylBTj+D#v zWqbw+j%)|_2SaL^mrNO?c5L%sQ7dO=jE=-D1Hk2ulh+=bzk0fM=cL$7AzlFGenb|a zjIGzmr?{m~L}Gc;b{dv8T-odA-a%DvhP#Kus#9Zhi)fr_qYC z9~hS(WJsGDw)tBNKYn?6;%6Dhk2c#Yn(Vn3?LUp#F*S1Qcw_P{AvNImSj6Y-!1`0n z`i&LMyN|WSCl)=uB=P=PAKtHH&sRZk`~k0+3Qt3UuMtHlE7+Jmd3lk$CdEUOK4nRf zIP_!T)?Y43P1th+&6?vfF0w@3-gdc*T}79flMQndR^iGrCN72$;sv5~zB>7YJtjHo=gO3o;dY#TL6R zE_RDA#>1ce;pTp%7Omxa+XLuvG$EQ3M{_)=-#2x}hx(1Bw$mMTjU89pg>^ma=1{Jd z0%@%Nd7b8e>VJhrU+7{YErmrFnp!zo&w8%)!>kj|Kbtdk;b$S5J>Fq^WqSju!DtVo za9$>xznO)50oEbrex!y!u*)Z=I3Na0Ok*dMuOSnggej(Ut|tGX=JT*M>6yoxYS{h2 z@jk+GL$L&<^-yD?{fKJ9ORXw}7xjX>e5IG>gbBfpvg(yNXW67MMW4*k@xgKVsMWwU z9$=b5#UMy+2{dF$m}Wb?w~6Tyrq>u^rA(N$+UNHX95t}jcFc0*+^+P@+J?p!P9^%s z&9irw`L|JXN;B?n4+B02CWh9d9p(A0`XwUVhzoU3kU%l4V!BJi{J@(n}C;k1?lE69Z$LrEU zqVva^EQl9>?1G|&6MmC2_a)?v{7DELhS>ugfr^uH`rk+c>68R5B<|7Dzj>XdZe?!Wo+kUZbz4Ki zw~f{98*9o5FjadLkKhv*$Wd4e2VV`qqH=xN5@iB%X zH@(m`u>Brq%<|S|jg1%cy>3z2-rAgLakfXzsgEvP7q|OJ(FLJ)aV#4LoQg?Ww&jXj zJQUe_9jVdJZba&eX8S`k-<+UNp_nj#n8Xt;$e8D~V3#9OvkjQrAB0XVbTKUIu}c@G zYlJXl0EQ51!YM-t2bdF+y-JjUZ$^5UIaPMs7p&a(*uqu!>vsj}Qm`BJj4ASnDaImE z%ypPCC$P|>czed?dBzIQID;+7zEQ-;1#x)zRaAP^L&lD%=t4bGIr7S2O~FsFLXshVt(Pdi|3m=#M!x297p1b>XTI? zt4(=}kbV+2grsLqG7z+*7DGWI%(a`2; zD)z#NG^TXCA!|zLmMJeR{n>)0?`_X0J5zJyOy!~Dr)W@Y%Mw?A{yRMmZTJhas5M3u zC{RddRVf=Fw}<(sBbqq+RqT)+6)Xlz7D{+jNWvpS9JNl_p1&x@Aig_-)bI_=0;(kC zkS$9$82y8V4~En#krYB|)1)AQkGGngWQYv8X%4^EMZHnG1OrD zI6h%yKGq=KzKr2nKV4#VGwlyH?|j(!`9m{ecU4?CdZwlEJbR$JF1OTjYA7O+O9Vd2 zKJ%Tq9|g`_8x);A#$+2AS2`-;;N1qRTXaECTt3z>!G>&-B~y>+d;&euR-&`-Gp9Zl zwe6vqAO2s$o?n_1WAi&7(r*vZ?GBF42sCC3+J@(tU=N8;K4k1g|ytMJh0qlRFI!{u2avp)XT zy!TdH&+RHa!Gb2o9tdR?1rPKo&A$=-tP3U7x; zKb!%nC(T@GSiMWGQ-6Wf2voUFt;~M+=cufFimbnQM7-+`B2~Zi2s&A$E~&rzi-?cD zW7srVzspmT>>h1#iz&oWDc+(zZFnFBLFk9=`d>xL=Z zz9{aO`TDC%0;8xOv|7|#$r(En&DCA@q{EGWFnx0Gk6yVybp5#S9Rd1u26fCWxSNVy zO(pIWGq#kzLnEX$iUw&C1*9v{j4?Jtjis>tV-oB$4H*-)NfT$i|J3V=Tg$3XU+Qbe zc7e0yJ3(rOb!66xR)m%(T(#DHl~ zo5SP>>k(8LZ5yL>cT=fAYIf*H?4CUHgQFF%(+f8$$?DL+(!TMZxJk%^Ng z#7KH1B7k&``r1tg9%|{NM+HIAIF)Azgn|s25d=6|l!2c73E7e-5)Ea{0hAB@=U_;! zLL1b|jNqXp#*qnxKp12Uor{d-$ZF~5t$s+d>Z1m#A5uU{3JvlTCKG5XOt}n()H0gP z#gT6V>f(<5N$}C^>Hcy`azFXK%|D^}VXiNQ!hXQoPfqD=y%_}<9Gdjc5oa?JE zCJ+Ud!^->sM`Ny!(Z*Dsr>OvCf&Dmm_!GU4sbC_AXvQ2q#Ni3l=LGA-n^P>@VshPI zFBrWz%{^|{#Mo_*hJLVYXX(MSy>-=GGu>nF;v{Fb_1RBcxUwSoNbnyG_l0is*X$du z&2V2<;q~?j=Y+C*v^k&v<~l+8EWjEO=Vr=xGUq!-7kG(-$}^{MO8KHK-!ty{VO;Y3 zjJ6+tSQcbR_A#VD36u}hAu~h5_Wu06vR}Mc{PXv$(<3%a({7m@y?a7JCI)iui%Z-S z4tgy)>=RevYbXfRWRKP6albPRbkmgtB^(~d2Bpa4fcYEmU$i#lY0Zk<HCX5{HAgHc+);?qFkc$oMQ{d#1yzi(?SHnG@Bru zg%-uch-gcc!oa?^LN8-6=i!WrF2~{FPXb{k5s2mFO23Hx}#+7#Qd`nI}DJvDWhjoygV1H`o`*6lu`t`zGIG3zYmocTxHUA|Oz z9#8YdmJ>CN0BS&$zuXo3o4Iih{yA*?U!#NPeHswCmy`2RtLY;kwJ0V_(pXlQEVM@H zD4^^(Y-hlVBM=koxKa<)aMlhIiUW+P(~LX68MSU%>d~^MYxV3Dq!!uQqaZcapwt(O z*UAoeM&5n+#W^swefF|$`|}^?d^>(0RpX)AE5^(*wsDIwL@yMIyg~3*jJgMFRQi6T z_AnNC>kEQ)S>xwznD|%oe?2pIdrHQkio&C1c^4Zh+t}W4SsV{2h*6%~W$;(~orG!R zu#~X~YG6^q5FuZR)KWh4l`8WUT)oK)3D2VfoXlZML568 zXyl?+oJ>v4g2?Jnfk4Pcj0~Yu%j{(0|01OBvDaO^7MFY|B=WOSx>WbqPu?9-?x8;t zpeyZ1>X>Br7?9fHt1ndoEfRvIY>`L}MoV`csRcC4XztO-TLIib`kZmv9NtKzF|n5a zjLRDJdfv$ReLm)`-!yIfWAysmBi+?Cm;1WAluHb+c647uSv$hpfj8&N5sz`goB-=zn}L}dl&GXZPTM4@($DRzo00j%8^Bxut)VJu|Pj`0fC4W``!vtQ-q27tOv|FlcM%Mu`G9@Vb?grF3+ePp5|1S=$sMJ){)VLD1)ws zLXRkPM(fmsgRa_AcjIACeVJ!e&RA{Q6y5I0^F9v#i}6SE7N?!Qn0@$MLu>b?<`!Xu z#I768WmAw)Su)0$L98Jo?r=i(D(lo8y>^iLfmdE%JhIvLtcf~mLHN_Q!)CBSq5r{_Pag7D6vuJFAdP}gTFi2DC zqd(wgIxsS(WJGkHi+I)r2g=UEw>Yqc4xZ(Wjh|~%` zQdI(}#XTBaPsvgO+X)*xtjFtrIYayS-%S%rxaelZ?bFOsAZtM#HOab@2|89QITDA5KtADH z{3NcHT7D=g(pg?8uOfD^Zs**>bvdR3MzjzXKBc@#*o?X1#32YYm=NbDPEibwe08^T|PvTCey;M z=KN7HMF?=-E}XexwEF9F*vS>FO=ZiBzaib*l7nuyr)p{&y4c#vQe&@j@^w3QvGtFB^~)=h1{Z9+`fNGE?4Ln%~#Qy#W|zEPR% zuyC2ZBPcX!{H!(JznUMrAvrnEdbB*hDL%EY*S*Nl%*Yo)Te92K3 zR+jFjZ@wZNVqn)DlrS1;tovM~nWd@wQl9W9U=hX+aMZOHf4=YbKBge3Gd zWqX)K?l+ZGHw`3Nn80AbU!N@!F=mnoFpWYD3^_-O$#xfGzPrxmrM3EM@_e-U&Jo3K zn&L;^ILrd~lo@YN_`}@a%rmV{O3o{*C_Bup1!tQZn|j%rg-`=eR8SOpnNX(xVV(LP zk($dCK(U+BIauKBAvJV4Ahn`F3nb!j?>_Wv3Dcb5*>(A9(`B)ZdTDyqcOyQV7Pc`c za*r6BMcbUrHkbpxs7MVZ)CJB*Z*|jT(j@%i3thD76PJ{FE=-|CKj={<$o7GpYZA0y}3nYrPU|P`x;N#JL~M+RMXeZ zWP)rtL$mJxuU`QRngNI@1^!KCuN1s0Qm7!sCwz#ICj}bSaEhP;rHm|ut#Sz$NvU`w z(&0-bv)phnpy=iM@a?|6hg#mH91O!mqgSu4yQ(B9JLuZ=B}2J>|~B)gh$qt zq~yl8j0tUb7O9~VB2}2?Pl`!5XMXJG`VIF*ZT8XbWAWE@*@;o+BTl+9FI}OJF4x<@ z?%*^JV-`A&x3&=H%d8#4Z%roX?61q_6be$n4jnyzI&`Lo#|+_X=R2jhp*g? z7T%z?zcxEiD->=1bTV7+iLrjooa?--;GU>mlVZ~!(CmD8_PS4s+wxA-)wgws-AaA- zOU*2QbufB8f1x?&(6Jx48HP912l$?!?6lHSE&5hBhrGkFPs{ zi$ftb7G>zv5~+tvxl%^hej7UV&5>GAD0(r(LOy5FFt9k&VK2LC|FL=7LlK)p!V|s2 zcLygFF}dMnu)3IRoQf&9ZOHaAWGQdKdDfuaH92C6CeGp(l^mc=cAxQi(A>n}If()D z636OO{mj`e`gD+*mgcF;gW=Q~&B;%j>#wme7V^*+jxiRGFc-NblsYqf((aqC*~;al zYiy0{(~q7!FS;0gM|MmImYzHJMuQe38RRvL!ih&#pU|m6YT%N2Hx{}2>e}tL+P+uc z-{tm;x!=}tKK3^Ms1yveoFa2v8Q>XgEN6HaC4XR%;1bQ1d1l(JhrvbzW*j)iREQhR zlsKn)YLdszUib97X&Vo=Cm(J;*>t6@t%u77&@Y${x!S|+v0}D{OU<~6RkNjH`rNfa zi?)r6v3NumjxrTFvCv=;GhjD5SnU|-ZLs1PUrjXSOw}b%T(B|Vxi`MM@WUU^TD-I9 zM6$KGvhr+eLzTUwQMs$Vlko}S1-ATqKF|hUfDS4K-6(iv2r3&MDTEQ=`1$HKTG3!2 z0&-DVkb#7k`n8&!Bw)asXgo3wND3M{qTY?%R`XRol$}fmB&+^O;@}bGrLcGy*^-4U zK5>-H|KTM;jR+J0#H1{ILi%KP(+6q+9Ugv_)Z!-#Nr0L(f08By$Pkr0NduY6>329l zc8;mt$bn&oKp4c6DLIlp4<4B>f%0)A<3>MmBza#2Qd4VcK_KyXt#EGT%FEfE|c>|(NvGTH7iTHF#!{xfusxN^&o?D_W(=WQ;x zR<&@_W-BvH;&PtlH_;6s94Y0;u z9mxhdpv{5TIHBqqkm`bFeu510#YuV`h0>S!m03aMb5gK?J~%w6x4;mGF?wpVy|nB| z#aX>Hxl`hcI0k&&OYcv9O8b8c<5zCnQC?nt_DDrrU1e8e-Q~6xPRSM+jkE`@S%0AY z3il;QJ^iJnXsk@>e+jk!D1;TH-g&FD-~Wiz$^xhY(_FkL^(J5%O_gQPq|)j&C$3DG zzh=5VX>7!9Uu`D4+R+xp1TV~|>aQa;gFS`+ERq(u=`7%{S4_5B(A|MoKh7S`o#kWm36LSZBo*V*!rs^n}QyiL=+t z_@tCg$0f&W5P*mgRV=6t{tkFVO^E>(|AW-(yoeZb$q8_F-htHEboFxJr@ggX964gC z>iC29!?AzT1kYR<9Jz~Lz-={@LO5kG16Yf}ureMdkVZ?XWkurw(}f{KOsSjJ%8~CA zqW0alXv5z>w#-|dnN!(yritYYIbOh~ps%Z!!`$t4cKfP=hM&eI1-$ktrxBN(Pc}2^m=H4zY&0)Nz zsPhiXB6on#cQgqw0;rW@Sqfw+V{eqbgba|_fYD$uO|p*SbO6Z`wur!^f)sJ^12n)5 z;(Z7*RN5Rz4nPSF8(18Wm*bymUaAKIhCpgEQjr>ZC@*Lz!Hb_%Fd~G95XhDQO`33q z#2s_Lsh>EG*h<+cg&d{GG}Xf5Q7dRb*5peK-l(46G{+$VRkjcZ1e6s42gp}u4GsLs zgXc!_97$CvyyHksF(qRqli}Veu7i9xV{By71bv!M*j@~%Mu#Sk(dUlVWsfoDVV4CG zu_@SB!<&w5b=O;6^aaj3_P5%+B9hrRG+CSE@!|*L=dOK7yUlyXit!PNV&ii}GK*Z! zQMoP#8(#?&)8$~q;;GMcH)N5li@`d^z`SuG5u774nJQ-!u1{#E^>3+Kms~05#HGH*MEa72hBj$C50JJegaem<= z&!=N1KBN16#PXQ;KS|5Xt2%z7{={*y+qZ+uv#)Tth%lyRWl<~%DGle#kQ$4!X)i7T z3dMloR_JG)!fnnSLTXVH{qWS#ZAWG0*6*3GZ+LQ5?gZ`D5aV9Y@Vy-0;T!?S3SFYC zuwAM5EH53Ep6O!D9AnI(QSsB5$Xx1(4FybG`_End%|+{fp-=ot~`0I)FdKS7HB`7`Yh6MGi32C>7ZkxnYu(|2N^Bi^LKD*_2lra|D*pjDepj4 zRTZ6%<_*ELc}FQRL>C^`PohCmd0((Xf;GX)SWBMH+AHRRfNPdGdhIQpz0Ftb1+_ij zn;HMD@K3y6Ug@!5higQt(jfcWB!!Yr6wP46(ae;t$M*ajicd@SHkaSKFq>oF*dy=p z%4h7beq`aw_}vv1mE0NI+J*h)wQCsDHFWj?(`mK#-!9w9LHB{-d)R*E6p=MLBAWq# zb7Z#c3&UweZp1OiCb zkp{B6=|ddCiO(B99)MmgFKLpU%!TX-hx0ehSItzWU=>fn%ylXMo>_4vNFl7qPYBT@rG_f61cy3F0~ZOR;D%5*YjGPUTT z&Gm`0_(ocMqH^(%(OaC2ESXt2*~2ShAIE4<4BhDY?9%U;w*2H3GN0yW+S1YmX^o{kHQ z$`nVh=&i2WJonJu9)F9U^lao0X6oMAp2{uHXHK1Mt!=PlZi8hv$~2`xl~#85aLs}^ z`jYl5+@Lx&duJt52Zrww;{8_W_ta+I22vvh`UQ~qPtmExutF%302A7DW1l$os^DDP z4`;;&&;DRS?0#hpz3K_ zuEu@7n$12l-u|U&%Z#^Dag+ZNH*wLLAk&VKkvlOO7jPd%&5ER`TsJ*fpXMx_XhklX zY`2IU&#+vMy7gGFpW7}*zOsJG+>hSfl6>maDY_3G5bEjR14N42LvPEYa6?p9|Dc7A z1W)?qCgGxjm1{r=qTO=sS}Qw^FLLG9s?5Vvo{RN;;oXrhtZ`kmhxREOByG}FpDCTQ zA$O!v*n891s5{@N4F9MM->7Uj;AJQuvB>IaEXU~1bzagW?VfQ9*8Re~p6zMptLmB> znme(?M4P^BKYH12-hb%9u(ji(cKB-3f$349nM{RoEU;@>2EF*EO-N$5`jeOt)8=?b zrA`b>9R16Pr{dP{DLYeGUViFuN&T5a*SartbJaSFAj;GV91stiw3NeqYLn^Y7sB^FUu=wAYb~j zW3p`$5T_6pCKs>_`m zzBeRdmw$AMt2t$)F@3awtsEAgaGPJa#U~;UyKX0ajs;u>-_$f z@XV^5dE1W#z4&_2YpcdbY-bZO=0JCc=en87J)$h$kvSfkEEipdlOY}Ftj_|}JR=GM zG-X~3Y=K(#-Q+t(rMt#v`7BzgU%UC}sbipYb6XGBE{IdG;V6Rfa$jY2Rb6X)>6ykY zwzEHZ?airwjGOY(XF-cBo)IOUkv4WkafYXdHq}F$EZ&+74??2yC<58xTy!}&DT0Rm z&SK5f*^uh2&rrV2Q;L)4AD$Bwo*5LDiW?i1j>#EAkrAQkqi1b!`@{VIo~8Z$yr`9l zyYovbjvqaB=IGhx8YaCJO^f5q6(O(4ad9%UEZxvZUDjxy`a%LojUXL1<)Wl8;SM4- z3Y47m2Bx_Pb5D8AcV3P4eDyuw=zU|D$2R4lP&yn+(pB60HT>ii_=JB)N4K{2Utx0l^u{uXs zy*1@N;Us0DDrrBXjj1C|$xg;(5~M|O35ai4UO=P`D=enRU9@Sz3)Y3cwdT;FL-aU0 z`0aJ%A-`gnC6;3xks7duGfKDTSH&UVr30)v$)~;XXk~Twspe_VXnp^>%;lxk(-I1( z8doiyLO6PabfXP9_ZV3fvN`KSV;19QTzCe|^wE`Jtmtk$I6BIPy3HZ;lT3RbocI22 z%h8&1wLM*2cP47*Y`49j!~XOKdnZM%=Kuk+7!@UEIeZO;ewrL?Md0L3n~>umP)1-Z z#OeA>0(k#ED*WT!`|``n3$iQAvwG@|UaC2XLe1%C$_=XG=o?XdG4s#Sf?_J;-|9im zBV9oUT7`rj2?46e9pFJ?574H?FjaZ}`EscMK~f|OZ6NOe0v!JwfLyW&z{+5hsOhVo zFGXsylY_Yu0-un+ z%xM|yx*rt3#XLSk7nigB+KWE2eW16>q|47X)1*vmfH5Nb+QRy8C*a>;!9$j>A zL=KxhUBi<(e`(^Z71N$K8WXK=W*ockc~j8K?~aeyDW-*EOYaHAj<*zO14BW11*tPe z8#0hW;HF1})lXCG9fklY4vZ-q6_t5c`0kLHoqvk`U|(VR@#?0twOm8bXiyN}-G>p@ zwYDx6t?g&)+Rk0FZ_7FT$nWM&{Y%2cMf;Fr3QT8_i@P=h5eGVmwerXe@5n5EB0Fa6 zxr7(ztP_xpEE?w9$-n?3LqX~+Orbm@^8^Nk=LJOM`h{ishoz5=%nZ_``G)Utp0&yC zx!1otQ~%NK)KB HG4ICvCgrn^?+Zy=X{O1VuqCBcItg_Dc|HN|0c$5isu(_nrc7FV&}~7c)0|X}xcvI;U4gHc z`-N@#o$kZ5lB1RN7cVq6h;87kpHfg|bR>Jh^{zqTD3mDItvp}o)S^QvT>64hBqSC# z`V$t*9Aw$ocD1{a+pG>%HGi6MeA4eDgZ}!u(_h~8kJ`J23g4BMIserX#1kIRna>>1+`C|+f&bm_eV&6S`2X{$x8G6`zJJSn}b9qN)hrRT| zm5t>WR#dc1owp)z(Iy{l3QJ2YSNX?QI4#T=J##n5v@*g`fH=>Ev8&cXrqa3UtYXSY zmrEy7M!9M1<_Hek>Hd4&pJUc-FF2NAEoiDfQGX=g-ce)kxkP_tpvjmG#|S~R6QNW8 zJ0dj@gUm-EMYJMRB~lDP2lY>45=Vt3iA1~!al{KL>W4rmHU5CsB@+=X<@$-HAhneF zDh&fX{3;(Aj-Ro_fMnG_Nmlw*4>=C4Qm;YFCM}rQiGvtYK|Vtr68JP*q8fNwh)yRc;q*D7!s(oK>&VefUvM^gui)W*+EkjQ3IIgqbcNC=VaKPF@Clv-}|1l@YC8h!i;InAggqPm<;{x-x{V991ExHdk1^;b{=iF^U zOOLo3%bXS^W069#QlCZm;DlBVR?1{aS#kVHAU}C)caMAR^(844meZZ(M;m%OxsbQ> zGSkF%=Gny6)kuV{_G`7(7wa24c4k@rd&VNSr;V<2KlRq^8xxUoPgsU$Y=wXPfzb=n zkZ(dCiAeQ{Oh+^!0PixFf8A6*Qi8RTqs(`RHyjvYu#DuW7Pgz|GZ_GQMW%a1PV}PoA;dD=Z0XbHPSnPEo|Z^bJIgn!9c6D<5cA z?F6aotEw)yc5oz}FyIzWIm|>12m}g?5G=-ME*yWQz%fcGoEPCjQ|x2+4?`tF&bQl- zU$s9Lwc2ap8V}t*hB1%?VWL_U#|*79p~0L+4h?`m6($1;Ib(DwuDVqA;Cs&5;r*wC zrwyxiBxmI1X6{c*e}8A5^DlLQp=r$Vj?~!hU6jNoL4ZTFA5mYT@iPqJb@O!fcST>n?z4vF7$w>I%Vj4Ah+t#@k*{bNs# zUR30yD-iuo$KY0sIRQ;E%GCnm1tWDOI45n9D^?j%IsOsplR^`}GjCPsI%`gwJ+s}u zrPls<_$L3CKYqZN7J#h?!z5)+iRFF|CY>S~b&GnTMg&G{ZKHKXBsfAZlJ$%`G9o+= z12)g747d3^*=XQDf3w%q@&6aT{Qb|iSxOI{Jawj_wz~adLm$`CvR_YOCXGdDFG}e} z8@>&G4xjTw#Z)CQBG=K6IF*l-w-Oh46R1jH8G%5c0g#gGCNeV#xI<-pi@&MRpr#K3 zGM13wrIHFUDtR~cs6JH+u6oGvOOg7_V602YekqAQyDEWM2 zjxvONsfF6wT1Hm4fq=I}n`30S#3VC0k~?+5@Ci!fp6kI#C7iPGz@Gut>X`CP{Rkq2 zk^%s%iLz$|uog(opqC43g~09QI0Wt}yjE$qFW7m&f6iJ@O)4lkOov+Sqt9Rk4W$0s z{8XO>J0?9B7yJI|B3s6};}uC+1=IhYF#7p*cg@`MpNn!mBhvh|>ByO3CQdYFt-Tkl z`QryEdye&F7S+^Mi$e;#udw-qGqSH;>b)!^0XGphGcDd%({z4S%Kq_xo$vHl^8`bp z>!R&JOUl1CH|^`Q)5R9E2qDS@Qb(miHhPL9QV)|PC!OV9y>+C)0us4t(%d7H-6K=E zdV|H*|5#`lqc0o3{3w=qUVnQ#@Ja3e%!*yHGc!BCw4|iu`0?X4H8u2l`p6KKDCD|W zv*tglMyxEl>H(=o%-t67>Ia&YJ3#7& zN`cg@-zqJH_8@Ykz4RkBIbwySG$3HC@w&Psky_rlhEa2SkNrfmJ#N>jaiQzHOnbys ziO>hdFih3=85$`7EihU*Ou<=$(AY!-!#>WZWo18bR^s%(y=C}dXHI6ynFBc|j+X8( zI{w7mPds1Q?HXA+BEmK@e1}Ybn3W~kk0!%!QPR(r?%#E!;l%mco=defc&>7$OpH1x zl!DaEV=!@x!YFT zby*!BRoQ>D@^IjsZR0hmF0+&P6-^v;W>O2JzV5_2f*kyyzk}2x^riRc%X!~5H`Bvh z;ikK{uRY}65`auVY zeY~Z-m7eo5JTC74{CyHUc>S5p^Qeek+TORtLoG@mX3V+6`1BH1~86A8%}n&9f#6E zDmjub6iS_1l5r!EYKUafZ6h_%EF^G0QVTguNROD7yLwIBPk0%rWw~U3JaTnF*cME= zoV2;abYryHPK)+pfyRv4UC*ued3EjMGnQ;i$vIqJc;@)Q!&MD`irYLTblbf%cXB}< zcPF_l+{1Dejflu}jY?xyVf0gPc>X%_mkZyGU%NN2 z{LINS)z}_0Fk^ToVS0!bJ{+WOz1)w~?qNGYYRvM`{9r+bPDtl3S~ht8clW;J$Z?LcIBE8} zuqv&C+rzCgDw@+pCe8Zzql{yPN6)rjthZln=g2$om=g6*(u%PN%Y5w|n+lRr1z+7m z`igmiIFVH_z0=-aE3RirIn?~Ec}ws5?fkLP+XCOny=(4{Z!F4k3NQ0BpLB{U9<8;q zMxgLBQ#Ljl?I@jflr|sdq{+wDj<)R`o*fvr|31ww?-$)Dv^F)_R*r?9R5qp5{g(;PTdEhempOXqfGP?Pkgfy5`4i#H1E8n{l+s&G@RsNq zeq^%a0T6j0L#16Wus3kR7D4F1#+x)r1bS^RXn#rei-Y?1Hmww6}bHMBD6+IfWqQm%9E7A2uTomYC>JDI~j-`#$^ zt@{(}p(kF_PI^B2?%x_b=WM+9wZyTD4v(b91NPX{|ME_UbS9R(yL29{QS~+Y=LL1FS zv>jRz!z3)3JB2Q~sjU5hIV%Ffw~h`=g17xJJq)B~fN{4rWpvaY|Ak3DPcEOaWJhZL z@xup7+MCZ-R-HOr*Sb2t#rw&3{TC#o`i<77-J{vBly|u8Qy?|R*uK2t)%W*g9z0W5 zS7WE;baQdE7~(129_<69M!oLhI5^oUZdx^WB#^N&ydxuSBjNm|;!%riqa#a4DYz+`F5A$Qk&n`1vjJE|fz%8{JtFda z*?O>W>*T0J-+3FR$D}#Gwt@TE-NTaEL`lD+UX(;YWUF+9h~vH^#n=_U5-7UK7>?J| zTgS{v^q#doXvPO_zYP!g-Tc`r_iQOVm4EO!3N;c5g@~36TU6P5M_6>n6H&>d_t6ap zg9E}HVG%zCL`tilLzvQczff22IH`^aLMqs#V%e7>g`A;f4qR1QNe$vv`c)65xILtX z7#PC0vfdr3y;VO%l9U8!N4DQsJ2DP+LDAHF)w0}bzPAyd@=|cv3nfF73h~6@q3%>t zhnXWdh8R*L5)uM)8cs|S6X1N#y|LYW+_iA^OiM>mi~Sez8$v=q$L3^ARK{pc&hVX6 zR3#G~x7h!{)>x{@9 zcKSf!nDE_b`j5<8^V8XHC*_?waH8f?XJ=b?OW(Clv0jaE#V|{euoSboxAQ{Vr8D&n zJMzksPqjQTYuUZO(fG{YGHTJ@d$qQ2=!$Xo=xolKEYHY&0pUA@QC3vi@aaLD_KQsS zjYx9~Pscx6pEuHw!#yU>k=sYS^sdvN4L-k_^C#^)rguJ1&pmkJP*v@zy3Te6k6nxg zRhXs{9ea~wRSqAiC%m*2q;@h`MrpG~YliEX0dPd>#;R(Nnt`goU-A}%9-PDMH%KjL z5;XEsR8Asb`Ns7V+;Mifx%KMVZu|e5)=v&yAE4dOTB>Vg)|jXqM@Nkh=0<6A?ltF* zirmZIpYcz|y}hNNu>4eY)#>ie3zs@BayDscv;DiXSBK2n5i6W)`)w1nCOe~@RmMh854=KxkY3-&ECurf3EYl+%t2%w=R`EabKIA$bGDQJ4%x~Qu_~%K)1*= zSmYL&L6vbp4UPm!2kSNG7uSq`?c)b#zVTb#il?-1Zp}ZEd+5~Zsu~c431QkZEJ9}D z|5r-RTdfzBHu~TI;2VGo$YCjp5w^sXqie_P=(#+OAzz&zYMFY43`O?$PkrMbK(qQM zvmE$=KXtBN(xw()^-zS{Kx#On&I+ofR?}2NhUtMwW(-vLlWbSZ;^-j`zfu>ny$vYT zFtht-q9Lm(IArh)-F_fjR@Og<)Yt%FiV0G)TCE%+#O$A9DU^S{Wk*%t#M$qSHzqrU z?FV^BMX_aOxXv@C$a&FT=jT88R>bOWJr}vZ^msv8*~P}%_LjzmihE!a9jll^sF(Ovqo|IikZvPby-v5U3^gl^~1 ziQyMk+&>bT>Jy%fPK}B^%4i*>&mI-A%Vpjtp3lXHJRSPP)3ev@$}B8BT6wCv;Y>Xc z$f?gXOR9S~ty;jxm#tGX`(4svAOGSK7UIQFK|_5F*EvU~-!prg-;DR7R%~aT8l=9` z&M0DVq-G{ff*0~hESO7}Mg!$4ZLuXBXe(>Adp~0i(eA)DSeS}MWUG$qmNibL-_(uN zWV2CgRQR58Ge7>`jOB^x2g)msG&a<n7_6 z5NFtplT62iXG}Dt2mCdD+3u3O!>4O5Gyu~*9j(fERhEcCh&p3-!>#riZzuWvLGSkL+fFmqWB$Q$WcNfB-mNL(JtE3FGD?)49!fnb zi!bRe5%}S4&ZtQ1sK|V$$UNuJeJ$jFSl!_(m#j`M*X9sH+B ziwUCZ>B!S#Ji=3h!uL)I-Q@RF%o8ugtw=3hos@1VKXm8>XZtoF=T#QbsvSkB8vgI& zQTrVOW`wOH@JU1f2zc;I4-uqHCcfi{nsnszuPGXMiWWHlsUge}#T@;TY~XLe6frbQ zf>qD$AvId<0EUpPn&z$YgeC;H<>*2(-?1!?{=w?vR&%`V_>_?$liDgAX}i%cTh~8} z)QDAq)Ley(T8+pRatV{~m3b%Ptry15`@}6`Kjzwv{d-%I^;-&E{x8~V!7lE|7#(p7>5quYLcDPOpU>xj)@1ul_gz))Lqy{3A?P%D%$*KeSnodHe;g} zWV(c9v&9cLCY+VlY#hg7;YLPEC#lTAQN89vVt#0aDvAuZ8lP2F+){Ze-{xi1pZVl<&LXp`%%qd>uUR(A2JG;}4)}O9# zLf~BPCIf~A;=1*#-PbtArsra3bNAIgEjC*!D*RBN{Q|@|Y(}+mR-H`>tMcM9+${i7z4d2+;;PU_2dk^qBuH)`|(L2FT zQC)6v;w0Z2r+hAXlRR;p;y6y?$d*+pkrGMti(63G)G5iLdKV?JH?e}~y%GSy3ibw) zAUe@|$9})r1FWtH5&~%!`HS~CT%No4Vo#s{%$%7y(WypC3yjI2d-<7nObK>(IPQ5` zJfX2?4B_XB=1?|)+6 z-jG=mpP5~}yWrfJ;|=w7(t%EKBX63R$u#_3F6b?`yNZ@_S7cV9Gk2b-JQ;-!iXnke zo0nNSPt5#{%YeDgf+rOo1F5Mz-*R{6qo|u%RWoyKNKNmJme$R8UR5Vh0j7|uFpV-Z zqk)enpgHV{v+CQqQCC&&)&5wujyt8B-Fw+enh(|Nx(1|XJ|St6ircL&L2Hrop|)(-M?8v_-jrMf)tGZ{Zz(tQK4&O%H4}I|H!uCAEG{qJKA`l zydIAm!RY=ry{E-sJOoTSBrvDY-M*$aBBV6cRX4RaZ_g|I?*GiWclL9)M{V$5km|Ou z$YoIpL=U<&)sZ%xSgFyV#(1mb9}87X@{LLKiphY5VApS=BYo=J)ptI)^v93JZb~YQ zk4q>m%sWt!L%dTCloY~jTnsmtjDoRt%)EMH-ucCNka};k$kf+{)SjVRE|ICnLTb=N z%^#ploRP7-Y8?`=MvozgQ(C9bS)Oy>;w|phtuvn8=WEFWsV6zUKx%{j=ljMO>5Hia zOlOdM7o>T_q~7;j>eQcEe*0NcZdOs{sgtd3jqQEy9fOz%>aDH4`;ONB@Zlx*&iMdv z*A^CfF1RXYGS@3QKQJo&J25-{#{TKf6V0U+&8T{MJ6dEjNL(Rgma1iPlaQKz!&6Ik zrw2NQFq}sh--t0A*xlMZaOgx!$aAaj`$hC!PrN=Y?9*wB6IfrqF}r|Z?^x0b9HRtv3{yKU^)}ig0g$0GXE}TBxT3gO8Ka>`tZEC;2<}$UpxS*dn`zTt< zT~Svku)26+W)xB@;grU*g1I}dSw5Ptz3v$bQtzje$B)#=ysA;aigT6BYMU8e4w{?b zGR_QtLO+;q=56K+&4=U3@K?OYL~7ONV{jnKc9BMzr5hy=)6(&jc+J0|qqr!JnEhC?aa7)plZ3#OMAKZPRyo?~gDEI*D{*I>Fi*@@e zTOWLR{nT0SPq8MTXH#$Bg|c_HKo|q=qf6w8S8R^^q7wI*eAM!HMQ!`mytkj-v3E~Z zM}1pQe^7m5|L7(_Il3b&5 zHEfCTf_e6UzfDAm%OW+cQ#DlfX2VronCZJD)%)pGkA>+-D_Gt5&RXsJuh0M8lW%QG zIGCMUbaYo?_0jz;Rp&a|o7%B_6EwSuYYe2OU5MO6ef@Z8VNrJXtQXm*_KMB+j=jua zUA8lM=pUW#I)CGBPrZXhS;>LJYM**6+i!ia%{X*Hy0x`gSR=i)Z>VK}Gi}g9V8G0d zc|dGxKy0$NW5=YR<$wA>?9R*s$Mzj+uDsCN-h|`b#ZFYhGKtE{>cW?YI0ziu)mJrM zS248erz}H};N=5`BX}$Hz+ftSwvIL)ojuuj{-XXb^Iw_vAJz$vJU1ocv&r`O02>FX zmrQWOHQp#PDr*MQm{USd^zv+#n4xQTsa9 zYV@nj`9pCS08k%QJyq4q-uVI7wIMZ>M-n6gi4%>Vh!XfB_cr(FWxcv(eaRj3KAI5v zIi{h$3*>m6Df+3DK#yId)8Z;Q7a2S&_c?a7Jcw#hD|mEe#mTup20g zx~~H*W=+Syd#R=O%zEuk>vlu{{!qP5!L<2W_1yXH6`SX}pxFP}{m8JB96Rog`0VE| zZHg=Ik@arXa#ccPn z#NW2GR0~Sg=BE+gNyNR&$<$^IRVDc-{7Foj7PQJ^@y^LFuHmLIGS#bF$<45Yd9(&>DAT^wj@aXI>z#8?7 zH&gEblAweQDeu)Cn-0#L_kn-Z4xc6YzR|n=Y{ejTpd;IWX}|)Q&I3eLQi7XbOePEi z4sMfTQzpkI-2H4y;3G?)e0g0{o76TC;HgwkOr9Id ztX~EVIKw$|#7iw*kc*{6OIvFxwxZ+iSs?A^A{XV{aqr#8DqBzrh=H48D>il;oc zdqVUuQcsLZngH7zlQ)9Y#ePu*lA`nAlo$w=6z`<&=0iru_v!swWVU9@30z$49u`O7 z-}|DrPkiXrdmnyr&RaXz7nT*CtT}zYy0x)ku%ofB_2Ta-QiBf2rLCPHA)Nw5 zXK1+mTD|d4K?6|gl%6HLgX75s^+9S~yzw3!(XQqw1Nh!S;qAuqpP&82ix zpr#bF+Rj5`A~kgYreQpsp_zv8lIvBUG2TNds?%-)QXAC};}x;t6&T<@*`8wxfFpS| z`u`ifW?IO4Hf?dxaJOd>QNbA~o%7(7b5dVHB@n0s|2^Wv)RO$tBSi(-^_6G3IwfK} zI4O&Iplh%bM>xHts^>3*-k3h;BMu|rZvn?kUhe$S%tL>)$eh3zO5M-_MkRb>N!&N) zz4>0o>3wI}1ZTIg%@C-u<0XoOSSb$-34%0q>%AZ~kGh)J2J9c`IM>*ic=Y_AKfciO z-yPboUiS>zI`!#&)0dvmB62ChEY3M&)=&UCDwE{t$ncCx@mUl<_4$+l$LH>kz2p0z zOaC@x#q-OHvI{D!jyJWOs_w0*9&D;dLx^^mm@;(o@Ycf^6T<1MF_2o0DRPpj6;gY~ zC>;o$Ij-a%oq4q~HT~I5-x7qgpEj}M(9ts}alTG>=!LEN_Z=(maD46^mFOCs2~vB6 z=L!l$Wh2Kakxeiqy5GpV+fgq7$cBKffnxjsMRhK29vjD>ztw z^kiR4GebwA&>GHH)?4cJ&h88K1Aja375_OO`o*MrM`tih=IE#)V~m`~&dh_DD+R$xnKEuV%?~iOTmtWR6J> zj7~zP7Nm|&X99S{>^5X-L23?aH(*+j8gzztG87%d_Yu4nb;p#KPiWD*Ty5E$yy+Xd z6*J4b=YKT){>Asdxc;5w(xS61M=P2tYZ?YIUKs4}X<<^|3?g}51_4UT#jBvVpaY=b z3oOv|gra#HZ-)2aZi2FNx$2?1gOXfk<#_{n=a1K`Vx!+<_8t|u(K59`dpJIz z52PLu?l1!H>mAe^bp54-qwGcicR+~0O^Zr{oyHBs)tUwvIm5AYei*788DvcIILWr- z&N*-VaQ+L)rDyjYKXLfrp61#MZLNm-MKK0_oqcW1?cIHq-MZzYI=(3Mn-@R*g~JBMU0#7q-Bhc& zs|?EXsf*%gI5xWf=A{`Azx?->kKTzpy6;5C@gsE|)t!BHt$K5t-ibp2d%8MoC~2hI zM^A*yJo!qb#@b71zfGj3i@e93{Gu|h5~;=70Ho%iQNwotD>6I=0QreASP=ODc(`LysUYg(?lu0QQ6*6vPaCZES}N3NUkPuE-PoMLacjyLhd*ap2 zA4}@w7xuYY+1SmPIQ!#Yzm=MGs(H_$6SWoRQGHGd6P1Om(vH@?y5|0q^}WSa?TglD`2SPTg!^CohJ70z2Og0bL>YBoxJR?+ zdc|b1B^2n0pX7)qnt^XrmV3-D_vm7;s9oMs`M!>PKSwTO5#Y$0U?*h++EhmF0rqSe zCPyy6)GXNn&mGXhlW@D99I|f4oOkh_{z>H9AEq6SFF8|s?qYRgXG?1*DlB$h3|9X# z^Y-ic2ujOE-JrB6B%%DyaB!tOz=ZYG*957lJWWtSC>0(9sZGcuL;cl=@V6$YnHe6A zfz%3}DU0`zN32#Ia=nHanC6ANb~I9}CU93nLk1m!S+2nIh^deH@P=m066vvV&L7o# z*P#72kQxKmUI-C_gCS@#Z-?3kbX-DyWO;vP*e1Ac&6e*TTMWHr?fXVw9;_8qdDz*X z9Y$(0lPsU#{m_zyD|cp=o;q>Sli4p3 zje$QzrL114keb)3%&2=d+G%v)T5P7ah&bNcriHEei+S&Sns(;+xehi2h%DNx6S&$y zYJ&!%z=Y1zUK(pOU&3^BcC^(tG@qzy+K_jA`>DP^3;w|67fYu^?C=Rs09Hm7I;=gQ zhExnL!sJW>Y>D0vy*=qyF9iHc#D6XRY|)215(bL}=?PW~y9U#p2Ac~8ljrtG5-~5}Gb_QBD z_&5>~pWP!e1s$RafDB^_WqU>E0@DV36v^F@4{-Z9vV5(nfC2}h`Uh|Hc;J=0ABtMA zVtc`%vePFk355+K(9+jW*AZ}2=4@XVR%Pv-dUjbi0aPc3uJ8=oel_za3$tfDk%2at zgn*!p-uee?AHiuq2&>gkqk+T)-5J#)}?@jjOYyFF1XM5hHh z5)GtIW*V#BhAE<-fnYc#_$9xntN=$wKvWuFO@@yo#YgcQeyN3}u<`A0OPUh4Y0{&w z-~Gt*{}A!&n{fq2r)u|~C@-(RNXTBgq`R|694xMCHs7dD9PfJ}uw2kv#L_V^&cp@C zEP0>=AiG448*h;}=6BQwbfa!#v_iq0YKt>cnCNC^=##OL8W^Q3cp-PS7hrCD|L*Nm zKui&;6jfpFszjQp%H;`pXIWn1rrC<$y(VAz2D2=B?8YNCY%tPLH?#o4XV5+!t5Y_9F{vhB~CrKzC*i1Xclvh-B;>WDE9r@f%Ft$$U%(3$q zODeiQ+g*3}BQJX2|1#7mz@7}{ADyU=YA;_=TUFr+VcYM0?1S$=`rE&GV8P0yeT4^4 z9XoNnqT)2RfxUelz3eGL78H{JO*1%$t0Hbf#SP7X;qA+tgi5Nhy9BB4eDwL7gVcuM z(_l*)wIZmZ6ia`j2hzPMi0>>-_cOpFh;Z!=4IQYf%Mgjfgxy_3?M@D>IjUw&n1V6LnRU zuzE0g$kc}4xH938IdlUr0XsD_)P1BV`nRVa3vih**jls_O{=-8se5nDzz^rWeD`C^ z?ugjzZNZxHfMzY!q6*z&^VtZ%SOT#+(2)!l!y3`yM#`o04HizgCcmgOl|XhrB8-Fb z?#AfwV_@1dGV!*U#OXnwy8krnoA+B6eYzug_u+#lPFGeE^RLbD&NHfP@D?N0{XO_! zaN4*O(g6)7E{x77fZ(p&k-k<)ZJNU=ydGV7^+bUnc>s?3s}VBc#>~(qV=C)aDdL1gn%)iys;f67t=!9()kqggKXSC{$ZMrSBa6+!bAQky+|r6Evlapsi9 zTS?g|mQ$yoK9D0rlS$}JP6p85PCoRVx$n+gknO#2zZRC~7E_F=6V)~9{&@b=@r8TSckexavA(jluA>t>J^0v>3K}EKA(c(t11G8)pIo-i z=kfRXLx2x@ONLh|5WIY$j?6$urh86p)^8{yZUO&%3GS+kDjgBTzLBLf?t|`|H7$H zeh_Glr$wU^6{AW#S8eC6MI`ymUOVaUqJQ!D>;Ls&%$9AL`*s(eKUGpyvA?~myi;$% zXAFxgP)1rWJ&tG%(2aD(IQ|zReFdbJz;b*&qWuP`@zQcfl8VaWIMHz?U&mGMQxCyu zfuDm71FaGth5e!~9hT?q9Y?-x{lwR?$zySvW=)wCQ{)$(O>lLbgD{CF&V~omBRalx)7jrvt@f)(k4Y^;T$(9Y|G@}P2URn=!cI-?8qx9C@#HlzMcT3q8~B( zP}IT{hABe74pN_P(dU1hIQh{Rwb?7iKYyryO5IUzNcmV;P>-(aM6hG`k^;c3y`L-ZB-#Euxd=P+o4Z7o$5)w@sEJ^aja zzkjv_JoY{z{#;}CXwiGM*nRXW{p{~Znqc2K!JgpnfZ@zy|JpSsM~js^rX3zJj76%K zq+}9#&**fwm`vB0EPkV5t{EfeeQ1xboD{s;_x@*R{yoXH-oPPo~rYeV4CNuE!Tq7EHJc)Lvq*+M1W-m8EhWZ&kgCnT)O#NmbGs4xA`yL zr`e1Amh5*8j>Gd5nvXLGlorh@>zWux{`Pc#dnO?)AO&s+!ciGMvFQO($$nv5W>i@o z7UOD1Dx}6YD%l4*Zx9@4j$lv}F&QM(!VkP$aj7*@6O*W zo?-bM)t{d|#m6o#s5qY@g1JX!W2j8&JfZo4_LKliyvMwafe*a>_YeOzA@$_;t$7DZ zN=u7#+v-ma^i}oi7YTr^kecmPp}x}B19}e%)vJJN{!oybKNn#Bl1x2})B}U;To9v7 zklMQ49bV#UklII(`t#eKe9y^Ci$K28OU6Zsbe4nx5sFMb2$a+dnbune*((;VgHb)- zqK7ZvH6`RzH~SXNx|4{elcMun=O*|@dg&ykYl^S6C-G!5aNb#uLCCEy7tG=f2 z!E zZU6I#4}Kc)a(d~xlNah+I%TWE5U2@rXT(C0xpLz!iV~fV%t+~8qocVSgDz9Xu-xi_ zWf|)4tiQ+)&et@im6reY?B^%{=9N1ZWN0DD?n_Fwh5P8+QAnL>a7O~uU@?dcQY)}F zFdCRn<)brFv&JXd5@v+0|3<{8GkzUA_ub74-d`1;m2>jMk%scqy%#GuWmfOz*e@A+ zsz;K^`FnCHwB-&lf{G$4jzMFg!wRWEF^DC9#dQlCDinJ}-~p*s^~R__7-68FsI0+O z{zO&Ye2JN%U0;dRbOoSEaW@F5X$}_^R?w#IJh=p^;hInmP+_z3mo)0;3=pN?XryLk zLH9bagl0RgTVi>&_YBk$SL&30clfHw)@}Z_L>~dE3~zh3r#;`@UhLx7t3{P)v2ygD zdrYFABc3RrQ^V8z!?HMlPm4%*C-6~B!pxX$QyyIQonJcECFbqkQ&Le?+0usH2|=WL zhoF6m5V5L-9MMqmfNO1UJ6+fI{fF#-JpbK$96JNWuX&ed+l5RWV2dZZV%;*svgN+eHI8j36Hj%NHMBQ1*Y&p5ijp7w zp+FA*n5B|aE*?;b_ zg_Nt_n6>CXA9wVy2b>$z`jNG(mvC@$H3;PlBe^);29ZH=7X);}QU zI~X=X2F9tfr5g-_Jns3VD$L!G>=-&ZF`1Ttl}h_Ph?0F!0(jp3@beQag4FO8<4-Ui z+T4xP=DZuTeEaUwBNr{mKcs(tV&Lw1 zAHyejJCfL>W(u)=?`KPM#XKphkh_dpOfiWO^mL>J*y8xHzjY@YE7+CcJv1p|`yF%M z`|bmdcXwp1i%-fcEQodfi*eP{mY!A087o}Oq+_ONBSIPw^DRxa(Od$}76C&MK=8zX#Xg-WcN(aHRl zg$9p$Z^XuL&3=nmWRERdv$pWS#*Fm+M-J9joI{bJ6JKcL$ZnYi#u~e!{c|0AUeR`l zyrQutE?f!h01LiCp>b;g+PMdWZW>@sm6Z1NN|on1^*524#wvb;x2ZQcXL#EfNUhM5 z7m`uMU6X`()#Xxu7z_$k{E}j;ZtYl@rPGJ1|J5WJdldN1HS`$E%CH226!hrrb$VA5 zMBtRJ-~VCJlt^GP5%?4OhEQo^54zCBzR$&8szsq*%hwj9xyC~G;-*FuZ(jUG*s}P{qCB}lJ+k#RWeNOW$AOaf9DDmrf<^#SVRW6PXKjKs)oB+j)5tp8@o zwlzoEj@7o+RA1<6sv2l-fT|(Ia=+3AhekEv8Q906p0JB+;&X2MS=hv1zw&2`5?mg7 zpThyQka&#iTw`|=9mT_zLmabdK^vw%_~y4BdG-H>zW>&aeK{pZ_V3?6&hw_PRFf+` zr}8Qp%mzZ`D5UNg7(wb6L2CMH{4mWgy&Y-V+)V~j#|gAC{#Xld}@jvi2V+t*Nf>By1NN2&4Vn;Y`T#gnM7_ z5X#|}=8l&?To=8rXv(i%B)I5p*0>qS>6Uc2$SlB1A+>@n1F18G--BU@Dh8=>uk(zK zcaMp4kHrixexmL3A3eQk<*xJ9)lE8)MLQcYUBk?jSU^TsTxooM*XKsF&~l5Pf`GAf zs*wb#MchW`4^mSH)+tG@?#8aRx`P)Q7OcpliX~XFkLhm7MCU~<^+re zsjrH8;~bFN=Y0Gp?B*<4@%+a0+*9YW_Y|Eza|{m-wD96oLG_G*ph~y^un+PFq*lXn z6YdZzE(-bsQs0E$9$myuMrtGlS@JA0qFc4Im#QaK=(tQyw8lY2MWA*h`P)(qq~7Ij zFLAf+b#)YKvDw;!6!#c-_4tXADH9{IC)oD5IreF>CE5bqIpe2AuD$QES7ScTOy6_r zL|J)bTaWlkq3&g`*eFrmDca1S*sN+DOh4W@{b!N41+Vw9QN%&bvDasDiH9WtY7fn! zN`lnUkotU(#hp+OunkcqAT?BFvUNL&%#_IO6CQc(<*f4sXX}riJkj1z+22-AD+z!y z#)T408Cn3@$o_2Ql-GA`*<11b*-Jfs66*FJOaAJ$-F}uN?a6KUh50Tdjz`ArQOOe? zd~@b6pZ@XOmlrQjEI3+q@@ysNO|zAwY(&k`9HZRvf5oy?$>_GP1yWNXfYOlh2dmn8 z@@odaAGKzh2-ImJ)-icRtcy30T4ZWZQO;z$M2XcC;oy`^jWQ%4HchjndOcIB%}bu{ zNDlnf(&$f;(sv&#C^%Slyu72KcQ^t!NT5*4zz7MoVm#^Nq{?o6_mS$jvx5P@TsUps zM}c9Vb8Z*z(jGCz2=Z)OAlJillGw-?sRNwD2vXzp9UJemAl@}5DZsw%n<2}s%hOL? zXzXuk(%b5B=)<#x)iI2Z;~%rD`K3Z?vCV@GVy>!|a;J@=07oqYjti6vfmTyNx}g7b zo1Rjw|I3^Cs3X|xmmPm4QyXdoSZ-L6Yd~uHigPXhIP8-bQp#2qaLj1?;p3-T8(`^M zbs`tRIE<*}jnNPW>S~&MD}QTZ+#h6WH4Lgl$V0NewlX#1swq<=UteG9dbQKhES;{q z(K0n_9Wo$ZQo;`Ru;+NDO^@8L=eGHu`dbs+?PAOAWl#0BB@-IL!q{_&H~-1nQOwZDy+6tc-Hbf*>+?-h}vJ+^wn;~xh8=fZ!pzx(o< zlszZPPoJ&0STA}Zv}DY7aGya`*BIrF|0_kCjW$3U$A#1k;`kF?dbKjO;Du0Vv3IKK z)n887H{*%7r^h5ys0$_yGIWIm#mWu)+!Ce8_Yo-m-|0c}r24XatR-4-9z zLer*1#OXpVJs3u%@&ddC`^VNhoS$pIWsV0F+T@^~eT<@M##f@sM8) z_VW2er@sF5;6J>UKRGg<__vycL6-$W=d)^9r0$MXEoyk-jDJ2bYSSFszhPZt-+p{m zan*sdtw#=@9&GOrm?kcZK(+kGPz+->))L0-ypdgWecsKgICN07|29gdr#bOPl=1#5r zIHK2<3;iT1L)t(k*4u0%=b_DjZ{k8nzy zA#$;~eN#qBYFYO;AANDgGB_I0+( zVW~`YL~`{`-otg3v*7YSS3PIE>+6Bk;FeHp{u^xU>aW!Ge_Qg|w7JU}2!I&ZC&f@1 zoL(x}LE{Gwk6!=EXUZ7zS?I?1y z7kFE9{4801mK@Fs@ro>B-okcz2uI3%7L3+nVL@@SPQKl;>CfiBxibCW;S*T3tO zaYGyI5XZh7dI8KZU?eieGBMzIL{#M=ux$JQ6$1{;So94@kfP%Qx@Gg>Z`d~bg~kyA zR143bZ)umYa+8gPlMa8YSlsa=wfv!Fb70u2A3wcid12k&Qyqs6o*iuK>1}K@f-v;q zCf6xkzJbuxj&y@N=z8_OT9SW2YLhgX8T#b+0;$<;zh0B!+TKG)sXwIaZnR7-%SslR zkb|bK-eZmZySw!JLOz~o*~-?Q<|u&P3bD1N8!5xvnjsQ&WGY7hxI2>Fq69hxD{Z?q zRNwYJgj{g3Ci%|)Y|2ARAAfzv&OPNP&s4P3Rufvvu!Vu9LUGaTvBL$0H}Vi1Wo$Jd zhOGoEgM0V$6~m9uQWQwPWtd~2>aRFP&w4uva5LChKzmp{cQe( zf3^Inb={07KPK?0$Gy5+2PB~4$ch--c>!!=9` zza~gc%nM?12!37c*Y~yS-wS&44*NFOhy-9777M!tZ~@_t(E&IZmkE)mJ`k}1Zb1`6 z&=v&IY`NYXIU1He!ItXx@SBgkow9M)@jWNb9xppx(@@1xF8JBu)rRgD1WEIa1guGUzLs6y zkzlvX79hzbDiw?t@1z)1Mi~Ji8^0a&;cvH>96aAx&l#I->{0g_hkSm;{JG}AHU1E& z8%AmwXhUJZoxIbxbU6NE9D4_952E|7*7c$u{XgE!oF2NtGX$hAfOl0ZSLwu9FRasR zKx*NjBDVQix7-)8@~wjA{Z;z0)6E=;+tt$6KR`%I4wnU~**7=1+&>`o@G#w^{{RRs z3Ij3}QjBfOgszVZi>BX4i!w~es5X^1W$OQ3NDXWOmk^*qy{cP(Cw2eQyz09nH~2=x zV}+~P3q>BW=i)wt&y+aBTGM6ZR>_?_0Wwrx%w+gVo+B@{^y%5B8h;S<+Zm6( zJ~@0lX6IUHGKW!WvL&6ZIkJ)2-R#sP$uBbAH!^`(8D{m|ZRrFkrovd%_*fDr&tLV> zM|oi%?8rM-exbUKgC>XB|0}N~#ZM|`Nrd8_4!xze>d4;O$_mKhro0n>_tXnMKYsk4 z2cMn%bNlz_z4A|?FTS*9dsa!w@gsXWYL4Mp4C&&})e5?DIoJ4&Q17cmYByW@_!Bl= zSE>ER7#U;{8#D0Yx9KPU$nxoAdz`CXVu=Ws0lDQ$t%R)ZeCsO8;I}HbwqOk^t z!C((P+lwGJVXGc{Gd|;FJ>FXFAhoy;j7YoJIDlXIXTwNsY)OlRNc~% z>?WaA&}($PbVy&4cJBL&w%%@!_YO}YRFN3w$*PovphllnBWuTz&Cra0KDgS`U5TUa zNW90f?a}3X*OoLVl~i1)>t!>mqX+v-z*;Qa)WROF?g&?*s{FORn;7>8?Y9~ulVm9x zcqPzRSkJd))Nf!C6v4czu{Mh{Gh>(g2c#wpHPpYdsrzKF{=m?e`rHq``Pef*ej+M$-!bAR zSJyPOwRXwL&?d~FM#NrpO$B_c3F0$rO`~ok=#PSFMWZm%z9TmIj;G%L-mDkm4px?)uI%9W078#Q zNtd~l6l?|r;1?1i5861;p|>~m0s+4xkeVF)k8B1zBQ=bQfHiERY!0(;eq=!3QmwPmGimlm68hVc!a0=& zgPqS3W<>za!Z-~xMOTN^ObNW*wcs67tve<>{MJM7WGz^g6TiO#2)%>VCYYHW0!Wom?Le5=3QA2<7x$)7L~H$(f4&bd#v zx;`l`zvrn}riQQdiQFcH3#1m97D)v8nlhD~&;QK}MGU2!KZAB42xlZ<`ss zV&X3xcmLDFuddjL8|>-RCoeX4a-4AYpkWF_B(NbNJ`fr(2D9@^?qbq9G>CiD{xenI z`^9X(p9X&`avkPLT6lsXQx7AxRK_MUzL}`Z7ceaXnt=`>+wZh){?@#A=e@aY_nCTZ zy*e8?l@H=Bm%>n$r_a^2=dPX%-}xktKw>9D{H3PO!3zyt2|0V8dvkf(o})SYkMBNq z=IHqg7wT)9+8fcw4hjkV5+}e5foW$3;7jkn$`8^#MjDOO!>ms4pz_k1`Opgi5!+-> z|7vCGCpS!;{Z919JBkh*s;j7gMRE4h8q_-o?X3_*8Y;#HguT$u_37(RwBHl-{-lU4 z9@bf9HQJcg=bCPV64TlHJk63+I__%$yWv zG6|&+cOPp!EFaHhGNS|_R)B%jL`0cl+i_RO@`v9^$UM{3z%iwbRUkEC>PHXSrPF5g zFUI?X2B^h>rpd?|U@cQt2A&;63?u1&lwd=^G;^J5AKak^bL!14Nvx4 zRD!45Fj&(l!Dy8ve^oLy+A2b|y9M*+9n)=FX3YQKyTPwnR%aH~_MUI;udZ)3Ivibx zfHn50)baQ0Vqqdvs~{fEa^h%-5@_JUp~Ixlx4fm!vyN6!=P`n}PX?i6n%1-C zOUw)nyb1f%qq`A0sY1|Zf}2N8d~Fdia$9#}*Gq zq86Dfgv(Ya*4HGMb0k@zZwY|7kUPwDt^B~yTOtriIE6(2u(dNEfBi3?c=R<|;7X zd~F$_*26_yx=(%6kedBsC!`+e>BbaTKRKk&TAn>&&PSMe`!7Plg7#ZMu%T};gxL{E zHq+Rx5H*M($OuxqMyB}ATYbl@rGNbEu#dLH@7Y&ed-l*^dkxGg#$+JDc#`x^UpsaM z$1XHIwD_Y5KVLXKc%ye%q86N_q)P*x6Wko}u2Jz?bb_k`wTwb)l*7y}1F5+?@?C6c z9${Oigs=IVg=?1=oj-B0qouxPkOR%-7_{Nb9M&t%pOGJq|9_C0k!3Ib3#6vuG>hYG z42}^h%1(e@-L2zxxT{(J*=s42pZp|X?#dZaNv=WLIP}VYF=uJPmY~fLv04^|fz;9i zHh7h*(0+S@)Rr8N;1q95@}z~FakhSP$Or$hbmQXf#RqB!8ZjnQ+;;E45Jx2w>2v^x zz2B!xp~HBP8fZ{ReZBN!zk4^C(~k_xM4{MaVNO+E-M_X-%_15Dsj0j|YU+=0&By;; zNX>K^)N9)G9jE)h6ZVnY+)uq1uwh4#iVXCGZq|Ia$YNJPYF2%wD^W)r$hJaY-6Qke zBMV%uJV#-et3{`IMD3Uq_StO@JoCu&E5o0DBRM1IOxf|qi{(9?EdvMwB9<` z*jq$aB|rKuF&q1vTADYf<$jibY|4My?zC;35S=O*E!uB{f^@|#7$hhc;o8u{s~t~} zTA*C`3bq=lSny6FNOM3^^qQQ#Wi@q;a*Dd5t4wc`z?yUZlH~*E04Wk`grN_*Rm4Z? z3?_HAbk)~%Hr0xycUNb7{}7(GM85^Igsxs9m|ybJ-{GTzX@eMkO^|w!{Yn%vskQoj z!5>Tr-;5~gxgcMQFve?m$YheBmJw}pB(dCc$ph0Q;jhH}0MR=?a8d4*u+{fI^31H~ z-b>6cWb$;kRO|iCtsV94eQiYhCjJU{jx+Bb;^0d{oB~~!CVXy;GqU?@+lE%;oSXh% z&&-&&e&&K)moS2X$g~krdKjkTwU`9J+RGN_WlJy=GSsugNMv$72nKH1F~PBY%Dnd@ zHWuceZ>g)P?Wn83$j}^LGjsi@w_)Bn1aBzbPa<6#GfJimD`;@2yQ{yUUCxd_-lLcF z>JNRCHtER^edetr?9T-J;6iu81$oEr(jv1Aum+}wk=nrMtAlBJj3Jv4k>wpK3J~vw zSuQa&WF?C^h|E(VU^2|xgppUd2PRUa?8 zE2K8{W9I1Jss@`CfR5o7O7%doOX}?WQEf5v8`}Fdl&NV2W8qxkOY%UoYNJAG?q(0% zk|A)0kDH+V1~!k?=wYi%rp*1=Z(*8-1#D!Zdu+BxWSXZX%Ohf!tEI@;=ED>`QFFv= zq8QI{v*fv1@?9-N`$VA5(W3E|+A`I$;@-zzd|^}Jo2!#Diw>T+P*KxV)6?BH)XP32 zW-x|JM_-3dVuy_LcReS;PCjr-1471Z>7`|)Q2W`F1z5l5jC0L@0g$yDHg z!?LkKBDq=9_$c4XNAB_ik`|eUT`?}YSgKE-x8k1{t&ZP!_Sm_~=5}0dM670%oxA#y zvF2MYU>8YQ3Co7O&!G_QdIxc#?-o zY+{HF_OMJXhWtYRmFQvH>1mB8 zK#GK}wGw)+$i<2;0|!0lx;j!k35W8;2Y>h6rX9!X#aaIR*{-%rPd8wmTsNd1Va52L zxd%+s)rP%RKU56UEhZt{;Jzl^u`xe1?%>SO4>`}BL+zUN z^+F>2OOC5G%PlfPI^k*(L?F+SSQ=O)}}q-Lbs zd-VO)`d`}Cc+X$!vM5L61W7_lT9eUt`G&Lg3?f6pKxABL5{142<+dyjOP)tWzI+8z z%jrDHnr+i$>+1g#x%`8?s@0jNQV&$`tLrT5=&NgOZ*6UEZ*L{FwY88}iTvoqfzs8z z`h@|#tYzqU>(HK7{a0@#`abc2Ys5~0Y4nr$;aZbDtcilfqS?zA%0nKE<_Ch*X&%;i zl4eQKESYZjcSmGSwZwh?8Ti4X8qJ}at%&vCo{x4-AJ_yuA*N`Y&@{OSx z=*8j{HUn#RWrr+ZDY^=29bPXlu3b4y2e6Q``Sl6sn3$g4ztbn0wvYj5jr9n=rE>X}XYBkRt1 z&RXRjoWQX%YM!{+5=kz0cupdL;JCzA4zq=N!qgEHV7E);E)N(~R)K5)C2N)hmyiv& z&3$)yag`j$eEM{=p_Wl2$`n%9S5Bny&HzRi{Wr7Bm{GtqdMG1gnK9G)<(#`lU0;@Z z?3?qJ-4(UkEo3DgaGv-Q76Gx8qcjJjEwf}v(7&r_^5lEGo<_t-r^PmG@ zA%>>L#n9ivrmBgjDuC#rP;7La%_ra*7awT_{KnS@sTl&ZC+S*u=l^IiJ+9=+Vi zpX=1mcIjt3^fEGEzMt&U_jc;}O?pwCo>|_#{YP>Cy;sYaq)|65EDjt8uYDG#1W9M_U3If>*&i@`Pmg9&lvXMp}$pC zS9MUOQzhyTgefe(1mo04zEW)j;}F12X_WVlA~lj=JrN+cpSnGG9kwWPX2FuZE-zq37VjUvePT$Qe@MDV zSe_OsJ9k=Ck`{$*o20Sf7?$lFn&%!~AS5nYVt{K)61DlC{nfL{_rI3+#9Mh!yqo{j z+I@3BFAdsQ8noeH$ohl98%sksl!k0N#GNO>>kiCcf8dh)y!E9aThGm1dpK(2o_X&j z&HFU>pI%MnqzNqoCmO@K+ln7bf|n(Z0}6?iA<8|72}#Um_?YP$ndB3(l_Y^N#eHm_ zW-DY zy?O=hH!5Bf49L{ZNR6A+$4Pmw=AXSiVjTx|!xU-H9%XuHAzOSbn@J1@8xUgWK#I(E zfp-$^ceYnVl6S;T4}z#$QLAFXwVNQKo}t_RJZ8gxFWWZzow&#~1#?#J4cmTh-ugpx z*BzXzgW3rQ7QXiASv zcekXHM3*b*hQVYWfqF<%tH@%_Qs@z$>lc>f6TTDC8|w=Kp?E)??;pJKKVIHZaJ+U; z$w3aSMt)KA$D}a7`^XNzfdQtQjWaJsklKLhp^mP`TJ{>)WZAH%>fe_o_ym2TS+=;o zv{$BmbP*2Jm{1A|b38|cC@Z9mk=a^guF>#JT1}tR;R3tkpAyy-&6Xg#g(yxE-={^F zYPS8FWtUq-3WutEFLq_fy3E9rH5DyAE%mK^AT@Crey^lzMi6vR=HDjti~$y41nXMS zjq5-9S2K;AX&2OnI{!W*HGSxe)KJSSbv~_Q-SMr7)I4Dr`9#twN64yX+f2zkUAY|<7G*} zZ&av|HCK@x0}eoebg;(TvfU?QyGuAnBkj^c^V}96)`F6zTejc##2cR$l%L}G&8B8C z3}f4G2!qvO$8JMj=BRAFqerjo(@*v32>2&E^}`MAr#pI2cj-r321=WT4!7w?+x5~` zy|hKT?r5`qtXV(Rte*x9&c0 zpuXZfURvx-vjsp$$yUG+F|n}4HpIL>y{=#X`>>bpeCqXpuuWPRoZeoMsjX;V**)3H zK*$RPsbz0^7^x%kz-ywWdq=22#McioZ8vb^8JT=v)OK9pzd7$+hJNC#4`+mZJ~?z_ zVCV*w@V1^D@j3U2VH+=-riZM$cmA9AJo)OktgCOgZFZZ#g`IIP4$KP8agMrkV6$fNPEQKAl6u3uZ`-BTp(*#uC+5+V6RIi}*w>|#m`UB0YlS_`5vwPmw zN8BDR=8l+38Y|A&q8%O_MH0UBK|LD2o8MfLkv>*0BO^IwH;7hQqQJpa@2S&&6#m|n zr#|quZqpWEW68!7aqsEg94$0O3r+Bk&Yln}hLkem!jP~i!0Sv`iyQ#Ts$qe^KCx;H z7MEEeiI0qwJKq|~RiNDXb6cv{Vu|pNm8R%D9HpA|AbSL^wtO-2pZnoALY6H}Ik2ay z>&U6vj#~CAdJVCf38I=YJmFO{ox4CikyhU73v?I{QY%>!qy`ot(Oh3cq*hY%Wxq#SvX$rIWs#b(xP{ZltoF4cH5eoTfrWgt(2Yeywo?w+71P*G zEOYn*^3v5;->yHK**w(}ug(5^!eVeOSqo0^U$V<9DpRDM@D#6bWRP@M3nnG9oMlB@ zSoPV!HwmP60mK1ogLQ`*_=KhUho%IEBn5^f_=hF`);y>v3Za3CThW$FwY$GY!#yx&?2) zb3xj_znWfjw7H?YM(=LwZm%J{QuC06kAP#5-N1p~fo8qBRiF9D(n;YT-xl%7?ctwJ z5B+pn*otYPtEPpn#yELO=-Mfv>&;~F8*8VBtOg^Dw0d&Lh8ZCn?wGgyyR(*loLE@P zfiE5PdQUS%iGiUYK~*8|0)1CaslMamM4=7qv=sL6^ecb{0aRd){+wd+$Jd1Zn< zNn?i*p%rQ@MEk4nLcr&3o$%OOi$2wHO=l*|*93`=3q z8G0sw%%89XK+`88Zk&l}hW+`3u&w@KOr#`cqjy-QcW5rjD@>9{I1>isf_X5U1#n+7 zI2ogtsGiJoHHAPl0+*q^hvoAK*?OB}=ij`P{p)u#Gs>DyUu?#pLil+Z4lK~yj8G&J zs*7G49%30~1Fwd0T)K}3DlvAKP4X?C``7}oe!H3_R_Fky#-q9rpRAk){a;_&$)Pax zh8D^`6n=09pG=%Un=DU&m}RSEXDvKYvm~<SLF6$bUhdH;$370O2&qx)6)RGBF@|eH*&d7~_687=i z+0`3zFC0ACb+N8j@8;0zX4N4*eVj%w^OHn-N16{$DId*;(lxi@GSQX{C}uk9UKT8f zyaCK1*6~Y_UBUD%1Z$<$q1&hf+c5wc^+(>kY~^`qR-O#?SN+Z3a+!IRp*NV@W4uR| zqClUYU7Pk>l{NZ~!qen8$fyoC%NkuP-ar$mGne@`=e+swx@XL;V=SmALoh}?Rn6%- zu8|%SuLZcO~=S?6lb*LF8nwluO^-qSQhSVo1^7>RZFHR$JBbg$VTXi+jD1H5Kfs}jKDP`HOHwS z*a|4H-bjqI+<4e4v8gf1D`?jzKJ<#eb*BMCVD$J?x;B4%z^u0xeY~!;wCG~_q3(`) zY}$FRFt1d*=c3*VXbb}1=XCwQmn8&*ZZV)4bpCR>Y@tBm7n4W9^!1%TqVN%(%_6)U z%z$ju80kwe%`l0Bm|@S1Tel%sjzG4-j*7WBA#*wGRrai5^W1{Bf?@>P{ix{NvBviL zu0Br0HcS{g#g{>%j7lK;FNT=zf^rBx4NI5OeTmSr0-rS9I0r79K zXB@2V(Ra7%Pp;m5XT&;KUoZBX;D~~mnYbmYR;mzjv)Z4f#5Ofc^RZO{E>&1Ppky!gdw|$ z#AtW|H}!zjdPg?_Vf3`at&^WzsRboSFbd?0uoUsfM4KIyV1P0d?@I|9Xdo9Pf~{c^ zzSWmYf^I7DdxJ_qD8`cn5S@#-+{-D^={E*h{!%4Xouw7w*ux}a3QMC5bwT3P`Rk)U zOg&jv%Q={}wP)IU#axx%V6qPBn8mbrHt45XbdM+A)$H4WX;*84vy#w>q&t&$r#$tK z#925GVQ}iBZ$G~wyYzHfOZBOtwn~anA~0hjbXX#&O1W2e3B(&QpGS}yXpk4m^LAZ4 zoBQep^nx~h;)6?l!?#H2tuJ6`eEIp?{b#+i;A3R!-F4+hdOGTrOwATGv{&zKK+2=U z>H$6ZO!r-nz3d;p_3DZ+$L9fNl4tw%XXB6D{=^%8PkuHr8n1A}91i`NbMe;GR3xiV)$C^zhBlKeqVd=18?*d)`Wnl zG?3a5#`#;(o54^G?|FgIww=T35n;d<;??pP>3&1NhRelp7loZ(*QJ*=4nFzXR=+1c1EXqx@=XYMIg1odyp6Z zpzzd5K^y-u{GH7GXOEpdUtV#xv9+aF4hIqF9Mao*;fxyk*?M+={4LG4T|9bFp^L?u zNyfi2lc|MgdD?UR!xJYy^5!DKf*(27P(I`U@vEe~0g^_hLWZe4unM+Ha5=0UofHQjp_& z8d1Mf?w*T7;h$vQIr|+H&f|Z-!QkD{`GX8-ps+aqnrxl{%?i=LW%ZTZnQ6>V1HPTQ zh)$r>TmZXpR7^?k5s7S|`&v_xuWt+A@YlhwY}tFVw5qAHv5m9ehC140G-V4#Wa>+i z+TfE%(+agHo$tfHF(wD$bi|Iri1*ddJ&4od_S0Q|8Ts*q$KIJ787DFMLzCnTGHmG) zhZS1_Qp--Xu^Ej-O#Q`~9VUc3PM4zY0DOHSlD%iW=l$TzcSn5o!&lRZnlf?Tr`n?* z`i5==sln(GJ2V7pLup1=7#4T3mqA_xZHz-unCA+)h-SYdZt~M96C>A830Zzu$Vd0T z9v^@3LUju#koL8;6YmJcQD1)-(+BOID7~4qB<7N8I}b;9&P{s)u{G%}=r9HxfDTHy zBLjSpha0*1a@-|7L*>B;po*Fsur`)VCunDgsQex|RK3dRfZ?GqyW-X&HPrxlVJB!2 zyoU+amjJZ$M{_fRM%}bQF}sTllYuEgmFQvTijB^zVH(zcvkVOS!2ctQg8yOByRb}V z?JzJ+{d%pg7uV|FdGv*e;ahxS#e)Wm6j`Sc=~`H-S9Cu4(Mf2soH|6LG9$4QYNjvX z+X=^!o7fOUM<=GXw){9q4O<|RyX>vwuhxdu z8lwBICjHOnzxhqedQ_(4d^0~2wg(yQ2F@P?sRfir1m`bs8Q?Y)K}y>r446tz`x>IL zm*JK@Uq>bu)Z!2knqc5{vU^1G#NhRJKeXu0q}{vDH6c9q^r9#vh7TGNI!Smw#f&jD zatQ}0m^6Y)>Z!ULCY^jO-(7MyR;xZ(R(_$XtuNzP&Dwo+-+AH{zuzpoXHhE0*om45 zC4eOjV-h1izi?vo?FdrK=8@6W2BSjrfpUIe6U|bfC1J)BZwLOTU{J0myp_+`z!=jgh9zMbm4y#bRBwI zGyB&lIm+AgN?l)fqI<^UuVNuAFdd$zSuzwr1KA4NSh=GTJT{g>;@C1e2@#fkG4{Vy z5*jk1do-1hUzHJNKxxj6SIOHhQ`Si7YF~16J%<5W;kC3bER_aw-r}8e--%qmi|A+j z&%&_v^fq7sgK;yPvB*db)s3C|TXgp)mZANYgAv0pKyp@%jsvyBQhjWhAoYZY--ud~ zUU2wSLsc2p0nD6XQ3A;0d@j=EY53Sv462S&R9IrhS>b~GfkNuRPORCHsnhE8J7zEQ z4_W8V>80Y8GhUd68XHLcp=0@ulEa6pFPsFa**KMgdLXu1+UzriQ zj?+aAS7p4Fzm%>}XzC50KjNCCwpx^~+mx)0NhN0R01%4ebgys`LS=r+o{N!&_tuS3 zmdH7RP~bH-4;(3iYm$HPhHuPy)w(hz{Y>-OmZ3Icwjn7>031f-3yU&_#y}$VpOOD! zR26=!J5c5Pk-_aJ`fgXJ>@OgQVi1r}*1M)m|9=*44G7+F*9*I~*;|QWKJl3nSO^B! z4O>t{=RqhVKwDqv4@;c#$kGRp1A!JEGM__9Cxwf)6yC2u5`{`jdS zQ~v46Y4)F8Xf{lTJY|?vM6;i7iJB)C^wDj98L+UTa#6Sn+IH18K zs+VL;q&6YX)FC^+=Vs;+sFmyq{deXfE~&Zt$Pf4#fZ|+j1E^)Ha(#V}T5%v$*p#U+ z+amQ4q-JPnl&Zhk3e~6^cQ=umq8SBh%QZ$l)mL9aYUcicfCBK$4j0RXpo@|nz~YGD zTJo8ABS&<7)|!%;k!vJSC-lmafilg_o1fk!d3DPPgRMJ zhW<^61__EGKOQm0HWt3vx{R4pj6ak=m%kNlo)qL<#7MaY-B583FIQFSPpo5!=ghY> z&}bu#z00xT|30^Ab6HQqfy%ntz5xhISC8HUQa7{?HB>aU>}}CKXTRcR-{v2g>l2nw zH6VtD4*9F^^0V+%&eS%L`YrpatlYz8?1_u{w}I3$bHF>sqW@ZvTGS&Vo|rllK>~Rv z%Eq3qfq@HsI<32X&N4!Nd0BQEVv(pr$C?!!l_E}RCb*%+WK(Z^DX zu3zleO9%Csyf1xD`pM(9WX`t)b( z4%8m1*Q=X27gZm^*a7=MImku+1B@;~YI<*&8p`kk$AZX`jG-LPt0%_8&h8FON#N}^ z9H{%JC2N21Y=Zk^pG=I(!u~<5$RcwHY(fYZ&#)cLXE+}kC`ihB31`LO5TT6p2>p#> zA&r=*?vXn^LbrL&-!$p*5AXcB<&lMNu1(*QSbXfg%_%>9GKw=sU4Ci}4BIT-W!tSe zIN$@Zn)ADN61c#a`N|}Ic*!%Pq);{v@HbzOu02QCb~40U$bxhDt7p=d#GlKrmNP^; zJG=GvdcEVKIxUn=pmU&0GM)GUOtW1eyvnV=AiRiXko_wWTT^Hvqi8ZZ&s$q>cBrX| zk~&rO#^5y6FZtOes&5n8%nV%t`dq0Wcn@&Hx2hA!j94;Xx6S~m)mHVD>frpG=F=#C zk8Eo;!OUE@I*ob}l~m7^>YLu+Qa$5by-V_6LTVPnfY1swmS~*}qz19uB~CSm@N`P} z&@=sdT8Dmn_$Lz`TP3KYJ;wug4@(Bpw7Vl$BK#wPDk}HoI~!Gy0w|&3^P;S3Gkrq8 zNZ8pzDh)f^TtcQmI>f|9VwH?9MWpa2#vhtReDQJ$5~rJyBD})z>k&t-%T`sO8Jz$M zaBCKgqJhGPSQ01Nw)j5s>dS@oZzUZ*QP$pB(X8VH(+QF`H0zD!%`JOdb)VTUc-gm1 zjKnYu2V2OLVDxyBh+s%w_H>Zi?~!+GtMW1rb13Hdp4K`jlQFc0P~4B}4JTzg6Yx<} z;qnh4YmDu%pUW@=2<0~nko10{a3AAvibKt}&3P>_eEroTHAGl@YU_kY-vgQ$Z0LCGeKT;02aeDGA@EgYTUUSeMmo!z_bjRN~RK6Ig5u_Ft#c-Si ztcg*U4onl++&g@W_qyw zQ!P;oh(aSWbvjn!B*U~o7#MY4Fb0M25-tyY^0!YX zypdf~+NjsH^mH`W>)ojG;7f(QR5G=;0w8ck>apvuK+ROz^9FUPHMLU#E^?bqgK_}Pm*Lb3y_1-=ovK9cgiA_}}B3Oy}_?v`TC+maKMtSRG6 z{Fp!C5BYOm!mD^8iI=+v5pE@yD5k_4_lVr>Y2V`(S)zsJyW0xJTX`4~JI6U~oo?Uw zqn8qY^YV_u(#E#R_QA6AdT-;9-gt5FA~N-X7G3+FNPqi=!0;@;-~w+ef0Z%*?Z=ihJwy8h%RnSW$oJ=wYqi)D`fM0q0>t3+OX#Ar&JwPy0eufMu|*RF$yYO2cz zx?5SotO8&KYhJ9&%5>cpe-5AV>GlMV;2qvqc>m}UdE#Nq@vs#$aBdO1-6D$c$9E6Q zVSFdpc3qeG!&zNSLN80cCl>e|%u38UJ12HY@PV3m zMc7qj-U2Fvg`2-Mf$$^5;$w1p*|NN>IbK%6t?zQT?Q#QZ!&6oCb#2zicSLRVd-RQ| zk1YGZCk3&|xXB0fo-{K#vrPp%_UT)@)fgvw`|9+>vE zbCgL2NAO_4Mk#)g=@Tr(3{0jUu!?tgq)TWW3Cc>O-`$#RuZOkB zji(w1Dry@VYO98NJNpdxGdib>rmODY96i}mk@-CS>qItG#P9c2q>#;q*rDDA*9`y*Ksz-`NA(6D*h9_jj+X`=|R5mD=y91YMRYgD0#>P7b_w*X4;_!pX{Z{+p~Te ztZNhkje+@=8kRZEkHvNv*h+znenTxlD?C=`RjJ=|I6a$tsn3pcILQu8lIcE(dgEdj zkv^RCx44OU2t(AUW1uV>{x0R%BD+ z|Lj@`@d{qV>xcwVbwz6_9%LiyYa!`lE`8fNv5!s48`ddraxw-uWxr)5>ka2L48}0u zvAq7y&a>lopIvNq>Ui|cilXL6_X^dGWslVLWgS&m(3@4K9gJL*4WhH7-i^gl-1Mb%@+TE z@=!fTT@n^?5`1`E-`kU{Ihw@E|syKg-y`<`;+kd~o*eg8}h( zlZrZvt2;0)@VFJj;3$Hw0dUp;gYt%-mNF@5^2dNVdeh`&Zw9Hc(Hzt!&>p9SF`uqy zG^stVr!BQTI_BrY!**j6d+gDNvE{_qY!Y9$mZJ?qys)VTT10{RTE$|Edm?ZP5i<3* zg}jd?2q$U@UfX(hh|SeWoJ)hY_`beo=cG^U?N5p?C8XZUzgP9}!K2!8b#oQ0g`%3K zi1bpupMu`_*l)DG7z6$og}~8fBkbc|`{C4Uwm1s_rAEg82b#wZF~dslsKMq)IvPa} zv5>ToqDA7{<|+Nm5=U?pL$+TW_4S@DA#oSdE9AG!i))&z>#PUq$TrSzaOI>4<9Hp5=(nw6 z`&va)y}{@`azZo+$NGSvqI>Dmx8AbmBNC#5NVL#JvF|#F(d!|5F5#RYY@fJO@Y*hH z&?JA;M%sJ+5psYnA0LqR-F8-c$BErx(OEYu+lx!p)fjGUs_1MiuWl)*Q|oQ_7-e>N z$j<2gJ79i5^YeR8@0iC9wh>~SaFXo}6Z_xJrJIgTCu(Jjdd9Y};oFYAYjp#Aaf9>z&m*YWXKAqc^#NaoYk%c& zFiMe@mtS69O3oH%bXt3J0}!V~tqzh`Off&#Z~J9zkujVjdT!(|diXXbS+?P$A#}ko z6N(*T1${W;cQ`_vn(>P2kD!lrY#*DbJ~r3ivc-0?pet{12)*SH^*ZM|*%)*8l{f9N zK`vGpVzC*&j}8BA?1gI`$GCj5J6{(O+ftK=8DJgvu1z$i6{c-J{LP;DnC$x7W!M~E z-HtDkuw4P!>jRCf3y2^$6xIuo8XpE?X*5%g5G-0N5o5RQ zAM$_J?>Qd*#{JlNX}&7sZbeyjdu_G4vyoVgEp@OEZa1j+N{dE*=KjXNLf+kdWsH;f zjbAV0Q|rMnZ#W6qQuR$6(hAhnGb1`Xj()v2-u75*TyE*Tx(?)y;xkd4XbbI+$Z7B0mAHov?9DASFx8*b zWnW<*GD`Ys0`yk%A&r535sH^ZsBXR61$NNJRO_Ttx#M)(Rnn$c1| zku(_4gbB(ap3tiY!{|`6Gt^)VJkvPYm{|{gV&(8G)*x~S0ng!~zjooyE6Od)20IH+ zW&SKD>=POQ{9v4c1#4Oj5E~oeUtzFEJh){`0c=p?jpgSh9?B|}7}E~eF*m?AG4&ap zp{{CCXVs{;c%PrLb^mzV>mztc*bm_y8xb0He``T++_!B-ece)Db4u**fgQr*`a5BE z`*L5)t8eZ&)8FF40E=@2%rAiYTU_i%=rT4&z;`8>W$P{Bd=2w!HQ>RZlQMf?z3?3Nib(JpS*u0wl- zx6%qL%jz1N9+RUpyO5fUemA272Be1i>ivZXXmNI{1Hd#zYBkQtu6U$QsZ)C=+?}vB ze6;1|!CW$mi;^W=y?`jB(qG{px;tXbw_)?YcQfD=Whm7JwUOhjgq*RHrwn zv7;tFO9w^|wdD`7i63MY|DwpBeU8nw-f&d*^~xIPmHvhukUHuu>+7gLZ|(g371f_e zQt>Q*?`L(oza{7tA*+-9tWLeQ^Jst0rGEC;-sDF1cNM*EFL>QiG{`IY9ozW+HnAFn z+b-&BLrT1_4JrUj2?Okf?^<6Qzx}we^|9mP!t6q9snl6tSxvr3A~Vcn1vtvI3zZlT zij1~O2AG)gVg|iwt88k=l6}&fMiso%raqcp^Ip)62|w>2yX*I%mSn@gfeuO7!5#;2 zU^5?x6ar^t9?$TW@Q!UPh+!30lZ?^;D-rs<6CGkE>^eU19~@Jwuv3aVXA?5`imZDN zDjTttdm~m#U~H$pv#tVT?=ax;aU%CZ%IGaVL%usO;FmL_9Rw)f!FG~2IfB=@B3R={ z8Y4x+EMiBP#}2bV(}-m_Nk9V`WJ%^PhMFmcn#tb!HEM*NP|H<1-t20+Zus@tAmRd8mfTI*}xl-(!C zapH*KZI^@tZ3o#V46+sW#vKR)8wUdJig?E+>b0#W`s_IM+LoZcKZN)DHt_8)z50IX z(eDcnxP8CydizVCK41Ct`O^RGEx~<159uW#FkZoncpZ^|XoQITov;1h`9AEmZ}+_R z&ED6xo$kkpeh2GLcU}ccz2TgOL2tMJ?zmwbGA2LVDsslwK>rJ(!g~+v%S&q29rzl# zp}eECT#eHhCTt5BX>ko92iZVA5KeDtC`UYmD;;1X9%>$?z5UScqkLgr@!j%Te0YOy zH7OKmNV1}=4c#c{=f8y16sDoHo~U67V6B(DM*W`Gg-JV)55+nnoEwfkSZqbe^|J(X z;$3UOAgctp@PptVzUz|q4?)X+bh^M-FG$Y?JV8d()oUi&KiwXZ_^d>hjDn}AnWe|-CV<@NSg zq#pMB!mU3;s6{0H??YbyKJ1NcN8d6#*9Ygfnn&Oxqk)`QY=!-lY~u%Y6Rld{nJxYP z9MPK`QD58GQM=Ag-x}t9F)i^{T}4GpWpVkFmZm42m}VkP4`m88LTQ5-|MQTVv`q4A zbrU8+$TwL9HIK8J)$jXXn`Cx!#ID~*bK|hd32ZGK*$HzR6&QBWP@9;c*0IDuvL!3P z`*J1yxbZlbvp**RybZLG4YX0fh5Uz@UDvXY9JYeQ|Yd zOC#2`B1H`JkyF|Ji!mjtFg0PCKGB@FrQhK~D?(vH+XJ;V!IXxF%YaoEV6hJoo~mC& zLX|%vp;1vaOImFlEd0n0n>yu++ZQp$ zK4(4uBS;OoL9oche?)3p3N*7YV4hpnv=rDp{;5L2TkMPQP=gTl1X87m!iD6i@TuoT zE<)m>NR76KEe^Xr0HGZ)=A*63M`Q-`YMFZ2XZE^Ik>eb&Z!m_G)84fe53z-=?iCHS zjT^;{9%*%XtmVZaKOGwOL)hSddyM|VecTsLqdu`7^NA%(xE=W~>ye+>j{2Ab8uO7| zFI~KX7inx`KkkYUx1&C@8@0u4$mgE#{M)<#w|hofoSneE0cOBbFPTTMp*Eu7mZD)e zY1a(OCq~!eu+8xs88`2ilsqhHYpZ#zZYu4pC{f!UzdnAe$8fVtz+6DmpCSTM9LXR% z<$&E$Gi}a(=5szev#7APt)dm1puu!vHnPINBhGeacJ2PNNR99yg89S}W4=g5N9D1) z?y>q-lbTsj_Om^e+?MFvi$71?>I45p2mp{~|3+Q{q|J+-2)5h4x zj~9t3%^01x()l(dGx>SUse4X@h{GZf7y=u#CGh**5g02p70@|@gLbv z*}@z4p<~|*v4?j^>>|BScEplE?(c}yxH00 z#M0KPrWW#HH9oI?(uTZ4SRe@J&tA}$nn;aXC}+(+re-$>erQyn8x*W&LU@Z_nh)Uz zI$&TK>XZTmPykvNen!Q1IhuMHKS61Of$sR2rr9IXzkEw0N3Lmyn)1f7p~)Nk;2BwF z*@k2Q4KHE=G1H$|&)ATvh|T|icRlS39VAFH>X7L5NjXoh>tSZ4`ViVox? z593HN7uHJ}Ya2Vm=IV@{CnkO!I{8b#DW5v)f9|aNk=5)EcNu=V+vwAsi~rR{MxXA+ z6T{DT8h*Cj@ZY}}efDdwTm)lY#OrKq@ZjOh|JyPBpB6}N_7DDA-v*8O!hiA)2XW#C zSn4J72sVNv8fT*z#YujHlZ0W+8TP+@>~%O+m0DO_a<{Ri76L0%H*JvKbsq|nsfMQT>7nwria*9r5ST`%;xLZwW+fm=G33nRA^Mt zY~7llS@MlNCp+3(JD=REZrgiJ=@oO!z~4*a?O@$ltY$ zoal_6wV+4LFS#9U8$Z)7YU9m@|C~dH{N>xcAD{_B?|Wy)t~JKpII1uYGe2> zo5i14E&IsIykLtS*XAJ;Nf%@E_!t4pqT9)qcdZRoSl?FD(tcK$KI=29v0MDL zIkA&Ha$eichp~#84m6xmwxZEC#KkSFhyjj*zRvtUuJLcX#P)NJ9pDr_*fDB|L)0+) z=zi8W`a37~aZGvLK6!wh3>%<*7#w>>S#Yns0^bp;TXD!sJ;uT7FoeYzfvg(rr3cCr z3X>uWT#RzlNn1b?E`XHgMU^K4Kt0mIaH_5m!*lgEFc%@A@TmqyR8X+Ae~qYUY^=&f z7+eU9S9(lX_cAZN4+d^2Z(xb0`z$~73HYIGBN$i(Z+P)V2~jcPSJs1s{>IU7aH3f> zC|u-)6+5!??1lW&3qQewIsha^alkg~QN(N>UnGrZpW_wwEqD+uBBu#~D@YhFn>rQv zvmCNdXaS)_z!y6JFX13m5*^s z9nO(-BOM>(nUtUkMsNgZ@08%j6Z|yJHcHR@?1G)g7W^3UDergl(5uH|vd+b)UlnIE zltDd_qRdE9#&tp|k&?tniL%#}NL~@A;q~q~Y0R0|rFrM#GtY_&PDmbD9F`dV9IExD z{~Vi3V5ysDFi8kJGyH>LXkD5kVv100Gtw-6oSky8Yvw=)(KzcfGq$?#jg;m+th!g% z+5&?MCk@uC&q%Xp{o+2>;`b4D2?TdIQi?v%QP0SVRpSh%bEN~Vg%iB8-nNpWvpL!9 zy!Q72zwV8UNPC!5r@r5)u5EdQX+d&Q$|D@bM9Qh#qGjp`y?LpNA6bI3#q@N;BXz}N zb(y^}=AugooK+Blo|dA3()d>=mlhu|;0FZo?eJ{6yPNtk_I zmh)=rk2s0cJz;L7@aA>F%^L~%(fs@v{!O^?lKYqAZ(ooU2VX6ixy4)iyYTs(Yg#tf z$Jzp><418~LC6l1BjU$HRGu!RX7Cz$1VX*ztm^9^ndl_MPO9^_28CVA6eQov%PVZD z!|E*T#DyXSbz;5%HZq8sRkX;MGG=yneo8ww83dA;w!)Nq>XoM}|C&MpTX*S4#KhTi?^Z@6mflg6_90>ub z$GRk7(cM_z?ANR$?|R;R*C`2SxajOU@^!$ui?WQenyQw@D(u4sEy{E!2q#@)A=3er z$OE>L|3P#l0KpWh%;5nBL3090aZ$BNl_7QUq)Ul2;DwOT{CF3U^ibo73d)mS=vGs7 zz`GRk5IK!dQ{^IZdf_La1Ky%BQx4(2+6%l*f>0LND+`ivUSb z!BS}>EhgEnL5%0J$3CR5P^5;X3jOey%s??8?UJ(tfIsT{YV~J(;&g4#kGHyl0ko;E z@(~s{COb&R+KERwfP^C*1tXpKpwSNevG#)T9ML4MYzkLC*-k!zE5tbGNV}Nv+(u*BF@YnW?7*MqCK=)&9_ApL z;>@46`}n`TFUDk--Yu5P4wx5uictlUJzBbAx4q1l4 zN7=?quqQOm9@R#GiZs%ZRHxDQ!m->0$O_UP&xL6unBXWI=cJfmCzx)2VeXDYhTnSz zTv9|UbCS}tb8_-tRsBKDDY%u7kA?H{3sG${3o1Za1!cMU#Razub8p>8rMf7&xy9|2 z&Nn`=IrUsb<7|Z^ZG>ZO_>=4srrGhQaAPLe-Wbnea)bwN@78YS0wYsr{oIU!4m|^HJqTMxjJjO>CC@&CEm$=BB1%|v@ z8tW=C^onh6tz0c*lH11M1AtiojVp{55qoZdp6Qhg2uPV)WY z3ot>oF$D;?FWFIqrj9W1^uTMH0`xpsWv>?{%Laf4uV@AXKN!)~%qg2G&74v{SOq6E z06Z8>VC@IZI9WfN7V7~6e=kyl0ZpD^pCIqZ5wb(=G5Fah&q{zkp&r{AQmeYE%N(UlzT8FNy2|3(s^aqM8hnOXSc{d|9c5L`sCrERj*&W8h3XoYOJO&%vhO@>t|@D;D(Yx$xLe!4b5F$NuYIT6Mgsar z+o^!p6C9*doFr2m?D8@)RCinjH7b2qY5;}DRHcmYK(&n z2nF2KcZxQ2x&F<`)L=zr)Pv5XibwYvA62%r)wSU0QKHhHOW0Ey)Y$d}g!znadfd|S zxVE+9VSW3(X7$}C)JDHW=q1f{`%FQ8B_%IowGxlqVkHDj4s? zpJpGY%ORx2C4~;fKFlp~m}fG&V_KfF>Gm zQmfVfa6NA9cyQ8NDSyOpY zV?`0F8BU0JSkwBTwzaqhAK%r~R+To@SJl+jW))ThT~q07anap%a;kL{%6F`td=ghO zjVqdN7q7#OoyLusYKLMKpjeR|hQy=_ITA6Bb%-Hk&!6HX(BeeSwLa$?|8QSq;>|ln z>ZTeTnuc9;C{hCy(M3hy0Bg+PV!#&be!VGJ0y&Dl8@x2!~7fR zl87D1VS{PeM^CrA3YumgjaI-Ey%f($p%dweP!muk#yY`Zi=E?geZKWE>+?x5x9jfL zccMjO**V$87j_E~5(Cp+r_Xd!o&ejFz%#=qg>s^Dp?J~Tg7O5UQkC)|4GCRJe?my= zp?Z=;`GO0P10B!-r?0#`eoYOGwD1<70Z8}UxL*PXfQ%l$;uf4BDr6JUB65}!HdD{d zHG-iv!3F$lOEdt0BY|x9A1?y6la7#Tea%uQ3q-M4~A)jjE z{2H8D{G=JcUG!M(5t*~t{=B|p>{MqlG_8(D;v{aIwzFumvkV6F1XuBRo)BwnKoeYr zlbxknPKnx%$vXDQS`JCmoMcm6B~#o4I=mY*txoHI>*H}T@w_N4IX$EFetvaPK2Es6 zvL+bi=p%rzsuSbxYJ7*@-io7_AfH}d2#o!!A3tgZKwx07fgv)d*7>9ZUw~rObW2lH zb9+&XnqSyCZ>yia<;kh8H^vd3#mLB1C&e^J1-PB+ES>BkoaCA?fybY~!>`gw&Z@~y z$y1$FKx!QiK86!VBaEAJlFcQGLhxloIR|G1KO}7EsAS zHOWyq#ZeBV#ssC7i$KdIVVX04stYJ#vI~+%{0by7!9_LENe(}lndBs$f9dMsZg`H{~cZh-m!E?VueXm`8r&XO> zr+)BQo!_CpkX5(qm}rgTX+zHMump4+qO@T}I0=A>fYI@Uqur%r+{BQEj#Gl3 zJxHkKNVvtg_h|35@c|jb97$dl@Zu(X8M@BwV2rXrB$Vgn+$=9GBcpAdj{!G0eQd!t z|CyG@k%|saf&m#AIY?+S^DZNbgh?)9$a%agsZNtzAb;^R=Y(mF{HYG{S}r1Oo@~6m zXpH$4z1^n`wuRarjlZ6B>+XZ1hRR~>zwxT-580d?ON%?nUQC!5fYl1Zqy~Dm*d`8& zzrDS+qV=)lVe6uwz4f;rnzH-+G$-j~C)HFZnU<4yx`S}KV*&^kESd@OIKf51P*;v1 z#&H-xaEt|NV`OG3Ct7>g>F*Cne)joIntHRYs`5!4kQ(TNRh?u48mI>k0TwbRjN@_W zY#=lz78G`3QJ4IF?Pu;M=2#q_<1NM_>M>sF5Fn{hy(7qcvbzjc#6&m67>o%xCrmUy ztM$_!t?ca|01MDCk4MkSHQfvQ{5rSEj}KdIRD=k zGkyx4;~YKCCUUBqa*S&-z7(6}lQjl4+(oSA%%AQQ1A+(bf+=^1k<_$lPNY%b38@dR zQZ$pf9`RFuJ+R*8wEJaca#3T>-QxCE%#YW?T*3Bi>L*xji9H`MX^svrOjpLXVUQXu zL59r7EYzeWxP$Tq27za&#Fwi_=vAsV;Xz2Kcc^YCZB3p0Tt8GaG%Bl{U!;4f-qvIT zPw*C!corg|{9kk-Fn(e=fgcP2rV$k`nhQ3k^!B+dAu!D*!T?_o2^;5gJ#3<^=Wj=9 zaDwvHF1gWWTXh?{H;x+0FqQXT{yGH>bMO=7DB@gWf0pdm4e`lqQ z*dS!wqAuZr2Vrng$+N+p>!JKmq=qp^8Y4EWK%IZwgdtWaguDhd79r2G{B4e_5IPfG zDs6Wa)X{WTiI%H;3Qs=8O+3k6ILTcA7k;SX>8>d{E~(lMDZp!O7loF)T+2hG?-o6C z=fO3W`_8By#HHNIyLGdnvZ%STkQ@)ee4K*RksKNqsdGd%pq{+UqI;(DATZ*f%M(iHk@}!w;L{o;X%O9zK2#K7zbH5HRYNCg5s+(-8t74k7k{B4yDs7%( zDo;Gc4S5m3oywEqS1soh{G{a^r{^u1>?t4brquFEo$f4{Z*%TFha(ZP+`C03=#&Ak zi|X3)n$+*v?Vr8lpuSzKj0n(h?0*hg&QD=>1nw7}x9sr`wMyv}_UczN62DCdjG45jvPZGV$zOjN-d5Fb{*pHI1u-#`x#Tq{RTe=8SXw{;vBKkGtSU0Ue6&$*Hwsg!5hkVnj0bb zr@Bifc!)t$c|si*p}vz?*GUQ?OyXgDUNy!$ZJbZ?7{_=WyU3+3*Qb5%ZG9ktFV9g* z6nAdrS69|xvbCaJ4N-jNcGQ@2Y@zej*&gB<9!g{udKg%y?Ftfrw0OcPJn1Ai`6QkK zgc_yoq0n)YYJ)2mp`N=`-vc8vf^j=9%-nH!`HtX233<}o2PI{t*b$xVzwrv|4^jB2 zJ4C(XAE--J!OX+1sMr^*{mI>S_4a+&Xa5{Beb*^e0Bu+0be>Y%S)$`8oZ%wWbrtCV zhJY`mX&^5OR31{kgv3*vW-XXhn>gJ_Gv310L|28@@0KRn>wYmWk>ksmE5C?T(6C@i2&M8_DM%Vs5ZSMFo}ja z!8u{Nmjc$~RGWy=--l^`?YY?|-pP}8vK9!Ir$ z0XWujmudldT~yPY6SZ9vwcQg*F5J2@1~V6Fm~Ad8g`m zD(2f?GqF14eO4&XzEfFSS6*3BTGv|AuJ*euoBo-@eD0Omu97+KNX`yW)GCS9)QU;L60ZWb(841%V)UD2x{{r7zCc>CczxyO#8_Bj*$x; zA{N5#Mq>A(mrRw3``}pb>SW~XX@I||cMfg(3i|AWvI}3o( zlU?OZ4Uy@3NOgE35F`vaKpG4w(f`7r4XHCQT3ki5-K8LHPR!)(r{?_<_OZjksEmi{ z_eyH2E1#h9;INWcSbuOvG^ReW)`+P*6sghB348+xu#b6rXHmQQLVB6*=MEFU@t zGD;cR12Q3EVN68a!eT@dfEeK?V^;2oAk+#y56L1gp)v28;qHCk_+R?b^H_97aaK`X zRdYvE8yR^c4Ic$Wz?u{q8a?F%tW%vv{&!pcfInzmbg7^}p$T82Az5V(4}#$pc%WBV z6nL%&^@lzOKtQF_R5VpC>!(R0PI^&h*zkA=O%COc{)Hy=yeLuR3y{Gg1ztylG-l+N z-XcXdewGc^gWZY%8Ng_o1OdE1_SSnO&E}N#AUu$Zjj)FYJg`}&KhYjyk7)nmEyMLw zq^7ZfLkI_QK=yHg6Uep)d+aUCB$XbX;}rlap3{qlq`x9g&0F{phDoHWc6GnhWgg%y zyn@&e26YM22HZpJG?JING#)B3riNjljqI4z+0lY}UecjHB)qxI;=n@3%Rp-APpW@_ zAn55pO)(^bR@b5AMo@3MXQ~#DfVB=UMb9G{h&G*$krTxs?bn6P_bmi6gWqVg-as99~NH$sY%bM6XTh;s@p{O zoAkc0)8n4ia*dtgES{tgD2PX5b1h~rg|zS zd8#IRB~SNK&3BDmVtZ=WzQ~yL`xVWdC6zU$HBI-bnj+*`dLR5^V0Oa5DQ=O6WG+vl z#}n&$sI)zk&`p@^ku=3UX_~tV_()VePpt1Mn&m2(UyW@6WvZUn?YdeLcb(Er+97K$a${u^IT(}b@lC|FlIj6DQ2!q4E=SkOWbT1{z7jR zY=)^03FxAd(RjdzN0OdjI@BhEDTrUB3sb>0ex^&TE-w}%A=5m>I_``Fc=G8y)ik%1 z$?j=bygkYZ@G3Fz5iW7QVDL+z$&YTQqm$E9vu>p(mlhT_w&1I8b+KA~P+7dv@wbJ} zk-9E%(_BQPzwDU^xe-KzPIe=aL)yex!oUmcB|<8=#BAWfdJ#e_U|!cI0^cATeD7%< zayCBmel9kgsVT?KaOzH+Mb&lI(krMxfM}x6N%s(y2LunJ&4IeOU)!6QetA(e;JA1PV^>dz!+fsR+w6c^bn z57}J%$Yq?<<_F_$q(6L6iBEwDC^I{SGSh7&b#$_E;4H?tV9XNZ6ZTJHv-bNxR}Up+Hb-91&+ zQ{C0SLS$JXNG1j5&2xCvJ?J7or9~*`kG0>O&b9S%TW|Hf@BUZ)IRwt9F6A`*`R;yR zIlj(_Ih17_;s$Oh$lB!T#zq6hap6ZB0KS={}3r#catzHg0yGaf$}2-(u|Q^^}WKu|#XMez+CmG(M2 zbqJY)!+`bzW^ahKDXSo7P8A$(IwlPDsP4Bkl5)U?IAP7seJFL6dN%OJ_{>`#GDizmM%g?CF^Y=-o zUKRed>-d)IcI6%T<&9m5#~x$(ug4oX>}yBu-x-|p$**;tXLdqYg`rMPFSJ36an!at z4u2njzL;!fRdyL3LCfd3$LJMCA*Q4NswXPO!02CRXCJk9iS+hS zZ_A%U7Am|w(QG-Q#-l3F@zs~e%?|CIVfE|SdS{;s>a{n8^*(fREMgQAy6xXsXOb-S zPBD2`Zly!32t^nfXXM&?>H2zg8FNP&`3_lttAZWfq0lLGR7Lcjlj_F^@@u zKK(l<2?a^|B>&-ZeCf2Va$Pxk=^5!V43Y$?m0ah~i!rVm7;N)^romcbwo6nu@mM|t zO(1mo0Kmt2xHJ)*=BcBiGP##Rs?W0A9$So+A3lHafj4%dcJNEF{8paLUIg8+L;mB; z+$@%VPDXN2Za`_-VUFC3ZAmnj&U?#y+!i9QbZ;|_bFtaFPm$UM2rg*KY=tE-iojsH z2U>|bN(0F{C(7*UiMjj80v=i+eMZyt!?XN_52R{ zw5w`=7~9Cmcn!19)WvL$i{zh-Nf6Q>2G@dA-SwJj8>PRn(f}_C%r}a2PcmZmpxs5T zoWR!{Vdk&hk`uBi*F-F@i4?CWbT0k5Z?Z`XZy z4+L>0&`cN${_U0G1~*9xN8rS>SkrE4$%KjQ`j}%hg63Zr^2o~Rp2MHF`rM5 zEdr5-vcngJa*4EhEr?nXOPEmyOsa^`fRyLMl~4axrgo@VyGj;qeNGDtSf6A>w@~Kv1xj-fbLfa ziWk1@K0yH!JfLKw=JRLBS=c{EYCNLT>l2I5c)bbp$1~{YC~lOlj_J|u>GQg_T9KLX zL6$6?k!dF6l-a@2Qe|I|3AGntbYWkS;a!oDgjRs+ekqcFCNJZd;BgJmPY5VA$ytaN zQy=Me+j1uoihx%#byYJR^O+|KY#^AYRgX0ikCcVM&hJlM(Yx{(Kvh}q1xf}IPQ z)N8{2U=L)248l^MiIAW{n7tpZ>O%0--w+A155RIJz^H(&1-mlssBFs3x95zO|IVp( z3B}Q$;c%39Xki~Sm=-|c zte1cQ(r6#L7Xc@aSn z7o_{1I(H>UQB=PkSLt92jCt-7{+LG zMN8CyMw2k<)BX`<9tTx`paddj!hi*SfRre~jDCS2oD%CzG9S}STufK7B7CPNyZ=6$ zD!R}%MLWcdB**-$I7d*qPoow&M=19%lP=@Zz+IW&UJkd_y{+Dimz?tzddkWsg3TiN z^BWl`iSg3xolN8|*t52XE2rWW-zgOJo=?@8FX5>F5t#u_)d&t!EQtSK;A|(BJP3;Z z81gwvw^I8)&o438OS;tv2$b3b6%^stZUvL2OcN3!>bTZNA>Ngu#na< zY@oYxav?re>OZ1N3#r)iMWzV?W=zmn;V1kdDB|ERX3IK;iAi@OR;`IEslMi|bGM_^ zE3m5$Hc}4U>g^{lCRXnz17xl&TmxOlLwV$#ArKv;3I7f9R+46?3w|v!jbe2d`QNp z@2|VwcQuLBW7Pm$U>mN!czaOJ#37hwnjswI78-&SU$a$oeAT%&X@hB$!e-^*s1f?;t3O2D0_o{?B0 zb;BcyLbm%~`JD=Gf|!p&4}kE{Lre@s-HUrB{hbY`-M8Osq)=2XPY?~e3!3wfpkpFN zjtxw(5Z;)JP8%NzI&SZd;YJh1rOPWr_XtuB1s@Gnb7ec?4F@AjQkw2kxOQ&T+a+qC z6R^D^kKV~as*hgGF+&d~@0Exef#gUOm^MSUjX>=Wk`NnsHvn7{9MI$F^uY!PLmaL> zZ}#7n<|-3|t!92baAga(?$-(sgt2-ScMeC=tz#(p-dfQ9HKZ)ZkP=+Vsc)Otor zYe&i9eScCBf-&J|4^WOO+(i1j_#il+WQgtvMyI3KV#SPe1wIeq@K-9!7{Bo~<;G9#DdgJR;2u1Ac5_K<+#vqp7bTGL;U& zQh|Tc8vI=5hgeA#N>um3)e|2onanV9-*CcvwpwxZl&!{HaAIQ%0n*;T?xB;bcrDW79*U`suY2`#UD7iYVU4JndBWGFd=E9w0lcxwN!hAS;+?Md)mdGCyZOEYqgc&Ce zX@cJsEe3vU#tcg{uZpEux~9)cehx`S56kps5V>)uu@20az{6E*gyp7xp4LRmj{v-N zGXFXFI4Z8=_Q?A5;QI7bX?~?+YV_{*BI~aq6JX*fl2};Zy>3fOhN@x`fGjX>&zb=3 zICmAn@&!k2zD8{s%X(sPjl7hbUOt~i{2EAOU9E*)kChD&vM>N*M;8rasG?E^Rdf&n zh^PriDRX*942Rwg*7{3Y$b$`QJN!)QH6b~lXeF>o)Z4`sIJbmmyWmT!9;3t{a{KL( zZ#^EPZcXuE^n?B`eFD}Vgu0Y|oBbbzL0o=!fsCg(Rmaz2XBhP}4Pih@A`j+DxTE}N zupe=7Iy#gf;#xCIzBdcbwfJHKp@t;EahAe}Y}`Y;ki(#dF!a?p9+eWj7j)5a+r*5X zU3mIoyrD`6l}xw3(RF1$QP1tscB!&m`+s}}qdrvAh}do@z`ltEhJ^jr`hlP?UW>bh z!8FdI7@0x+lDlJte(apjwrbLwvl=&z6&OZN{d*@d#*{suCGXeq%0d&H{lcB-BR&y{XUx>;dA@P?j#mLtAg z>#O+muzw4Q_fg|C72Ic)b?`b`iep^JK?pMDzNa0-dsz|pYA6VMXR|IO`W8-0yzZ~O z?pRH&^*uJGb@QyOj`cm8qXO{>hJwVbm@->4$x)w4P%VoJ@H72DgxHkr9P}VKuZb&r zfrtV*4@H89{eta={+o=7Fe{|Aww@N;q>a6>aZ?gANXU%v%GJ=)tgf-ThVL7l3|ail z_x!$cd6SbJ>8We#nh#|q4b9QNv&bqH{Texd+065K{PKIOy8W2Rv^@X(Mk^DzQNhA~ z9V0YpD+2%_X&^xeTICL!b}MT{RNBCQ6PRCroky74L!pgXB1Fm5HzcRyfO7+t>>jSw(7>zAU>03zLBn_U!<{vrSjWVkm8-yRJ&q! z8Y^B~PMlcb4Vy&5RN%M7MciWf~&f!6bXK`4TUsmC?Lq|?a|!{FNkRw zK%{{$h&8UP{e_EHRL#lA`SvM-_{k(+@~DK{M5|H1K-^0wwu(<*4L3svrDaw1Zi9)< zB29pfG-Pq6Jf~FT`$YFN)+i|_XK_-PL2OroQ z>`C{7Megl)v-u;Hf!0`-tktROm7vsKH7%;=6&aC?Rug$e3;^AhVz0jVGvZi#m<@a8pf~_ z?(OMpF`kiUk_ePs-(%F?gKP!!1c&|vgc2Q?Kt%^FJA640Bs>9eplsD_f) zLMGIWL=`c$9yr7iCLM-P1!!cmeo^&4cmu9U0LrkDSNy+cRrQ7Vnfp^=Y^^3U!8S+V zXTL+sIS4v1(99eiV5lJq&6J!~i@w0f^SwiU+~;5bm^1)v^!B%Pu-A ze4OpBu3kGyFZD-1nUYqgYP>fK!ea~Q--?7KAvj{jf22h)mdm(j*FH<0zN0nk{Vof$ zDuvn2@)ukxD>~nK-KXwq-M8?ya(WoiSqvFha$&_``1|vGo@D|S3?;xuthh~4Xuw6{ z`Im(57KDf(h>&fKjHFwPq`%fU9_3zopNCt4Q;nUd8?OOOGG*GgXe>@pnOHm?+ciG> z&fH($oO}AAL)CXNLU0g7YtF*=Mjz|)ASaiM=g$q42UNZ2fO zT5M?8I@)eNr1F9uoE1_fwElr%GRrSGA6T7thPND5BU-^cKolx)>PhuN4Z14v<-#7< z(iwx%sRCcAQh+B6w+($9>pn0}6U`JzjriEp_(b=p*Vj+ZA6ENatTjk!VfZ*W6EQh* z$xxU`G&bJ?jQ65ce0Jf{T0uHt#oa_gqYYioEQ>}0v}51;Vg#rcBWszL=rwend{<}J{D z|K8vF`gN#Agbz*`c%N#P1%y-`xXN@<-2buB1i3;BDJ7g(?}7oC?pIRZgVrfp*9}i= z?j{03tTLtZ)pi$PRYN7;uH3ekhTFoou*EaezBI3CE&MEqEs$TJmjSejLBE!O5U`}R@Z%bYDQ!I+ zVDjUN4vDBklPUv;uHVJJgWTPe(&o@)ALA?pt)?=e5k)O`fD z@WBS=Q0cwP2Ju^~yn-RMFfc;tztf(#w}t2$G4S9d5TeK>3^Rz?GK~=AzsBkIizKJ^ z*_;CK$yN>4;ZLy#Kt&2#(@){UFv?RO33GZJb2>6>1#Su8MBw8fY#332O+qSh(!IY* zd!Dw%LWB$!SqFFisqj#HGQ!N|b0S`liOH%I0e8e@z`?c}_7FXQ?X<$bmL7|_lz3LQOFvjf%&D=&S+CZubLCXSc z2O%XJ6kHjEEO@i)=IL)D7j9C$;yTH`zj1c(u^;vfOTcEB$;x)b+6X&Q@3=6f)%@8V zeoL;8^?mTH&^kfjA!dJvQZqE#o{Rc39^ar5Hip+l4g!A=lP&sdF^AIrYtO!Ymhz21c8 zdf_JcmtmTUB$%x62~N96)anUA&zyjpt{?~u>=FdmkhAn8T|6UHzdj17*N%W$;XkHp z8EQxQvCD$9me7==^jQ{)6>a!Y!0Qdb5H(6eUAm3(?WzM9dV+BE zcpmv0tP@=8jHK6L{H<#YXpk(6MZ*};ja@Ipmxu4%?AMcSUmwP*Z&nt!TyW&%e7j|W zb)YxmkTbpd$4m6vnxF^dYnioGmG${(Hy}w<`Mdc%Cz%J7!%Ii^l0pM5%LX~2o0$?i z1i--mx#ZGh{yO@oykI-YMZri;&K=@d+4a(dA|wGGo|2-4NOWG0jZAw)C^kX zPbA4Za_Ti813#(ySM)0-q0tsR0qpfZj$o|UgSeiAWjCiz<|;QtHSnU&TgWtVAMzaY zb>7T@RIiR5NrHGGdx4g?1fNcaOsImzn+@Srf80Do)tOZ6#>qS4q{PD z?37M^PFH7xJIH_v1Q4{$pubKXziX{bJsK=MkjL!H9GoS2El9jF43#OhEqdgH68zru z8o69VveX{(>O{Ae=N0vJmDT?+$lCK!PWdP{9@|`0(4~ZaH)z?nxbr=?%H=3!f)1Vs zCes8l9aQT4@fEeW8%LCmI57<>3naD+-=|{Iic->v@b>^akDjn-r`LsaeNGZKWmFQJ z^(8liNl`B#Im&J72L$9yha&cQ@6Db2Ow%?)Y25sBzdcs3{I*4RASBjH2-%XayUF|K zC}S(a)sew@iCvnWt3dS~=l(Si7mV;kxdI`>9xBZd8p#m`Ma1zEu+=194JQ-Uq?F1I z86^NE?;)TO9@#|C8bNteH~IW*Zu=CyVbXYwvBEb8qG=~D{#AW(7ipA)JB~Eap9j$P z>!86nLtv?qC)fVV7^Mzq6U?Ppg}hc$(e@@eGMtH0mg{zZ;pN1hg~PF*$_GiT`@?2f zAxAW-^a0uDm??t1944(~s~)<5E{ct`E{PFBvm87|n1ujhByihh>}3% zejP^jZErt*g!p=dNVaL(nfAKz>|=y>13Ww$yerd{>5=j)rO{}DPn=<3b9 z99oj;4)g#X?h4~=ZyIMI#t4Pp0A(#Cu$}o3zY|Rm zSbJx`64h|EMPJi9Y+4k`xaB#H<^mJ7SQRRYfh>)HjcFC97Qx4>nA6MI1{D;i_|HH8 zO8PGKOGH2%FM~42Li!K!qs;iH zW>M%S(shv8V@&VPk74<{#^V(t@qx?`UtfzGOh!Q7O|0?w6Eu{E)_ofV`Vs{SM)Ui% zvg_Z9CsKds0kc5gK4Jct@7jJ|8QM0+_CGxRXBLK!))z3Pw;)J_b1NF{v9)Nhl6;u5 zup|!48w=%08;o1)quSQ5tLL(kOAwzX^$Zv(B>jN+QN+AonTYBDR%+#I-=@UYX=01w zd#Z(A&VN9A%(89XGAmxv>>lCl9#HDu_m=X%K*gdyi-&!YH*20EHg|nYvu8{_)L(|^ zpX7V*lecfrw}>5qA-p5fWP#dBQFEko9;S7Xa;6cX5h{bQ z@xhq;(UN2b&}jEwkGi-r2UvDCQaib14f=W5>`RaPbMZJX4)EG?Ja~mmB)j}7^Dcyx zuuzS)%~f=b(XcSoE3errY!QY(g4}%*6&|pAUJi5SO1kGNeF~O6C2Afcf(g(d_WKJs z5qUKNI+uC8f&ipYXqF+d7Mg;@q1|$yhZAk)9BJV1_yZD)2|Vqm2v>(I%c=&lXytkK zLFuYVR3AkRaSeXpk74CjtoRUBY;hUH7{K-h%OsP4{hJu-s?@J6oIgSBsoeS`B5!H! zP_q5YwLjcBJoH7#gi-*n!$v8&<-E$Q1*X2lV2ro_REU?x7|gPdlfUoVZbIJ2ScGj_ zw=}dD0udO;t(NM`$pqeYK1P2~I)NertZ{9)sssk3O1hP-eQK)jyCLTCr4m|BNpvsC z2&ZNfcLugjNOZ2Jb`EIPFBr7`;hPV(xApE{NJo*_g%KCl@o4D@iQNWKL@%BFED1|} z2IKyP?i21LWW_SOWYz5)Imn4evbA=AMt6^m-81)^=vbwJ5HQl;@7$cc%kUBs?+Y`- z$FY6-muYbV^BXNNc2V66c5Zw*KlL)G1tQfW4uf})6v?8HAXFz9Gg|{k60(6YB^jt_ zxC2&2|MtDRp5S)+MK9?czb7kAMR99(^G{bgL44s4r0`%66EHKapgPK)k&|ExS_rof zG`uog$hl|4b5}tSW+Uhs1o{?^ zi?bi$@vp#H%$;2}z=ShW|dNU#z#8WDOcT_r8kZ(Zc?{=9XiH(+lO2+Q&H@!fI3dAHLDxps+r+tPs0cymWbV<=q1LW%dxYQI+e1u1V1Ez7sVSgL%zu)Nmg+Rs%YU z%^Yqs-N?FrzlFAvZ|1p1>cl(U*rJZGN`%7c|b!ze7y46nGbAM6h zz+n=5=mbY7jUZ0H+WAx2@|BcUBgc@7J+(T0HE|NORwD&o6MH9sUQef~>W%_GtM17bx|C5%O8YT&VFkN#u($ozYt zG`O5es`aH|GN~!h+g-+C99f>Is+>+t0mZw2xn-ZV_{>#+vu6FO)yDk9sSmzbs(LQMIDjtc+`q#tky_0-lY11D2^^oUVblee{Bno$TG9 z^w<RjYpW*L`8- zEatwsHya4nzf(IPchv35S|GDYeCyAX!|*V}wRZja*Wuq1a@@2w=3D(^`^=m9D>8zQ z$8TmB=X?5D&|i;_l$q;ZhtZCR&rl!KIU6jfB@iijIj%L^6MF2tgVg4tfQ{u(U9-MH z@J#aV7ygYhdC8Yg&|CdkOJ3CP*8@373rux{##mIBzJ=mlikhvc+&a5!&~ub)?VjiD zmqG7;&tK*rr3l?mQ?;p=St&QCMHsF8Eoaf`_o?5P1S8Tk6`rf1&<-^*OTd)EbFy;B z(ArY1!W5_7T5=L}ol*$2c=jHj@pP>f0f*tM32LhFM7i?#ZirS;sqsNarC*DXbnDOWj zh!K+TspY3p)HoYGZ(p-_Q`fwm7E>2ww~eWGF`AuochF2xC}y;J_Rk9#)dM56S{Q$4 zk0TP1TW$U|4V~j>v>J_npxv)@etm7%CdePGu--Jk+KJOHMi0a2H|hs0UBAZPZvnn? z3m^1lmXKuXtWtb}R@UkDCw@Tt=-H0jUs`i?-iJkIYDA~fLT>9}Y3)zRq~)}6V{^MH zx98pEF8Y^J^ap0rW%T=IG?Ex?x5wKVs{EWsavl<2w|s)mv?(fLl~KSi4Cf{m)baRI zwK}4xUw*qS%xyNrcJseHyt$L}wj1p)R8rJ>c#j_`5P1Eow7mZET#o6PS#v#^8#H!) zA{FSQIE*NoZ2JV4ZJ*i9HLmJ zu9so2@pPXt-@)fk%1%|&P*zpf)l^$qJUD&4tH9%CK2pkbbznQ!(o~exY`M)&Gfx?z z)8g@7D=DAp!u^ZbR^tt;5OVM!hQpfU2unJ^-Amzf_u;B?RPAZCbbfvH%6%%jJ=Aej zqW;KE=^kt+0M|QQ_4xwnt*$*sCqc{%PYNGZe>vRuuz6V9C1AUKw#Lx?HagBx%GLidB|j;slyp@f zE38rimpmSC!aEogrUv0@FO&f>^Sh`J*{3hi*FrgXfyvhyw0a`O!`=Dcl@fo z$##5+@fG(n6Xv#x*r>FPUHAk6F$vQpQJEE<4W2)UGnf%rcASD0-dtZU;TOVV!`Mh) zFM#C}K+cP;uPKf9yN8->YSYsZsx8X zO(Dx2edW45h<`wtzLB(g+H0aU_uxDPdyO^C;&=N{m0nJ-Y7`48W=nRB*4^q-Ml>D6 zbGgqDrw!;XZgkJewK~Xgy0L(GE3lMyqsPtm?yhQC z+nD&80`11jq-(%8TF#|n4W&uV(E2(5EkkXU*SP>*yz`aRFCCdNZBX8gRC`mHsj! z0!tt>nU$T!&%#7z=kBywQ|QPOJNdEImrn4>X+83+vh&65wn1Rt_3V0~{Z6p?a@)h; z^O>8g@u}blo9pE{F+Qc;ddYj!7pbg_1HcS!ymf3T7-VB5ei_Pl2Nu2p=-JGuRv<54|qR>%z%$wm@K}dD}kbh7WBz3y$+1(IhJ;+hmrF-#b ztJZrr&v-F>L!^yj-nZjDEG;Ndc?Mm7l28JvG94Mp;_S7IenDF_0>VV9~v_ z(cxAJB;=u5lXhRx?fS6qDdwu>siwf0%<@zdD}8OGQNFmyjJ(vO2yf=dGC1!uLWM;6 z$K*&`dAYeg%@sWB$r8Ph$p>%ka^j}lB#OeX&5+?| zt4jzeqoef_4=Z6=p)EQ>N#HX}m|K?2WAfx-vYKm9J!nzfZq}P32DZ+UKe7^s6kZ%Iqs@?1khjTW7pI<0SYVPE^;4 z_R3Ch0uW(_gHNzkcPP%foTe7$CVaP&U8g*UO!KWPoY4VGDFBY7rDc-*iaF=<_QLvN zUAoaqxy))gqB`}eIldHd(1+~+A_WQe?9#@P^2Vl?bf5m%Y}yy1`%OTYv%tsM==zTD z>tx3zQ-RPmFT=O73UT7o*CSKGuEd(pi=S!(5B{JqevY3!G%J`1uX&WSw zBwg(n=wPXAmJteug%;C>Hp1##m#E`0@a^@gb=$6N_!Td0{Ifi_I=!$vzj$b4F4 zUHbhML7~U}_uU#h<3H+^_al6e83hb&t~WLFy=qBn6AR-94=l}W&EY9}dUZIe*I$g3 z1?Iy*BcWDTxSfj24mE8=Jty$wK9-0Ahp$ue0JNe3tyKw_moq z={9;cZ(m#Azd!EXCFBXD7o9Rh{G)omdw^?a-p zOS8^?5|c2t+S`7)iSap3v_=aegY^bvQ(AyF5xYNRNt|PAS=i@|w^v~}L~E1+(QkL< zPf6}o{MOc?5T_%)g!JL*cq=1vhXD}idK8S6$9qdVSEf2c$BV!g;k9^M3Z400Tz!Xl zL-NKmSj?(#{g|5ZY-{`6r1_&u!$GzZ5`rZ`S`{r~WZ_M`Y+cz{#&$4$4z_zi37VXU z3jvW)wU!HWhNvv5;at4bUf{Dviy7)|;NXiY-*AAKF#;bj zOyveMV5AA`5lIs|EQ^i#I#1&8uQ(j(Fj~s!k9mQRN}aP^y)_v#dGS#P!+bkL|X~r$mNU;!tq0 zNxJMV)y>{{a|1lOm)oIFHN!D6Z!Ia|NQ&5nkLf>9ICx4>V($*Tbks-h&9lBxYvq^lKwJ` zosf=NhgS^5eD2AD>-QHN7ceWGYg;oB8yIXk9RT-t865(?L)Fp;&Q>_?W;z zRr3I!%S#C0hyVNu^qYqW{kZ~0Hzvy%<2z4=U$&u3T$ovm%TO?_v^E0S++dkq-~fZB z-kAXiYJ210bUk9$U!*9{DXOb$D{J}u*g8WcPa#7`JKwpnO_q^Hgf~8F_`7 zgGaJb1-S`_x2C2)O~&P?V^rzomK4m)&J7K)PEOOuXi2E($W+|f&R??fnufk=x34l7 z6B*PrXO*jRSIj8@6>A9=ny4+8`w9*OH@50zN%-4`m`8bDA^-udg~0!+lTgBw$mwo* zDCnFe3{o<&YvOxIi>OSmfy;mT_7@Lso3phv_1WS#ib7s>PH=-2c#eT^WD}FS<#eGA zxb>c3vx2k|=+HzbcSXxv>)&u72cC#=>lwOG38YStNS+Yx+2)5|Hz+`A2rR;W`-|bI zyrv61OrB8b%rv9e^vkS7((P(AAI8R!360zxZT=$Me1ynxQy;j;P!6vyzbtF&SjZcB zR1(8dL3Yu05R?8!7#3w9|MNyqVMW5S9K9@b8^FXABzI3#WyniktE@gJ$c7qsvVKqV zcekI-m=5+5uV6Ty&#f3I5%P>GUn**SIwSl{zy&<<*jG{+TZMl)JLI|7)mG-}W_MQW z;^j=Yl*BBH|MvMoiMRC>(KY>7Tv76NX4Yb4Rd&m|te&D*Mi0Gjs9jo1$pz5#-7|U( zxofz$AySUK{fTWM5B|GTN+Iy&hAVR6GqxMKc$Z;Bx4ZB|+!Lg{+KJAIdu2rBoOWlqw-p7@HieV$$qInwjBJ z_VGrE3cNWT?5psd*FpF_gGiEfH_@ASW*#b2=%uQ>p4_E$Y9+zbKPs9|Z{?c{6IPbZ zfdD@vzV(I%U{BC;=G9K}LSXbw>tQ zetA^(l*bAYs)FrWuicBTVsXPuFOXUlW>Vqhx_Hmh-b4jTV)rG6l!_UCdy zY7Q9cSWBe%GrT)b4y$`$4#~FhP#uKCIYP!7#NIr!xpYr^Lo17QpC=soRyyTa8nvrG z<84o>D^iN9h-Y}yIT_`bvK9Z(RVwwDF-Yt%-_p1#%dOL&ppx^C;Z9^g{gj<6=NnS0 z?{Lf!XQA3!zI$6l&HllGxPyc60!2i_sff%9FVOSk#)Wx0**J9d`Tz`2<;b?u>Ep^h zU2vb8J)0?QSyVwg_@dA+N9-{H^B2OQ*#^-l7sZuqNB{y2Kjt68btJp%z93o{)pMLd zy}JJXn2Vh$;40^QT@kTO^1oE{{Sw#v%{69h3&ZE63G6Wpn;x*GV)XST{Ln@nHA;-m z-*S$PSQvW%wbr-u=wBGyJI$W#=6H4iJG&Gq9Hkb}R`!5gfS86pX$kyW05kDNQ+zEY zRo8jl+r3++2Q{OO2@^6cQtA6GF2gs8x=B_R=M$&a3_F}R%siQx8U?M%aQ9aUSWxc| z$dN1UwMpMJXE^4uol2!HDlLVXt46C7Sh|G%ab_ZB0E}Vwer_w3ijdS;T4a`F%4uLFT?tK`?fs6Hw^u(}6bbUw6a)H4EV6 zCS(fC^&%BKWQ<;T=5? zy&h%d|7Z06)0jUZU>-Cu1L_Jqu*NU}!Z9Dg4P*YlCXzVeD~9?KFh|{7FP<9sYSz*z zmO1gbBnODl_n4_?X=P1FGqvVJO3GPu>>0NHpC*+O`|rVh8m=16SXqUNUtUabON8weLypaECd@(pac}wmoQC6v-ym0s21k^$kBgB z!s6!~fhmNxO5H4RNhN1C{$V)#rRk*LY5yD?by?k3-g0DG_}3``g;iKpkeIttIO z*Bpn?ilcT+7hniDuC5FZy0y<9#r>E5<`vZFMeAxEBMB-ME!FSpa+YzVwS`PArqihd z-q;wPQ;mhD``JrhCE3sa3d3%V7?9gShYW7UfKIY|mgzAH=TEQ<4bM1ObyT5C4uSEo zHhPICx2~0SZ4aezB#Y9y1@V7%$N;ge3$ZRUmm40T0Q@&3-JJ;=swXUqut*tIXOHg7PE3RUqi_HFai#@`)*Oo4%k)8u8Mr_y-mx1!Jm&L}o8cgoTbCD|rg(u;~6v$bc5nf!S4%%EX`t z=>=8Y^c8a%ePo_JI4a0fH%pNvosEHHimM$@vFz3Izxw{eUl0i7?3T6%meb^$N|SM5 z=pocCy=_?NP$*l!=*>PAg%w{qCyydS^#62Za}7!`Uby?FmeZHo2`^obtLRm$r1tgH z#clHd^-eLEFT0I;%nA7PsPzBj0}dom&_tBVT&Nq_F%&}Y|43ni*+B##LTjnqNSdC) z0msMRWxD)7H-&|IrxyoJt=74Cs>Q}W+<@@zRm`En!48rZpfA@hJTFe;hrS8ITC-PS zOzljZU7Sn}ZU0lUH?o3ZW+P-I{7-?4gPo22|7tn@Tg%H!$RKNKXYOJ_$jtdur%cEo zZfWCU>hyE9F?2B%H8r+3F(u^ZhxspA58!GITl-B>#INoiBN*t_5Sz}Yt99*h8SV87 zLLwNX-xgY`^GPKSA>?$zA6_|YSnt#BPlxiN6l>=`>Cc{KPup`MUJ|yp*`+OaEihE^ zuyZAneQVPIHId`e2b!+@0Rn~pkFc+difdcCO|TH$-95OwL(oPWch}$$+}+*XY200d zyESeh!9BtKBj=uT?)~w`cz@_-!QQ);?3y*JYOR`9kbm`f-9Dt_73yc%P*4f?7n_`I@8xG?ax?>1040+IPQ>O(2?|b)6q;Ew7h5 z&^r1|!h#g3SQBZmD4v%q%lqyY*cr6zU--i=ou4mWQ@1mYsXe-dEBG1O4i-M13-+K8 z(I&8086V_FK3*B7I@5WZfx(ldR#w+u7d$u_##jaN+_!1|o%!UIdkRk{_S(SzA~5Yc zqYAk-;hPyzXwaFIAEnmUEOLeGDCxZoV_*>?JKW+= zNxw{(WTFy>LpUTE4d@*JVIR@R<8ptP=AFKKau(CU8_H*aYb~iK?RBKRRne#pQgG-s zw4@Rl6BPA?5P@ z8-s}7bi=iw!<}%co-wrk1$HwjDRT&MwjoO3c}|~=#*FUxzUevqW>$7spb#u}I^H7U zVlYlUd`HlaOml;__dW@snO%i-zxRBxVv+iSEJ7(Kk&>n86xLQ?4y73#OPU#ro2}wO zW&*%t7}I&6&c#~wZ@CYk-?1#iePjrZC=;3kd07Q20{85XzkH-w)R){7U9%D8qQMcy z667!ecO78sEiGgq2)u>{O!ltLc`l}^nf=bqc@M>XL#6JcK1VE`Cl)ZC+RNhbBf1f# z5f=cFDI}5e4$|KY_St*1SHKS?;I)+=k$T7ce*7E5C6YsR6N@s_KnzyaP(qjwW8RMw zDZs|I75+*pU#r-?ZZsclsE^}Gj2XPI7nE<_P}qldeu;BPrgf&t&U=4h7JD|Vu@y*XqTa!yNj+LF5z3~SbV|=W!A{hvm&+AUS{=>oYRPq{AS}J z@Gj>SLmBIA9VST(UBk1l#+bEZ7HrpbT=)`>VrlnmiGStqH_Ha6%P%T&VKJ0o(Ag&Q z2^s$`=@EYK-CeH_zw_=M*Qz@n+fkVJz3sH~Ve5#ns*QMl`_Sii(n3-VYGXw-2&@=@ zuhnA89qkdvKYvW2FJ8J8gM}M}`u)nnsA!;0Q8X)4yhxUj@(7g)fJ?s!NZb zVn=w#$5Qi;MJ1^UCrI_uvxtnbLPWA3DJ5L8ltW~cZjUWVi=Fh1d<)1%Sy0Q(5zQwG z6;A^`PgXcs>a%DrRYCW+k5&d>F-s&8BF2+6^82EF&iNkfLP5zs7$L(t>mIq!&)TT# zsNukL#|E3Cr{n);;>ORFtpnToyZH0gw=RYv6Cp*7BemO z+t|Z{f<^C`q=Klg{Lt-)QdvLcE<+j%qj2L@)R0V_Y%Fk$KJfDB@JgcD99Y$NahASq z>OIAZ-sIQWPGJ=u#Ihfxjom)lGdK>Xaq+7tui*D+jORxmLsVuq&{Y=eyq$YOo~ocC zu|9yY-;cl1CbdSOfg`%uf@sI^{Vq2^^j3eCwlMPWmrROd<+pwrNQcnp=N;IA2kF5q zNaugx>C5m=50-=T#2+@r!+)>^M6a?k=5@I@%hS?hu_1+C0rq=ZrDIaR~li{u` z=khTwMc(-lCp2o7=Ey}j!Kr(A+PG86cgKK7f~=1#L6!V$ornMv!bPkgyc^bc4N<+- z!DaRCeqh;cgqB1vE__x9do#u!f>Yv#d=h@6j}z~8cxm!!D3VGU?(HB41y-2uzD^`- zVf3ND&N^^NJjvh~!6}8+5s1{mz*~g7uM}cn)9^eZ+vsi+cZWP_Orl0rCTW|s9W{{c)DcY9M3CPhQ@zkWKJ+B%c4 z{RcahO`Ysq9N+d+kg)Rnr$x-p*7@xp-WvWu?i;+ynVMJ{irTrsX*0hyaI&zHaPhF} z{z2G(5c|)Sf1dvbn-v}HjDe=kB-(FZ#U)6XR7~BRNtmQ<-kvS`_ovw3pVB0{Burv< zU+f%#_J+o$B!4a!b7CR+OAt6g!8b&IljW~w2^K~c5*C*K2qeME$V~Dk#(%({?ayD> z|N7<6B^nAwR;I@Pxk}oGjfCxw(8_=A_FsYjYWqjvzl{mDzi?BN5rk3Uw&LpfXoNxVk8#70HyFUg9oU^0L+c5u6zgYfQG;aeb zYU%8xXzD0tXJcfu^O;=Y7I?uj^aa7+Bk4@mH zQdm}>9}DbmmLf%tAdNm!u-ZH zSgWZ#0;Ri)7Yf0nz~3S~1ciZ=R}^8uAg{wpR3(T8T4_eHl*|Kjb}URnzEMWR-U5qb zHtn;l3e_x`^fl147D5IO_v zPBU-@7N-7AT;ifN>ufsE%J))Gl;;sr$Vc>TbBx+rtRn$GnsLj!AwI^gF6DxvvtK%!=NZh>eV zeGqDOI)bK3L-!b90@l#kOqw74hv-;Q0P0#noL(=^VphVvEw`92t6#565-6T)6)lfi za)u?+wmH2)Ox#$s@OSjT_x8nt>h)%J7>7o0(VBTX$W0YBaOP8$(#NhL+H#ak*o%*! z0w17$HX=RG)6%r6V9=7OqooH(?W<79OFwP2?R2hEIRJ!$X_WJsG~rNGjHM}UPR5m(j$lNC;lr-($8MM zeo+e}E5*!!15@!*5Khr(tV=Q`kW1RaK7+?aSS$Mo&b_EZ|?R)jt4Ew!FcIQOWo2Es@%tWJbAQM7F zTgYCDKB5H=QMyXYKT4rICzxk9pP+^K371MUyIi~JdG<5IQoS`(kvb3cE-&RSFV)@( z!Pe4DJ#}qZ2AH3a02d(zl&RIS%IU{1%f=jtd-BeYE2|=~}VKCy=q_PFC@y z?S4=J?1q=sqt8;78o~L7W3CK@pBUAj7R+Un5xEVS>c}wwK3ULPB!I6hGmDBoOSJDi zyib+@%^fiNMK!a8w8=kDH0*``BeA*oyAp#oxT$rO>_y8fUQB1@)iwAJUy^0=7w7f# zmWK>|tCQj;I8|i|*Iz^?r*Ds9w#o&QG@6CFzvzpu_!o^mk8*e>TDej$oy%aIcdo#$ zI5gnav$eU{i7s{D5k(ds3wu5K-z^5JWFS+8ArCGQht~+=>AUl{@08Na9?~3~1i##t zlficog)O+h6=N1T+JW-gpjtvM4^#e-%7y`JX1}kvX@%Nufmqs- zJB?y9SFwe<+tyWdV{>3gV3eUFLCck@jgbNYXe=wjIFpSA9FBZaK z5*AnPVjq;3wp^W~kBU;e>Le;YH#ITS1ihPN8;7U%>H8Ycu38!p9%^ z+^(n5=l*^+uEV!tUn#H70ViweP-ifK+BAe}($8wrfuhTH$?GlTAahAa?A3Q2=-Rgw z>?g4`Tg2*~B<&u);`jcw_5GyK)S^z)pZDE2>ASDWsJhD-Dx{T#01sD1lF~37Fsr`N zJj+l^E*7gg`7eoGx%?e}FP^u`6L1q`qLvx*WL6{>jOfS-ADYCbW>=b7+JuI&h+-K8 z(bRot@_!pBBVw#U#z%i3*FutLCW^4)L)ma(E0 zLc!Zq7^x7nPl!CqiynXKS;}8sL|yS&la9O!ZmyK{f~$X-F>wQ54YJ$eUldUYeup7% z_}i{5H!#ogQ#ixH3nl-)o5kjKSOR$+M<_ZT5*6oZIQDrIXaiTXL#Q2^z?-{0`{PaD z>SN(5u4(4Cvp^QWD)KNVL3mYzBGM4YNx0os`ixDs6f~4g!i~+xDn7JT;l;&|Rf`S` ze8%{$5?m({<$O3mC-&-_(z}d8mgLZHk+G6kD+8(Ro8>ZPI9|&n49ByL#`Z1DQve)$ zxyQ;^mDo`8l)v@#%Mq->7*oT(h9y&5mYOfGs55*0)x_ykVJ(j&hYccV&AHIbQ@nq( z^+t@VWBZp2^AyboqcwwfTi6@*T;=In-*VA$Mv)~WktLT1qpKSz_%X;gvDZ5Jsxj-? za^T!>PZ0dyXWaxE6OXxkVKXrYTvn$^9EW9e&ANQ}iJxzD9*cP%Sdsz%;_RHi zU-cVDsiDlYR=cDRhmm{Yu&y1}{HW)FZhCzBFWcY+0Gqd^22w{ZS0$v?b*T9v@pYrl z`p~m_H@khl>E2^9haJA69s>t~5v0(?G0(ye%?sERhEoZ{Ynmd;)-bm$ zvuCU^my9vzyV%-2)t!eoM`F5IYWcZNr7UVAuD5U|x zXFofYm|i9cEoMlLy&a-Gp;ibLK)FrtzYc_h1~|0_*)<0Jk}|)FbBKN&YVpsmGG43t z$(J_iC8@)Q@KdO`ktm!-(Br;a>|kT$@&0p@T$h+KVu?U;TJHyf?fFd940BXZUNoT} z|4}sWV|sfc-@!^QFH2;Rs-0gRwQ>P`df}XAZFnHd(5(;HFJb3Q$_)KK-bhX}rq$HZjej`*Id*&|@){?@HNLaOsFX?OiS# z?)N=f7iujHyV}SfZ6tu381gr0yIrOyrvh6#aOKWpOuZ0q?9kHM2f?7{ph{fed8{2T z2GA8p&@A8m#sPY%K7%!5VN!zyime^N6_xO`Hl%}3ZJ!el&ktIc8(^`PhVm1#LvK5C zH1Y4r^)E$rO92@kawc#bggJ7MSuhta{p4&q-pC;A19eoJ5ye!jVrw^$x5EUciewl_ zA9Z6YSURZdJa1~yE-JZPbd;g&#H7IU&IOw6KiIqO>SzI&O;NwTfbSZ{$QK=j}1W@(H#I={HZ z5^ZJ*npCWYe#SGqS6l8%uiZQnh*u3I8~2Hz74&%iHO)0Ayol-Dp5x!=zsZ@bER&w` zyiJU5=)-AcgW?0BlLgB40o|egJ*l0dP{IRImC@eyibS~A1}a#p6o)0}1Zwx|w7jV5 z&fN7EZbsMJMKH$)8K<*9x<2Wy{nR2c09@1v$Gb3l06Sd2kOR%Oy}KC74XumZB-sJ; zax-69qQ-d(j3hNcE^aHE2NC@a9Fl1Gy(eMs>LSWRzrU3jlV4NhVmGY&U28ktI8%CZItBmhr$*p){@IuBmWR85(tu? zrBH=+!ZUf~acBo0`3?#g%8r+@v+9NF@7$CL%{bmK*hZFbVa>NPG~=>G3)5)E8dxot zxehdG4Yt@t+HAm~yHf1xYka#MUN{Y}lQg-Wu1;b1^%V zcZKM08F&3YmgM+}Sag|m%{(-$nUcolHu$Qa>$ki_>MI7&KYZkCNb>wu;#%MA0gB|1 z1rBxXSDh|Z`iZ@0@^lYRowb`*q>F1#?#$0zCy^i_6uDtdVnn7po{|A_P+o0agAD!I z5xzK+pG=i`_6-JYxf&!1l|&wn|Es@3IQ8T|z1D@wDX<(`)nd4&ge3Pbs$JrsiFMPc zeYJYXIVcxk;n40MYmr#&^FlPQZQ8!p{-H%`AfZTcYz-3|h}$yc@+IPQ8AC1|kN%@4 z_mvt>dKHu4ru%k&)9Y!K-Y;tcTQ8@%*TiRA;xlJA-_TPj_vs^o#CYlz!KofQm#>r4 z{uT0f&-SctRboZSul-$I5w{WxT9VF#dQ_D)$w zn4u8EZy4eaMr;TDj5B6ht7I*L5KP|Yl?SS9+%ICz z<0Z?@lXVOvl8O{3+k6GbX@&&sU5xGC-YUn<2UJnTtN5x-$1+o2d%)L>vqD*IwT`*- zAGGDYTXzSrJ-={fU9FlDyDh$kRBd7My;hJ93Vz2!Lgj_hGY=5M-;y==W~^EBeCRkW zRkIcRbtoTt?%Q2IdOX!E+qNb;mUm(oZn=yx-x?l*sBLuAG6WV)v-I|KCjZ^QfQM`A z|F)ect(jrA3XDcHk5EOdXa8tqou6|K>k;;ut){q0fU)WrM`c816`Q%qk6@uTS|Z#$ zZs#8c@`kotsLZTQy&OrY!O>rPj#L8r*+`WU{l!#$ytjPL%e>=v@%yd0B*V7L5%rH< z;t`L@GMfj)9BkLb)7zopD$^_L8c3UsP1=c$nPbGm zSOtCrFLb8q@a~xA2;P;Z*;lm zd^`1D$3}0^J5!TB&vaJgc1<~fD(+ayOj744tRW>=ODV0>8K2jr4JFk8={9J*#@;EC zgJwhrcCQc+i!=O}R@zF3$ErS6uJY{{ZwktaxBur7kDpcn&yX*Nwwu|7W*$w z&V)MSoZ?_I;{e5Du6nCQkfz9lN%Z9%=8~4~#PZKnoZqcfE#0LR`sIPLxT~C69P=Pt zi;_LWi=T8Jo%QO8)B}I3ItU1WE6kvx4PK}ndVHPkm5k=xT-`u66iL!XgCum~cmSKU4b#kfp>>N$%tl%3coan{$OG@~UXn^`WW z&wG8kuN}{FWRXwF=ZTlTa=0Rn6rrt#pr+xCysM_pQ_9!_ObXHe#n5|E-I`!=(lg?b z)`xoeAb{3y^H0SKjr8bTR2%x`62On52jP2;I4g%=n5ogq(*FK&&)!KTP^n~qDJ8ZAEE_Ozs%)}rQ42_1E6TT836#sB5s1QPJYL9s4wbmtqLr!i8(8z;n}}uH@*y+V~?3RpXU0z zbKhY*X`#}RGrvj%I@dnHq`{m>B6fOA6!C;u7jshQ zyB=1nXo6HWjh!H|B3QOXuk8~w3EV#wFvMK@Hi+M^z4W=!HtfqL3T4T?c|bis`8W3g z)FKD5R-C}*MP5n$PN2r@%;v_bOrwn1vjkt?dVz3AFgdij)pq{H9|rdq5x|7VgcJ4*?rPVICt7 zBQUTMb~aI!YaWGe*{{zWwsqF0Odm>iiju?mU?>vu-xsK%Luk z6&Hk>V|OW+svgB-ARGk9z;m@e5Ve^f=+PDYdh=5*!cLZ{cNDv|#l1@gzqD+I{J?*N|5 zHvu_Fe;dZkP!n*V*+PUOvGk0iRk#8o2p}>t^7T=;oYd+KJP&?#s?a1jss?vu)}8_w zSm`iC+h|g#f5f{aMVETavXab`98DJ2#1Htufd|=o$d+Q8Wf=WoT-4AKAtj{uY634>ac!PYLv1Np ziKB5r(8$^V2J2dbc>cxPu19khA?aY&tme|L3Ws(7Dq62{W zq0skyoRhs}oKC2{nI$}5m}OG98ypege#{wEAk1M{A3 zQeYZv)sDwja@VW4w{1(wgO*l%7y(PrB3S9;tx*+R&(mlm_C3&dMOWY4iIkg?uc1<8 zeXdxg{F>R7+`R!u_L47sH7P0`1d^{(J6!YJhO*`Uo^67eRrjgL%f;kp4;fy(Qxx7B zj+U`>t6-;@3&q6V=S;{m!rw98X}W6^XNtFCr4q7`0J*msSw>bV$?BK(ZnS?}$-Ss~ zD))4}9Hv%XI{8VBh}O4{5;Z+<8(3y%+FkNFu;A_-vR}K1Pikx$yHI|$LPVN1f4v4_ z41Mg@8vv6W&)QIBNEk(d(%pdH$|*_xVD@=$Ly zS1A5fHy&R(jqCD@c4Dz3Nz(i#d~$0}J*MRoU-KIEiPQD=_8~nGRAQxaE+0FxJvCJc zC6llDi{#^XH?P0pYq<8v^R6|>pENPG zu502#&c(FolT=B6AR4M_SMPnf>g%%zh z_x6tOh4h#tP=yyOY}qx@s@s$rc0J-3cAe?Af*|#_TYi^UWVC+>-J!)awffQ;FFaqF zngzNnWP*^5{4Y6jL-N-*v>Fq+NSPaL#I-mJ#cxU(f3T*+_X2*s7bm`g zdq26*e1jleq}6I{*q(q2i2kD3UA%Ul$D;$04~XWGhRz36EyhpzxTIzgxOCM`vN)?7 zlrJ=0E%@Iq=}zc7)fsFAlgWx=xNF;Iys>7EeMW-okJ6Z`k$ewp9gmG^Wmz`gPPRl} z@)ZL?q$RmgEO$cxT0u`fP%n^xu1#vo7S{p8n&Xz=bk^D(6lfs%Uoz=hX>!g`Kww5l zSz}R`_9D1y#r5XtHdLqkWptk|^ZWF)&eM+gMX8V`ZSFJ1)#;&Zg%8r*US7Y*QZM+a ze&}p7CP(kh^jyONK;5NFOs7BG_C!9({QYbQuYd1HI&^Mh>4(y>x?eUo!0fT#F%`wP>k;V}PAn`oUt&d~5 zy&A9Yo+d-Fzwq82-WcoK3K->k)txT?Sa?ja;s1Tu+&`@2MU0i=Z1mm+v*ZEmEy4Ek zT|5yfWMgX9F&G2spWs3-ov1-005Rj`MeDj{i6NP|2FvD3di^Kn*JVh6uHMorX)^4w zxl&1qtUin3tFK);j=pk6NG4uTF;!wY%tNt8Mnz?bKu!Czt>(|uvAqu*4AQanXZ%tv zipoT00`yj``s;4gJ!GZj&BktJ`lN@rCxbc%?E9^3jjlmpm>2}%c^J)~X?FiAP&W=( zKO12V*xXy1LQaz_pmi}`6~RxCt7l06Ek676bJMCF0~Yf&%z4m;9v70QUVEZCt?gl4 zz|Sb&YxG;Yp{kx1sU%RksEv`;STanu9{F&u&BR>Q8R4Re%hf(d^DcOCi8Cy-cBavk z42ugZi3>xmB?-*6(A450>-k~l*)cijVRd$G?iE4AL|C>~h12|K>k;SP^s&qJzUm#Rm_MP?+6kF~@Knss*V~j==u%_t``hfpF=P z)*)=yk(+crG5@s^-&W9N9vtA=*nleSVU2D?x9xXIoH7|U$KS8X{TniE!T zMGTQH$j62)_@@^ZSfaG|f^LX^E;tf$EMZe{yFa`rG*~iLvNLy@HMG zWMn?{FvW4Ss?{u6E?6;Oe92zVOSVE(MvMot(12A`s0>5DDL^@Bu&eE#vizPZ%>-YuVMmT)T0^+_M4LC?*OC0l)N zSg-BpJHqdYs;ODOP`>OL^$c z+B~rrM{))IE zxK!PY(-j&YE!c+h36LSXueV00D`a$phJ+ltSsfMH6e*9T1i-HI$^>I9DSrEG1#$XA zQ7V}dmdKQke2$tm7;Hg=T|h?e2(ofh%1RafQ=lU=VZU40c)akk(x7VS}& zlTqg%9YPfw8QeBv@k1(xwMpp${s&8mS(d!-{{MtRP$BX#;nO`L)d#Tm*#tYZp6`p{ z#&(j3b)bG{p!sg^(+6SP2>Aj-avTByQ9i(hkOzB|K; z70+BoyUpCKD`+k!YJx&fq}vhSRABEHkIdJLD(@R@_2&`!n!?JF0Y!g}>T#P$a3Szt zY_NqA=4UdtdJ@E;b6oxeTrQmypMf2@hG^zpEVHf7}!IW?LmPO1&WT*gZRYul?WHF z@pre+jOB6Oi>TFMbMFWJhaz7zof}P!`LW|43QSm4J!!_7ie9C)brqg|G)3Y902MKD z22#9_SakU&h}GCC*65OK_pdt5Vw>&28I! zdC*#js9og2w!+r8(IL>OU%%Y8s=-Jt8;*_4^x%6?6%Y{T5myOJ0yXsvfdhD_(=!A< z5;^`SF#hI_dpBVkF0U(8`2pyA^n8#givZ4|5)$lAT=(T|3e`FzWdhuPPXX4R@2v0 zC|<@{yqM&Ow7?%xN1nOs$ceYf-g+JT+nX5B|0BkC^|TCL1%Gd5|1hohTXsWWVtx8o ziq>zA_q2*v*~Sx``*D!AOSZdeEZGm3H$d`O1vZY>1Qw3=~U=U3h!5=(P0rX1bqE{@AJ}%^tuB7uat-Q zNu!~Un2zBx41vSk%zbY~IuS_Gx8KSk_?VtkD1`kD9TH^ks@>D&pZS3`S01fDMALWK zqtgtI?6P0%OJKYUNWPhwSz%^NL@7?QpxpS8T*IMdEY&kGntQ&6Zd6C+tOMh=AXsC?rEzRmm22+eSnxL>90j4Qus*Y?u zrtb1`TgvZV@LwkK!T{xy32JiQLw8FODK!Ih@wa-pD;5X;HWhyHjRU1W<9amC9#qX7 z=E>Zm&WTBNXN4=QDTqM(z}))1|NB#Hz-PLEOTjLUi-qEX z>8X9MA368l!n56R^>=fdjpfY|wwf&=QV8M&i=UXe;100>^RkpuK6{(Z%; z$qYUM8SeXUT)yLu- z8PgDQi-*ES~z&bLy}NHE5XP~gOt8Gj zxXBuP+kMNT_vN#}sLoQ9sR%SN%pU0zO&Jb*7k!!0=zYZCX7Tx>de^!BNB8NTooBxv zlp>#H1K?8c<}1|h_9~rab$`a6U?kq>b+%R6De{74Lv0PSIH*4NA(%k``?-+6{qa#| z{p+KA2QkgU;o%nDpn>n*)8yEutVBIq<%+0#=0U7g`sXF2d$tg|#!B77DGvU^oL{ZU zv^s%Wd$~Tujkg0J>@o;|(KQlQE6jirqJ!dEen?NrGTvCN*A^D*DP(kF&^Ac!V^LLeDnpZ=V=2EednjKHECMuN^x7 ziYaUE?yBh_zVs&5oXBTb7t<)Tf->E%B)PhAHWo^kzW9h-Pt0rr=Pa$;Stn5pcN+Dc zfiQ7FILy;(@CF`P&_TXL;{1F4XP@26Ct9J_^{@%xBWE&N*>oel52nJ7^z3pCWzY7i(P9VBKiEIr@d$Q4S3PU}*h28o*n1GBszat2lwhfV@o`l=k0E z4yZQ9Q_;{Ij=XdX$bW;|Te==Q1PS6#H>)x57iA{&B@!xFDRM}l@gDjZSUy(pqT-1V z(6x}wdR+zK5Bd;tK(mhuKrA;}r?gKIHYef9LgTziOb6u-n0RWW;MwZJ9L&%T^!4by zrQcF8Hw+#b4XNkcrnCv^psGC07O&pFs5(ulGr(an-PF`}7W9x`QYD<&2&fuPgBoft z|4j>?CVMA%FIS>w2{t%tlHVrg6%+h~3Tm z=n%f1yLX#9O{>!*RQfyGxW8cMGU@NA`^%=ls8qtz=xwLBeY;<@dfSIzZ6=<2wOMmk zb&`MxLe$C@sYse_;xFs+L)w?O4VQ_8Jqq>-rO1-69byO$8R$>v;K)RB;!B-i5$tWTY({arlT=; zy>|}ZAC$W~TQq;f6pjHkjPcrRJ(hoo-_7xBKM zp_}fqx4 z^6?9P{WoozN%EbzAHLURevL?f?5}pHp>~uGk(18O(2WO zb0>*~NNqc%Y8hxMVnr%%a}OAKd?K0Le}^Z zE^j03+7^M-TGCK>pplO=HS@6h?WCkPi|smWc*6A`wbHrl9_fkMN;qH}s`|qeQZA z5=QoFt4WS}pH5A{{bq393FT&isa_j#N2&LoGrEa4@0Ak3R?NM$Q&KvF!@#O|k!0aG zIJl)O6L;6-sgD9F!_3IUN{cr?jsHI>|8Km#R~F@+(o>1NKmv&6%+25RBmF4W*atmL zgQLl6QUw-{xB4svK=^fNJvLUHT~=leGWe;5q&t$mYJI@2H18FK4%o4)Y+rV5#;)_s z`zW)EKhL>c_6(t>{*&JBd>7sRgDN9JnTB(>MZEfy==2xGs^D}<_7WMUn@?HiK=!o` zi)Mutg00_eg1eVp5vd;7^iG~vb-LfIQZ?4XhFxhrjwp&`LBPXg-VKy%#zM9NlC^18 z4t8q{KdhN$SohI}?b3hM63InyFraHyaL0SCqbCrgz8duG39u=!jPhrlV<$X9e1Y6D zbXF4})r-Y@f~O!}8S=)A;~IbId%E0pf;=*Z=90Ut$vso&thF5C_Yr3M5G};M7~y#uNc{Feeer+a+D?r3LnJ-6&mr0_i2*TlqC(eX zH3@Bc0bf5t&qKIx{rvTNeyIMt0}@T*lHOyS`I`@T~oz}AZBcc*57;hE~Yrwt_uFXYNnFd67&MfC_K&DsTWOn2-+POoFy z#?F}A5I%jk5{cE2^iWwn+eAu612EjR6sF+}QzoJAvSJ|?54j_31SqcV{SSGK@(Tt` znhA;sU5iftP-40E>`4XT1`4rwnKANYDqZ9qjFFs$SA3>gBJAjK@wJiAZE}V_y73&`*wF~-&t|4LzW?8R8h4j~U9Q!B0&U=YlZyrG1yTBO-jew<=?`aDaGgqi{a#C+6woe@| zf6sh+Ijp_anVX44u)!O9VRuDM^9WH`aNeR-JW{cfnV;{J?FF-S!HFyeL`^>^IP$%ix70?%Ivev?r3G_~q-guP#cftbvQ zSugNjoM4hSKQZ0sy&m5Jyukm>f|#Ks2EpgqZw2i1xaSM)LrRP5M^1mu0oC8ULKo-b zdo;#SHb}TYbO!mnNIY~8u}sD#)KX6u{q})r0SDt?g*}2;uPc)23;LX$tPkmDO6(gA zZuQzk-wySH<3OS`C)j{n+FJh0FrN9un8BRWbiR2u;zw?=#OtCAKCki8c1(baf4eTM zuNwkf=6*)Q%zD&7z04zJ|%?7`+=mxQ+cOV;%j76qP%6fFs#Y(IZL*4!Lq;}=iNBAUJ!2?X3u zWbS>+_@VhO{X~_0u)!juv^X6*;*%&@1HYq&m1r0nnIH2~DMoaPW%Yd=?%4qqo?IzMVMvHFbOeAN+Qz&So1wIjmDH*RY{1jN3J7HeyI9p~scG0JQ3 z-$eQ42du`_n-Y3^507aBy0G=MvBn@$uilFOv9P(=SR-fOzd4TTe}SXgP?W1KKLQJZ zEwYwjQ=m>pE6w}yUCgOb*>z&Z8&o;_3DKG>w_C^Mg3`w%<65?p1(HQg+w_KYHk2vn z>72cIz6EmM1oLgEgAJlVAj4FrqQtE8?bG2|o7Da%hwoENlHg5u|4~m* zb+BopgW$F?dFFal(fMb&WL9?CtQLCqugiE$#jgiVDgaQrGS|znCDpgOPxYU=@70?j zbr-mEGH7c>nace$GDxqG&DmKeydbhYn!J}qGuIk6;7U3)W#$dqp&4S zN4lJE*&c4jyEoTLWHLWq4ja#onN{=aE$U&zfWw1O zEiOD+=McGBE?f7S!mio~8{N2FD7(mfMU09)1KfyAwBoYF`orNGt}pSRkXN7?i=J8c z(j}h)^^+GTJ$FBvH!rErpG2xBPKdj&5)=CVR!9TX_QbT(1T49vW93(w60Z~+pHJU& z4*W<+2^xY@+MbCnG0OP}m3!0Bgo0*{%RFcvuW2fU-s`URncUNr#_IHzj%<$jjMqHk!bw7a#+f%l^0sypi&Aqw8}C2L!uA3YL)4;ZB%F4u{t z?7O*UIgAsmr@riW-p9l}@r>k{k3!}CmVVFi>cr?2V|Pli_QZ1*tmtpgk!@P4W=FBJMTdk>1PC46oUz9bOuHOZ1Z!#Qts z(2FhUD4BEyWS%Fq^?rKxe)L?cP7P79hzymk2%td_2lW=wd|NlAP0CJDft3KyePbbt zo+BB+ZnP5?m0rqYIZ%B&G4|wi?x!fJG+sS5k_%B{#y2wLJ|rZE9KrXzEeM2glCdwn zh=+y3U)p&P5+zIhNIc#JAk5VN*xOr&Bf3oS`oxYThnwT6#n8>s*<$2eX>z8@!Sv12Sg3eSbua2W#?(-jh5Q+eb@j+D2FedJu5d(&KtET=idoadPF!I2xAZ6kJ_yL>0Bs=294 zU}_mrgRq48HZcOrbn_=|4CGU#)L|V->VQSc28i>Ws?UAX$J^X{(;;`9Pt_Rrg2`^# z3%t{3xu#BXdoTZj)pC=30>-yI>|m2gQ+KaHqCITo^MyS$hLT%J=Lkf z)MLFLP4K!m-R03d=PXPSGsh)=?D1Q3&ZZuS6-QR8%Lhq)$Kc>VA5pQ1Mpc;pMXjXE zYD0{*H*JXt^lhN)ZOionS>v(eL8D6>6t4r@qb+0U`-9gEQR%}MHsRf)@1;~2la3}3 zAjToy2buvo@jIAWIHG4>{l;EYlovbnj+BYu5)VU z?9&y#b?mZQ7nOxj6`?+bug7SgCj5vny>SIej%P1H!J8ie23 zeOU&c@E!e)wGT`mxWLq`o}_sY>L@7G)UOF=F?ARO`4rNm_r)zV3b|HWD zTt)A==e_L=Gj;BK$BgMeB|~P~-kW_sXR>$JB-dQa^FPU@=x@g!&v7fCxGQk(LEn#@ z6K2@o9OG8>-*$!LUCO68mCkf1n(kOM!KHY-Yr!P9$CF*tr@H2jw|fjPbd1`b>6A6& zmzyi>6SkjED(KN-rC^7_tHOja2IVKlVvNXeD8$8okQaRc{-6!zMNj<<)Xa&~%W2VYf)O$Kadz8Z`YpQ=4zdcQ^tZfnP=7`HxTd%AhR3rpGi#aH}vp2OpjJ zTYLVpm!3hzfNBGR${yN35PFpP}-#CQMICp!BYu;#RE+0(2_*mFl`{=Fq*AjEYHLZjF15#RF zQH};H33cAn6&UWTL?tI|J-vfB67GC%efoogKJVGz#(1bHe&T<4RQ;Dj;XkOsIqx0U zjIrK1?|SA;bQVo=D4gtAGTFI!oNL}Vm-IJ(j-7NOa^cCS|Nho)>DgQV+;weXQ1NT$ zQYVatsV6%Zy>lvS%CWnjo{pHZ=EOhO{5>o zf6zuB?g+y>Z11e8V5V##5A5d1Ad{!xkKZgZa5FJAWmFVN;7TD;69Wq1vXn+!Qur7k zTLNK2kH&KmXc~7!+B8M{1Dq(3xk-XErtO)`<224Z9gd75{EC#p*U+`;ZJ!Z#wU7i4 zI077jmm+{K1)nAATUOTz@$f+jHfPl^Q4LX1LxyS3tOk@VM^~fXK-Vv}Bt&Fp^As%J zFnXhVmkIWvWTB!kD#VOlkqz7%y0P$WKl51&-@Wl;M<#KtkOKYMQ5&EphrWjD1-3kM z{fUe!hjcouJ@J)8$n-Op6 zT}F}r$xfm%NAHifx^eLQ-Tm(23$~w~w%_-yGs$mz75>9B?;oC`H$4iW;J@WsIo_#q zrd`nt`@%OJiYEBizw1@{mi^-?4i9IYjhlVIXUQJh?+={Xar}5;MWIyDKRDcr$Al&j z>n}!#2PZrQ&@?r13uaX)YiinGufb$zGJ@`U?I3OY=@pi|IV=u+f2d&@laS-}lNbg2 zbWu*&e9+s09#+AiVtR*-&w}RX)o;QRHmc9UyGjerR9wogl=Waq77DBBC+c2;P%j%z zd0{ISY+8&r5mI4xXXAnKt1yw?XbZ{u5fB=aWr-t10jS`?0&_I00J4M_28lspFbp%% zlVL$*dN>#o8C}lh=@8=r00^s3u*2Y@Ib?e;3`bi49-kxd*Fylc99qvzBf!4!L4oy9 z;eaifenh*ObUKYzuTkmMAU;$()GufhqSouRsKjVJM(NcgSP5AV(bB3zsBBr4D>$lY z5aQ5W8DbxCo_y~}inakzr7#~JqzTI^Di&BJsiMb}9VIa+4N8nJqD<|0eVR?;BqPd9Qoq{L`iAU6;ynuGQmRi^n-U zoN_i|;x7An+m6rqdb@jg#)YiDIY&d^Id^|@V9i)(OEZr$PI1V6`(W~nUDpn}MI~p} z9PvhlEzk3wE;aWA;v1XP{`HXX=uh|rg@oRX;qwF2~ zj5#i8vrmOi-fA;{!@-oI^0)_gYnp00ds;jDI)FQ7F9+O^Crtgsa)O2vbYZ_WOKZlMeux1Om4$q$U$)XiHNNHN#MKnEVoQ&#Y(P`-C!c0Pxroo>06wv0O zsxZV@HvDJb%P7l=6zOM3Q5AqgTL(pe;GXPr6K;dMss)cW_>&m>pKkm_CAPkQPRxR?4Ijg-Y4hKO7Ku zf5JDrrtk8aeKu*5{o{8X^C$Y$zU^N5-?n-Ga4i5=f~mpU@3>TsajhEXkURF5go%fJ z-}!dSkH>!gVbjjo)Vxdg>!!;gN6*?A@)Dj_Z4 zO48DGCni~+pY51B-X--d_xpeM$au{|^tx;1+m5x3xklUQoxNQ&Sr?o$m!THlBXJ zmh@=p%QH+@AsfZ}qgELtTGERZzO;0tm_&<~qFzUd60T5EqLm0f5A^-Ty^tk{06%-7 z{(z90n_w|O$B;^=RVy@liOSHgBt1%6Oo@(2wFaz}rculFutX{QiE@A_looz0h=%5j z64Al-C?bl)UUh1k0I(tKU$oVu#W*)e40JJsDDvZWU=&lR6ElRFg6_DbkQqC8?K^CW)mY z9ws$1QlTKwYRi?RQbDSbf`YWjXg!ZQTaQsVl&o=o+*rs1tv}E@piGU7v3@{f4UA8l zaw1fIQ)eh@PAXt+L8pe2MO}-HRsvACMyDLsYO1A%?`^Nl{w02jt@=J6!I@;5xQ{_dXjrnBf>=hAUb#pBPVjXQR2($2G=?K={2 z`({jZ<+-BDF1LR8WmGxW|jZP>f+*4Ax@VPQj#AQi|TwY-J0OvR2 zMx()UW4$WUrX*tFtwzxxm2v{72z(=rQbY5w4q|y>5wm$nAbk}pz5QQEhU{HC7q=D@cEQ&UbnXdJo?%#aqWdi-}&D9+V9qv0e8O$xNo6+<9GLK zmw2m-8LPZ+Lv~%uUF{OPFZgzTFa4rBhgGQag_{aGGK_n)(~p`|!PKaH!3E5YjY=39 zQ^}yqfZerPIgE1jnaLFzs^ilj}V(dqg1Li;vvJoY%b6JIewa5 z=6L(uF%J0_$~3zNi;iAcYkzsWLr}7)y1Ko$Zy2^cRM(Um=olqBmYc|>3g{P%XtDnR+a2>MzMN9Mj%9b$g~y!9QK^|Bv0B z@oxElJCuTnS;icR`G41(UbN@b)zn*$vmX?s-z&{8&8w5ovGzqb_y5@CzU?ToF!P8u z&N1_~lQGkN3OW-Mmi0Kdv9!LftjjN4G;59ROlyxfw!6-9Ntx)8_P@@gjrFd5_gukb zhqCEzm1EC5o^AJN-ihcjKb~E=$H_11L3T-9X=RPLuD++EQ!y-sg%-u8I19Z10?>M$ z3J-<$+4c?&;i*9*I~o{g?RRr~(8I5sl zeD9UAG2rfxZqb;7y<(Wu4ahtD`&Duv3P8>GSx*HY6@n(KizX{Bhrz zgP!4ge3Q2O-P;h5vC1#=EARAGL3!T?WPav)`(NiDZMu+!Nm)l#-hZ7>afr^wa_Y?k z1{rMwq0br(19a0r(W$AKS`b>&(Uuk;xL&5{@4$6vW?&Y2F(Gkvs-3}iH~S=Q@}+`> zW7hkotT~^$%J2Ta{O{9G*#C~{tAF@;z@twC(pLsPhJ0}`XNB*B@2=*56`b*jPwLvx zf>q~}cY9ph^^5bKUz{RR(}&QjttB13us4`;iW@&8f7ru%g$WBCbkC-Tlh~kZyl@*C zo5f_|Gw03Mjy(VG>_2lC9J16#=3(T%VAw>>W$9*4(0l>TpcLlAU)e!ScDv^j`IW1l z{|T3yx95L-{){;?+j%~M`OFI=Jb&`}Gv*ZjpdCC#)CKtNX(u46S*=PbSE1(*t>T!X z;V;ibEw@Wu;*vi7Y{~++wCQ%qv)%4ac6&I%J>5c?;`(rgP0|O>_h+6-nRWKo2d)`2 zjz@fWI@~^~w4mG2JgAY#67^e`{(Gpe+q7tSp7m4I8Lmr2wBc3>j9RxjO$;!Zf?A(KB`MI=f3&_5ru@ zE9=@j2PFf{k6ovPrQJkWLfc?isUMb8byBOQU9_wPA{`zW7?w12_h*ZH>_SpExkruL zcPZI}4A!|f%3B@<7kOg<9#)@IM;rvv@&W!}k2tF0C_m*zKD zi%VOy3wQg^bj^9gIe%14J;pKff1ivVf876cP)L4uPH%OCvO`f`rSJ_E&0Y1=q;;qN zYxOU0?7uwAzxZ#b9>B})jbnHIaWHwF&BLjCufO)iPb+ph2gGKIDqBh`>RX!Hd)qsu z{Spn9t41k>SBExEumhI{I?W57hF-1#agw`L?a}1}U)Y2#w@+N^d=HO)v3u4myZdw8 zGB6O#!j}ipCc8bF?ebur^S$|)D8@GBJ-eh8Hj#FTMLC`7iniYF-Y%`IkEr3O28#-s zbx(|}f86(iMj-CgFi1kvDkputchPR|4^BobIFr24A#Lipv}ukxGu=c}ob$2t$#j>z z@%9-Q`(}B0XF1>b);YoNZndag+k&ZE(Z$f)MLqOnXp_))n}RLSG;N6D05YmgU}|*q zOB8A}#f#)bWFT8EWz9Kub;-F{Chwn%Uu2s+&+g7_`}@-!9!+z3ghxh8;g&VtEoZEI z?ilxc$eT_%V?9LwuumK7lJ&Oz!+)N=JGo>^6mjeW!Q?LB=G zxr+9R3mePx$Z%Bo{|`oHwXwNQW|V3^{10YibhmmYhd5-{v-8h~D3|%9xs0Q`C0;|* zU7o*it#%pR_N=FptlGw0d0=3oCaJK#io{d$d{5E-;8 zHT4v#Rg)co=`)T*PPa)Lb1v(RGimQSWxsyv_IRhvckR;OwS8=%jIm9hXqN$b^OuKj z+dKwKzI*calw*-!IL5|T4Au|o`-c@nechCN;ebRH2MpbUX%0gB98o1gu!FZvuY^;L zRxck`3=g8V1RaQFwCh|fCzt`FXIQUP>4yfXeLL|722shhN>$^aVf8Q9=bcQP zYMVXIF6SMGJPT#2?fr#Ef;ZS+vIbMo{NOr-=kmX)?=X>3mWEVH@ zZ1UTi&yQR0ws?=%v5WCHOUlc{<%7MAvi7F_j)AH!vS63rEa!~3obumtv^4XyjE-6V z`{(#^$Af>l7+#Ps>Z_^KcgvK+q^e$XF)GV9Hh1opGt&>8AA2HtwomR<*UT9X52hcF zU2-CF))u#qce(h6Kgup{tgLM4YVDK{N>#%Oom@w08azSY8bJWJ+Gy&>Y4q4)1lOU9 zDOOjrrXLHRa_06po3wY%KE`mc*MClfn*XkCmW3}5i#FCS1Fzgzr<^xVrB1d_pKF^s z@7T4NTIIdU_NJb`VM(7s-Y58hqnDJvHh=Vn*Q!sVl;}xyzhRr*rOB&LE&nBQ_VMW1 zwht$s%lPLn8E>4+f7_+}b^GGK+2p@rU-Xt;j^*W@WOIMkv8Xj3w?ahS)q?~+9s@m{ zv~)_W3j;SWI#n*ZeF6OMXKEEb7fpv$i(aimAzAwq>L&jb`R>uEX=hWW+N99%?41ec z?vFi}{+3-XWUNijc$+MQW6tHiZJYm=ZNXc%MgO!dddI$Gl6%d&_66hY^2fug;q2oX z4ms10MZUNB#1GboF2<%b4JzQ&(b6{n>o;;sKS{yr^d!V7;p`v%$bMh?7S_g45`Seg zbDz1YH=p@^x%$nk%r`Q}#2MVweE7m0R#?fAs^Y>zjARPJAuOE(#`G061uAf5pB1lEBTi$9iEIAzmEpMDt z;s4lCcjdR-%KrP8G&mlQwa*!qjCT>eZJ+y3$D+5~D*owGHpWRb!}h_VQ;`ly#RYA$ zu0eTMXS+d-c7ot-PE}E3M<=QyXwwj5r39lRwa?>(9_vzp4r&Pr%4)UtN=_^r7E4JN zY=&J!Qdq%N!kB8joG=uqhTsy@G(=XNxiRa+&55?i{3w`iitWP%M=r0mySl?RkTLb} zAaopz7#c!O@QlF?L!fCw0#Yk>d&S;(Ebda%lYbr&}mqNcjiCA)RbKGaw!HVk@_x~s8#;i ze&-24o_=kW?cCFe3*EBE+hx7>^W%RwmA&Rv`M>PS-t?$_%b~#X@=nB@GpBBSt;h7jK09v|WbIFv&2PT^H zCz|pejJG`;Yni4=nf}_!?>s&C&2^hHOAnWws;X=0Z0_u7YQYjvZ8Wm!C~v{c;nMvt zi#M2fm!QzcHiq6_mbALMx;m8S(jZS;TU&d3J5f42JBiFEJUu-qp}k~1n9eCWs@nJGEKRoDxY z2g$aTYH4X{Ap%tZ|M>(a3}C*Ri|QFbC)vrL2zUHR5-9`Kx0=XT<&pgbh`f45G(rxk zZncMQus$5Qi8HmvC6v2Imjo<1jIDBjA!mGS-h}v^@wen+^DvzXTwG2fp3$X2@ud$f zwmllT`7cYh>?*B1TYsstva++4gTMO3iZhQ`D;E=e5~-y^EpP!Hwj1m2F8X{`m%X^n z{+6}&zoOPXHvi+F6(3*L&`@M`t||`q`gjH=sT3EjW6*s;2c~or2V2Vf11b2EO)#?e^s<$A1;Q>48_@ z`?Yz~N67~&&bJ>r-+JmoTT?r`li)8VaPal=#Y+thm)aOn}qW6JaoG0y~Mn!PiwxbSr`0b!sM6Z zzdtknsnF$beYPjB^w_cEryFXkuXMEac2Hg+S79t_9gRh)5g0A3`>wXP@e|2nLR`!8 z^!nV#!`4pI>|m9A;?jfO(ZzuYhsG^E>}N#&myD0M+*11qj>(#^q|h(6DCG5{9IZwQ zA>liIzHHwg3@di#AE|0+s;jN)A<9 zTlmiOzbAa(yd9N)T-09X4aP4i^N%YHTEhPHTPQD`YeIA`I}X09`CPZzmUFD8sk5W< z+{vpwY+mmbM;Kf;;S(ZNZg>d)*d|?IboRvfJa!IF!02L0+CwqB{AaBk z|3ciW2_NpW79FfSfAGvX?qI`KzoV=3GPdh-Y$toS@GCQ4q8R^Pj}+!=Qv$*yG)quG z_+Pwuv8k!4v9a-j@-z?f5Qm2!i7!!uZ-Etw-9Vd!FjeN?DK4m#%alnLk2+Kk!-ao* zfG|1g;7!?wLk0;FQ^F-|ppLz{MsF7sbu>Xzu45=#{@h|Fr|VRp;-&0mg<8-UY~OM%B9|x z3!DzhS(dAcYJL>GC1lPT)%|LV0KgU@JEp(apyY$R z%I`<6`?ewJTk)CSkJR@dr3-K2_W#eb3DF=6S^!9Xs@7105>{FNK zy_-1pSFhgpg89*xV}CPi$+~T}qT(|rj-IQjsqX4#0iWG7;@}Xry&P(>Kl0MskC}H( zjmsP#YaJ%>L}SKsLRjX5Ge6V6pICP2XifduOP!4j8lb+bv;A@h7RC1CRjmmd^L&5$ z%6-opr~fsK_4rTrX4?)NJ6n0~%<+TWj7;e0t!&>BHNv;ZT(N+P6SEe|S(H7jS%}JF zqT{69{xjpJ-!|=>WJsR8yexRxVXv4n1b$F_d9b;F*%jd6R@zT?urXzFg4M^AJN}KM z9xEEcqvE>)Wqh!~BwU9|%?24$Vgn!twn3BDE^O5!A?Yr21em zBq16gzUkwL6cVqACXY#K}J5mDH8~Ufy9S~p_9Gouh6d!2~^@qlT2m4WIb5EGQNzgVs}GB1Acx2 z?!OeQVFhuB3HM|=ywzmYdHT4%7u?Um;f&u{o2vA1p(xTl!o7ft|=GjYZP^IS|?XgGgEPG791q-D| z-z>U6Cgln3`e)zWv9avj!Iqx$-F=OmA;(T_5cgDMmEQ_fzeoLWy?atj zHdEFCiz|GU_QSA&{c#hcbD7f^X5%3m69|(G`|e+yJ}x#FyZ3;l2ib(qk+2gNe)d0+ zD_`H9bKu;CX66_<-2IBMJEsAEwMc!v<5A*^ombB^b(hz6Y_J?(n_uf6)9 zH(`avs(Rq!QlBLUz2hqwq71*hL=JrYluvZQV+ol*G<>omqqL&Brn>%oLt~AwyuA8_ z38m;27|{t633|zJAEF{qPWITJUb^*h?dB;lxf9@5pbMuZ?RzYoZYYU4$Vs2GfijujoJXAaiQV*Bve|0>G(GrZ1!+-)vq=17^ka?uI zMn3b%@WI|PzT;aWIBy_>&n1w3DLxLL1ver!i9@hNs~g|Y27cAo*Ygvo1TvC>n#hg$ z5(iY0TCHQLB~NaA%K{FO;Eh?RAyAI?Du)D)l;2nvH|7g(WgrEV@ns6KD*1_Isba90 z>b@y?Ns;jV039Kvr+-+!>jw)zd^7!2$tC-_PGMsvW(g3gt#x+HpRV;> z>gcX)znXKlRkLQ#pSAC9D>##ud-!nK$+P7L+p5orO*DNS4Cr75Yu)Tit!TAB^wL`o z>ysv$(?en`w}jLouO@%<<&Ci`_LUqycDnA&h2ADqs*7UI8tc0bdq-P+Rc&31{oM^I zPt7wXDGE`=iK9o39jrWa*xuXByhL|9tD5~=lK=)Ryg_QEny|NLi9wuQ$Db?&unG4) zTf=|H?j9ey4Ff_ybAhL+&_BM+FWMGlwoFg31sgKCf-@kdgjLRQrhZ3*38a}RElLd} z0@21sgVf2>W73#t9UZYh_^rbpG1jr>466RI1uI{DbNf!~@#^O8md?J;URsH0%wH)| zlX!cFDD0&UF`o-78m`!FXIgA^S6+I3>*KGzF?H5QkHw}if$Xl&^GrD8_xj0z=u)*) z^miFE#s8wq;8!?M8fY%}jV_TZ}{qgFWHsyA3wxV4x zBlAw2kV3!cpGJl@2veQXr6o&vi-!mheEOD~d|ZD8vZ7mc5$yzvCn2GkAokmk5goU{d8g zQW_D>GxY4YBRWgJ#0#0MOoTT-fd#fRc(JJIN^Wl8+<(j(Iuy`GkiMBJ-6bl6u5X zhzutX@>E6*AVyW^DLIH4%vHp?H8J^)?Bmye}+|$ z#%~RdP4x=jc5CBv6sY zMMR@hPcT_0m~+O)SV_%uae;Td4gWMl=JyP#Kb-y9)`HIMndfW=&bKnn+uerTp~+&H zgjnglghtGstadxrs@E=aToUIqyl*|NO*=b&-sN@UZ!f3 ze!e{A&75iupt#V6@yC_!*7mk8`;k`rk3&D48v6PDODs?e0mF1tOsNmeUGd!Vtv>Zm_DwM6a^o{=@%{!T3A688o-@&uG%@`1A0_ND z??01Q$4MRb_KO&ywcA_H+j|i`6bD^c{?1i@DRdq+soIA~GL~S)gNM?P+Sz8>&#n|$ykg&{V&{}xo_*0R? z45E<3!s`0`HTyBU{o7%md^0-rK3ats(FwE_F18>rhE`$qi?ezywt1tSnK_EBV2a*0 z(MY(>H(oRkJp4%@KM{dw1X2WSmMD&QywyFy>Y0!i5SKMEIvESD@6TVmKBuAl?3MG4 zR~gcOZ zaEq((T5>cnjyW6~L&TuCqTu*q9R6UFg-#(IeFp@DOTIA&ykpCK6AFA{v!*Pw1x9TD z{*ts8*A#@U&bC$dR9(D=FzC3%OcBt0mF<)?67f(I%1B%GWx5ZQOEqC6-pl?qPA9m^ z?gPx2?5%VPyM05A{kzL8K@mxhyjdD(%=OggF!kY~%ZB+vO^(hR7o9^N!2{2EkB`op zV9sJDhxsum$3D>CB=8#So?^^=)VMp~nV4_BV0_|Fue|x$wlrJOvD4>j>+9M(JFp^? z@>UVcDmvfs>X2Nx&9`hJ5*=vgXjlm0n?C&@aUJrc+#cesCL-fV;NY!>5AXm7pb~4K zkf9bvVV$t}l8+ibv`0-rZTuuYAUnrDRqz6FfG3$aIr2Gg`6p?jgbqQ!V}g!;iPS13 zH>G?)>Bx&Q1278fB--L}Ow-XX>%}nyzx+`BR#t(GBmHWEYPABjFkh0VQcI1%IGuc=5_jM)jXP!M!+11(2nIuC0J=Si2G9mGSuniM6yCGGg*l^xcOv(4neCzq; z8=p75zukK5NL}}t7W;u_`|JCve;SiMB|ObzQI?+x!=VEK(bhmi+PJt3m#E#rOLHeK z&Yl>x<9`d}|)C-PG!EU^}!QR)5T^x(()jfSRz4q#cjtlh{FJ7o^ZK|a! zbYAX2(n(5trVT;PG z-Lyy{JC&o}`g%}En>xChE;ctb)?RFGY;6&%OGqub-;JuE_aZ(V-~6cv6jDL`Zv!Bz z?Dmh#+8$c8{sBYASWOm6v7CFMB?!j=FAj{hxh)ZGfPvpMy=}Sn;ZFkj zi3mia!HCsupdp5Dt?o-uRC9b6XN`+Vf6$Qf@SODvR~Ba+xpK1hN;_jZ&YZ@CK+J;o zKT_IU|LczYPkCVjPH3{2c8JknS0DT6Yc6(Y9;p7=thkUr>mP{P%ES?K^-hNTv9Y$` zm>h;!{xKA=Knz+i-!cKySrf(VF}oLY7~jGo@7M!gaizYox!&fK;Kdf#(4CV_ng6}a z@-yT1*LNSUsP1d0J%iL7?|GHo1kCg+8_1!B60;LZS%6R{J(N?o`K#kfZwu!O(Z~7Y z$YuNgt~lTxnd+k#E7WYF_ts@%P7o9;`tpsA?mQ0t+9*_PWe{EfOas>F*OSb-(=@yM zpIyo+c5fu+tlYda*OGJQX@5s5;7%n1VLWPTAe2P`P7BVzaQw3_# z@KbQ$5}0Pp05^u_n3|(nHBdOAY(A3mLHNVNKLJ&D6jJE z&Uz5SQUYIUzlN%HuGjweH+SD3wk|}!Gax3L2{C^RcTL5?#=;;|et?iRI06fK2Sn!w znytzdnI+hqi<5o=`AJ5jQ!{}^IN$olTD(xH;;e|Q5R+wcRN8k9Y2TZ-{x=I&q#kTM zSaqScsUEvAF6$Byz_h3*9I)7=}#JTt>=0_N6}zKT{q^J=T=s zACuu_ObLq4oE(!mEpq1%jXUCZ9m9D0!X+$sxqS#DH*P6H%wBE9EEY-HgXrbpnGRv! zd!+-*Gi2P2NX@a~AT`s-Vn{G-`l%G}g}VnJbr*TSVHK&BJ#Ea;_i~DJFH)i#sYPd( zJ%|>fI_gC>7&SymrK=aU+-^VKYyaDO$qz?v!C>BBo5k>n%RXp7qP0X9Dow)b6Ki#2 zi#JAAChKIKa3RKgnwdwuaCrDrh7*Bk9`RNtOoBz*v--qYJmYb>K5@CQ_koz~2N!Mo zap;B()}}+}`&v7%^|Xtv0m??h{$4^626VlDy8AGA0v8pezMd9WJ)^P0((-f71@%`$ z{;)9k#kcM=rGSH6yaN0MM(6sQExu-}w>cl@XR@Nqf_>vnnK(Rj5LkrioforJae2Px z)N#xnMD7D38IVkU?c-;b?%GyVbH3Hy*51>@kPnEFC__zLA2?7u&>$y0gkKnkVj$Gf z)^Ulzx?cOy7Q10vMeu^no|<%a8 zDMR8ZbJjiZ^3rGH)}|e-Ovt5fWLCpfnSWD{8cp@wn1cEf9t6IeR3|mi0UhnO`F3ZK8kmM2Sw@QBNb_*~ zLm)K;ROJjU1F(~@sOCbZWHB_~B-7v?kBl#=a!iD98G*>MAdZyF^ksYo365+B_Xk62 znU_o%q;_ocUr{S(W{i%+Ed#*ij+56Oo4dO@_nXw?xu zz^Ok;kN6c+D+T3!W34z65n>@S<-1F*4=woYdvo4jyfHiXaOJ7W^T-{=j#n`|;nb_{ ztDGAQOuv&`_n2;TKzQPmH?gP93wgcFJt~c*;Xq9)rfz-)i>J|wvL6_iA7n_I8n*dc z3qO8&dE#do$B#DKE1K-N7wtcd*)cV8>v&`GEg?1F_*lf}?7;d{%=(QL&AX4a#U~a$ zy(IDeSs&i7W6xJXaQp$UmZL z`lw;&w3r;`ewpR)5i`0>cL*i3dmI7(4{&}6|f9ijQ zMPKM*A}xhQ7n)i*SU|rnmyiOdu4kAsljLuqi|j(o4=WbdjZxV z=6KZn}jK*bgm}%&wc6+R5gawJ)ppEst@G6tSH(~jc5lo=La_Q)+3pxq4aDOZKETg7jRG=8f*8q9 zYGE*>mPC>u9^$B&NTTLZb7>nk3mEhOlrPn{H>FWFnvv6nNSc;w%Zf-oqQzh^KqJeUglh{We2{Y%NwE3L;sq#ywpE3ImDD3 zV950`S$tv(ebKMYc@y>fAJK06*6a`d62Ez!rEXBbu}rY+p~i}>Ateq-;l?CP+M1wYfTePsTMXqnk&8d$rToaj}~rfY;SWB`T`YQiZ) z2nU!Glf6omfp127m^oE;+ZU|d_t?T!_v?2B>Qb;9^o%L;h$+S*QOtFiF( z&i6!auuOVB;Za@Um={-K^hlFq#0%N(=0Z1P5oeb%fKeEd!{`n-)+G8D5#SZJm%hxL zoAZ2)xy<=9D>8P`_6H+3e=l@JLSla5xr^tUJH*+!R2)a*iRzP8Bdbk$i;#X3YpRt& z)Q<9+Uu!=6!}6quHJh1lX9t#-CeuAaET-e&q!qO0Ah(D4 zrz4s;`c>?Z9u+JGOBPCaR7k=jLmahE*`B{B#vr~sg4FO0%mS(;<&Z5)HyHhcg%5_* zDv=aIYSW}3fsePEon(j%xoH+q$Rl~Ba!>tShRZnMDbGz4A&{6Dz|$D;FgTGy0}r1N zBEOOxkhu&%YMRp^wQ+}n=~kQ}b6K2r^2CC-r)akM>(YF*wm?%!prJ6(i1}`&Z!{L* z+1}u_vC!X8=x@wpD9)StUSE@#&GR-FdYKD(D=r_skBKrF&Cis}hd4fAWIom)-oA|C zSwCH3bu;Y`Ht&4c`1wOKVs}+sIC`d~@jQE=x-PfWa%w0dkxK+V$v*R)xgQ12TpJXf zJ;r1k8CNvU^=c9&Thr{JrA+tXI*1Y#tThHw(Ji&q{ z#~uh}76lLmx?lA7>(t6s!~!=JU=(?Fw&)M?ahasVB``X;{5W zu2X-3)Cg3$POZ#-_vfgre2T2UctpJG4kA^*^awgxq%Nty`iqEO$Q7PV{J>=1rg7xA})#Jnrup!^yP~>YYVZ;8ISmE&SCvA+Mh(I*=*j$g8TrZ(! zQe}KX3lyIK8LoP!ZEaJGNslc2=#4$a`G?M3Y3b;#IgfmCRO^N*+`cI8m-+guO9G>) zAGBK3Tge$a6V26K_N2p&e=vP=?~h)&KXm=L@ErmAbOv?IEx4PCT}>tK6f?GzzC$CV zHHrpl5(T6y(Tp)RLye`d{bLgBGYuINwMi3az5mqfiCfF6PhaY5$993U+F^Mk2>TKK`vEZc!2MJ0t*Rp&5rxYT`_GXjNegYtYCBmYIeOOdN) z#-CIfEd=qa3SQ|44u+Wh=2sp^IWIq#K!4*~jVV7=fm;n9;E{=wCd5d3BqD%xj{4e7 z2Oetaq(=oo(KwZ72!w(RnGpmyT9kpF{0Z5TClU>1%mI`S{pVmvtwI~r%8cNlB*u{m zgg_W%44sRN=E!R4=dFH7vg)G-svlB7N(v3~6DAXADonWyhSV~e%*By!1M1?A{Yme> zEbL|zk2X)9|Grz;PXDC`$7oCajE4er#esSdFwHAE)iXN7)12$8FD4KLmcz>Y07ql4 zkI}|do~Nk*Wr6)Tc=!{&kEviHh-k(fKE&Y()aL~2#G6wr++uRwUoRNFIL$q7*TmRu zkA{A*Y-j1gv%PiITr=Hc@8Tq9w)NRhT)46#`AF~|4flm^^w;bgt<7*>R^j#b3Fm~e zd$c*A0OmSD`Yga25$9&gcQWTYM;CaBgUU0fa7y{2E#EWl`C(l0{EW6Ae^?e|NcJ(L zKnau&(;+iM!uJ0By|Q1tSN!w$tkWYlOw(?e9KCx&LM8@s?u$#@6ApSUIqVZx;cF-e z)MSs<=5fC>40O|#1SK3E#|EXy;|Mp#qJmWqMadmRUPg6epsop z@m7>^uFXn1bm{wxKK!O}`*_nnY@%GE^PFP~#>5o3MbknA!8Ds7orM;~#E581l)}Ki zwn8ssG3Vioi7v$p-6)Ns}g5{d(isnd)*zZtb|S?bZUrfc==6r>i}+M^&f)u7ZDi`U8ycShcQ_{BLe zwSD%oZu|2e=X^VUA64U_*(=7(F}87wF+?vEio8MaR*bp_YgGDvr1mftdFu;;by?%* zZJ791^M5@vcY8|4p^CzzWqB7HD%;rJa9JD=D2P#>+hy=q`<;Yon2x?$a!Vn=} ziquj*^OY*|6UDj#6aSDgigmOAdjE!>^h*@m$ZE0-lL`z?kG2vC}&?=NnNepuoNQ zJl~}U#zbWW=raLp(nO(ljwyDED*>$C7$j)ZIbkeh(T?#86CYoi_weflV;G0TX8Ya> zQd5M9`m6`cIg_IHKCvu!qG8uK!!FOL9iHY?m*|`k(bkdCg(!orhC+`hbVlpcgoCcy zQg`EFPkotZRL)p!+7#XH$@4xA{)_QP^A@L_zLpHKtZ1YumpXEewYf!G{t>C6 zKbH_nA%=NIMt8+H^fkp5gVY4_6A_3;<8h4ztg~orfqF}@rZ7lT>Z3p4W;!r3res8P zo{N6h_^9=Nej_paM9b;pb?xUHx#|lYM1^LF8tR`zi@4$Z>WI_|K2lWzsl`1STu;eT z0^122JFLg+e>p?@_}@(vUU_fq!p*_D6sEXAXPOFN?GaNBYSUQ+N-AJYvxGBrld)Qw zO`fmb%Ca@4@xbwE4ZZ;6V+wymdA|P1eN7J(FI2f8y`wzVrEx)UJDYu{6;q3LH^&E z_$`G1b2JZTwSZ9x5TLUJP$}f40Kf6AigfvtD)1HLyvYl7j7Jsq#FtY2#*}4ndm@DE1+VBtd`HKmXf?0hTB%UflX8X`GA zSo(mnq?3%qWTkS)K}hd@5zTl^%hmRf!&Dda7y zjCAfSQmfS`H4eBWLa;))Vn5kp|B-&}Sbd`V^75}oA99L5?W#NKt1Su8Aw5v2_q#=> zdzkWkbS3@->McH+3`|g%I-|?GM5beq?4`Fbo5%XByEcnaItyXgtN7{I!IbM}7V^PY zkNn9AM(fmNdm8hcV)OoUiRBwhbMMk@8~0YG|J;=izxK{1>qYCKOHG%$db-+m!BU%Jeqo5P6tRkgdxO7Kx;beK!UKT8gJR-8DLURCLbB z7~AOBVw5`%BjwEpN&@vo!1NexMR4rFF|Tdqw$LfBz7z1fc|UkXyEXq%YU!c!6Q^ow z8@kxq%2H#ma^u1fIyGp{YS9&8QFhfzvb*V_>APoNj#Fn1&KuBx^3_XBQ)mB1xyRo34CXZZb^szXWCC63Hx-aaj#p% zURQITQ%pY2Ioe9qdzx}+64XV2E|1$Q*lX{u&k^t)Q#dj-b!%r_nOgEbfA6V*+&qqVyZ zHlTibJiC0lc2{uJelcEMa$s~6BakwV9KpJbI-+PkhHRX-k+&#jfYwTLqEWe+i=3i` zbHVi8oHaIb$HP&d&-v8C{`wLj4K>%vU!-SH*G>p*GMOS6+&rf`dp)=)IvXgOC z4`cv3gOyjplPo5sBQliZk?_Q?Jd#>McoZo6VqKUIWy-|4=>ve0`;F|POA-zs$^!B& z9?~Z@H623aLm)9FhQdH1;Fn{7FJ;Jp2ois(Us<};DIVs2qz1k@ zuMDFpkeX>U;FygbC<_9+Bhy%e=1;EN!j6=m7>xsq$ZAktB6W~9o2w5cQh#Hy^=pfB zz8;(I9-lH!v+bb;pUhiTlyR*0C>ApuFs6V74HNUH+BW;84%r=+< zzNknICDaAZM{jl0WYQ%3;tO50=@XZfdM-?!Xy%}g3}ux+3#$fxbvNd+af!-uWdhvX z4`E|9`2m_D<|{zzd!kG3jm>v5W%%in?hjk@^1FL84z?7OSJ%|{pA$$ArG+!h#xood zH=suk{ih>X|07a^lHFXiijn`Bx|Xu@-OKhLzW`aGePe=YP*5!W}KA-UE+P%3&Wu?_8%ljHn**oj(+*H%o&18aXIYYDV|F2&G z3z`9lDFyybWv>*xDpIH*#V34-kS7Hi)o_ZS0;P;BgspN37fGpjB-1BTDf5RWNz(A8 zxvTlAo}rOiq8cD z=gX`e!*5L{=fr~>SH5O&))Do$O zOSw`;*nS&2_05r5P$+sa#6mu2(J-($(_t^WYX7l$+d~nXL&6ii!*>TK6fwEsWU#uJ zY@CWIxNXSxGGr-l!Fkr8-8DI4iYCtD7L^>JO?IF0dC=U%;5mr_^AgAEQ~k`@F8Xwk znwI9N%Y)(68qLX1o9nN!Fc$LA7mhI&k1!XxB$PTceA4cluGz}vq-$)A>(h^(JTJN! zeMfdo2$r5Z_eO&jBN^m1jKYaWR-e$RL2BTVc{dih`s&*4w%Wc|-{0l-i@D#{aX$7o z|ELrUw45SyTp8dQY%FJZ7$tvTk>C=|m3d~`t%t!z17;jJ##D$K&6GH&dTNr#&0hEP zyJ;H_wkIEMKG}4ouC0g52GB2<4!PRH?XhCEhD*)3iB+?uV*1>*L5sGHi?Mh_7mhL& zIkC`S5HnymI#}%(=xwm#7+*~^UsfL5&C$ z0mP&%d_wwUchd)I0UaKGmDJ)V3rT>QG=GvN1jrDTJV^tY%ISAFKz5F)-N=DqhCmp^ zlPNipJ`Wz5FM;xLB;!UuaU^+P1yWOMYC$0N!e#p>2RkOsS$&^rzn?bQ&5-BHmKk%I zlOC9}flc0M&BA4iUaZTp9LF(llkc4M{_{Tfp1py!R06%D(uv>- z?(2}%LM$kFmn{(-A?#wZj568oFI-t#g*Epf- z8j$LOW`2SU^2JGd9EH-C_?1~f<#ST7fIc`psJFlnhcS9;v%R$JNX1#bG`Umai#P^+ z+)M9IeoFg)3*%RA+)-X$e)dR3TU}*WW8LMp7EZ|)7>%?Cu33Me{R;ObNIm_frD&{7 z>3<2e|0skNq~3X}v)})S)XD;=0@GZ)DD@^_8cmgD(4^ApH7Bl2n7?MaK51;kZeMLC zyV}tf#RM2l z5mhXx4gL;zL`{hS7XO3P>b!^;a>)sBcHV*1*mU)B;HSN{TO2uJsp|NH_QSD%(ge?3 z863HbUchZNltMUVFaubN!LTwOCXhx;sbxju0n>#cL`H#AwB-hCkIB@e4`4yHDm$U%d@X=xQH;OW@S+<2`LTd%a9t2vS}|a0Sd){;a2Epox*L- z9YShR6aDbi&}~O$<<{?+uWxvARqh1s))3=f&+xq*-{Bkq#|mAdtgv0F_be|Rm7eKh z%p7CPp;7VEn8;k}hz$iyT>H;m{mn(|f1ywON#v$+e|vLM)TThwo{uRaF(8j^+))w0TD< zF+>+0)=#2AQh8snLV`8H%2-RD&e|*HgMe$6IC||ZoxROh>;<(w-+uDWw<+W=V(=~MV0n=%<_TMhs$wBvl;d|JA`(U1ZtERQvTAZ<;kT@Yih^hQ-W(RU`y5 zN*w4wt5DTgN0IC3M?@o^iHRHr8e}WFDWx!+=cYf&Kz^l*o2#51G%~#D-rsJ6Pt@>q+s9(vE12m|)D?AWLEs4Q%(}zz8=c_x8 z)au}nij#B}*Y)_mwvvOm{UcHXLibJ3WxCAW?rq8(W6E?gW-_(tq0RM)viL??e4=vk zkI`G4jVzg2IN8H1Vjst7PYm7Y`Rvl~n6~`(-E99C-wIiUt1lP9X{8ylM2 zI>o#msx<<)ySw8O;C7_4y0o_K^WwVu{u<}^$K{je?g|XEdPNp{0S%g5vT)O9C@zyr z2bh%h&{%OOaYB#N=ep{%kw3TMvY}ZaJDUNFLN*x*ZUkU<9-fX1jLH;8ujs9=+C2Br z-5!67pY&|x4`%A#*`CTR&u31ZZLMvvV{U_GH_9}nL6uf^_i)XEIQo+IE8L(uHG5|z zQU`|b65{<<==aoS-Ud=51^NY$_)pQP#jrvsk^mFhbYq`5_Nw4q+Ye{O2G9OrLhOET z4Yp({%vayLAj4Z<;u)1sjld-zO{S+-)QGb&W28BIl+og%DWK|UTCT=@zM9QGGv5BC zY0HeaQgM_25;t+tnjq7Tk&!zw8W(UMMa_z&s9ZNaSfA!BoM=TZnryd-9M7;^j=J?& zu%Fv5M!vFs%G{6M-I9Fj)G4|T9T4j2-~&X8+Cy*4qi{o1R{x-djs#Eo3LFp*o3xa}eB@vMK5s^As-B4KrET!sRQ3`G z7)js&P=FO#3W-5?yhNn04j~4kM~)f54kCcm{7G3<0e&M%Dv+rj+W&BndH?|uq$G?= zc7aDwD_NnwRRYwI0Unisc=$=y1;Y=ChU%N#m1+?$_%F*VX&_(vvSYGprnl!IDLBtt zelAI(x~Y0e!vF#Xa7O*}t3zs4WJ$>8y{-6+^XyNV@%9SOn5xU29KJUsVwZn(imN$g zq%nQ8fvp@CpKzOBxWy+T54&zBeU7ua* z(q}=7ES?c1o{=_oMRA6whc?win=Ia%3=cx0@+bn?;aqe%I4OdL{mx>|)Y*{gtj|!s z%~Oh#=O3OE6rLFrmWmr2m5#|7Ly-}o>7!?DaQnmj|DL7&{k*7^iM#VlDvlpLb>`^V z<{Bow6-|rd%oQQ8$Z>Hpvn<`vNL|)wpZY=qNR1#JHszwEFyRg&H42oR^aiH62y;() z&39gn^?da`-{^f~n8!Bdpin!9=6PZC6;VKg@r%gviOk@XX?Qr=n0~i8>mC#Ps!BW! zB_Q>vsO?^%>pY%~{p*sQ(VrG9*Gv@KL-wifw8LdfjkFh#OSiLpnKH(%~p(<%V zqm8K}P03EiWD=xBaS4cTSYAM+4J$0B$6d5(!3)-fzP0Aip+odII{58%jwj$W!ci9*fkXUYw#;^-Sud@=LS(Sl+s-M9ti=e z$Q|H8Vh_-!#V}QQ{`qpL06|hD3vD3p00JEU9DrQ12*Ao2TVKWEaf2J)K&CHNh1{eh3BqS&T< zLuYjf%bFHj>Y*xDGrP&8x@s#SNQIbn4N!${a{~V`SI$ev$b49&uCB(-`$51*0r`S7Om}P>)Os; zvTw^d{mAd;P5n#4#6|m%V+u@Xk&C-F0}%&0h_&*_4DZM+ej+<&?74&&=d2TujVv1G z+sVKHBSS&zEKH$1Bl83Xh35rCB9XNOtWv7>0MU{i2*gOqPUsu7X8m?%(enuHhU9tV<{$V1>;fdID%{6D2?Ilh2 zDK94Yg(snfLG~~ymq^Vd$v9<~Rza!QrPZVC(h|ay1|g>_m6K1di&ua~{KTKoz?)dg zWW8ueR0KsqEF+)UIQCB3u}Lo{jMZ%$qus;4xv@)2@0p*9xtB*|fm@j1l22q7{1=b} z$Qpp@oDs~#GV`Ff(vV!jcZP(0HsLw5?&G~%(hqJ(Iq=PABF4Y`<~ZFBXUxoEi$;gD zEK=YdVe^c%z|KGcm-~fn`kn5>w34Hh z^%pNRHi&KDte;X)WppHa!S${|;V6_S*R4EX=+vS^DO~!3Q6wZ5Hu@75%N%6c*LJnL zk=v{eRW*N_aeUJ6BZL0>y3=3Y^^e-kkkXkki~;84IO#S zUj)sVadOGMq4{GB70$X+_F~^Xdk1$(a~XQrdppw$j&pfOWrw}=!j+BX7gkiXOr5tP zaM30oZ3;_EELZu*RyZxp7(H`0$FwrSQGhtlg|VyFLZ;HW>a1eQNS8||QbxIH?B)m# z+v)y$-JfIDZ7(>MVJ&E?K2d)p-`-JU@3};OWT45I4aW#Uv=gCI|2rZz5QEG|Aw{$z zR3%ajKnL|tViHG%B#A`4330>=De8wnC^i0o)+G}WE#>-&rXaPH`6>+qJp3vj8IGT^ z#DHYgKS@^lRS!81ty7aMX-aI8eyLr`Ktcd7ejSb?uacp9R8A6tpQ(G2RYyv|oO~Q< zATJ)mB~pW-YHE%i%B3KhW7wDbRkje76nNw}co-6>v_SxVXn?T69wP7)ac%>trSw2N zC}tk$YmE0%=7gCpQbjyHNZF3|-cJ5YyI{XR^kdF`9Idy|Z3PTP^~+VHBI+~JgK)sw zK_?XkX8$oK$t9)&3E;D6*Myhe_~Qcew*4u4vn{$0HwFJ~iRavHK}(Og8q1s(C1a67 zvQnQ#_~3+A4pz!!Nm+6HNgzLYYj=-(?e!%o6_(ST>Cr2a!*)>XKaOk{DIL6(vWXLABjlyiA+Z{ zApq|(mw(+c2uWShNu%dmgrhS!ZQrP zvbrCs#ay%EFyE?ZwNIY0+$$^zYjeRyU`|oQzVr=5j+(n|>?#M3Rw{~zO zoiN}QPC3j(3tKNThe3OQqRDXzLy_TYQY+2Q@Cgr^Owb|h!y6`CP9Ehv>#DlqVYIM^|ODt(w`l_$_U=s{kyM*+3*9M3e}3y=!pED>%crN#Zqy9RBkKzV~xc;ZXngY7l=bHOod+u2Cx=*rVK1}uh*61bezcX)D=sIgon?1ALzNOawc=#s&mp^{M zm==Jo2*V_0PKo7y4SixpaGDQ>n1WY3AjULe2c%S(4eLd0y376;H8oZF)DdC z^{7NrSVuHe%dUFJ@k^2V#w=8<~f z>LOdlx#JZ{Sq0Poo-q3Pb$89&^Ph`yJtNZmwCTv1VJ1#AX05#!toh>yDSM9fWER!b zRf|IkyRWeMgfp_QUFy9oBmp-OH#05XSJQNURm%SHf1U62SMvlzqU)mVK}*WNHaG3- zv(v>Evj`!|1X4$(LNdJMc;E|ICVAu`@F}zqF*J%(j zO@Jcy+c*%i%|2CytixFFO9j+)q4T+3gxx zIwHb0GJJvdTjA640Zv+{7@ zoNePZsV=jV_!UhYbY@Zuq`vONI)WVhpudCEBlM;B=*xNEH8<14T;jA~Kka$4Zg0@s zPrmVM!-Frzy}KbPKR>^^x*G9?M4~;T_l2)DR`$^K-d;cxtz4Q!*pY`*-nf0 zVu8kt*4#-ga^8k*eu0 z=|=u~{yl$=A2aK7jzaE;atx3H4zF`8V? zEOm{_aEVNHiA))zNgJaTsf~!pbd5@5R$=s0Z+QMX@|O$WjbFPrul&r(Gu7B0GcaR# zCSiJr7Cs!LZoS-()b3$BL2AtM$$glPqeVviBU1OZab(btNDYVC8>b-I7drKotCzVC zfy09v(gWJQcGAf$W zMJCPq_@j(tg-6e}U#z!ZZRf~4@R$?Ful{> zUMsF=NjcQ~t$9oD`tAI&(c1#w$h~Xsj&Cf=atbf=GoN&dDju!1vPPirGgCG;8to{Z zb(A(A=cLKU){eIA9iAN+w*NlOF7FrK`>%xb8T&7}zPyHk%H&wf=()Q*BD3Atd?DGc zv5rw3e=63S>5MkXVzf4YgtizrN?SN8GA|^d)P4TWfccxbP{#k+gh_voU$izg*;bB) zo>Vra)cuzU&s(Y&wU;@1=zuB;50I_{!ub>7%mbjP1(ecTP4JfJ8GdB4;{gzPAVZ~d zXb+@H0Oeap3RS=AA;N7SH5dc|4~I_T+%cra#zX9z5UK=n0-@B?+uqXK#XZo=G7bmLd^g0f-%TSV?JymZmZ@)! z4t5UR|MkDE;xL5g64qxGl^s7++E{z8rllihOMc+r-ni>`Z@J9hD=tn#hq@J{23h=c zyT$p&YiyD4?6#Ix)-|*;>DqaP1yZha?iMAXK%G~5+dG-VKi}Pcysi5a>!BxJ(oT9l z`tIKvJm+k@_qD{aiw_{s5JXNwK!F#+w%j8sg`1-(!Y~UHO4^&xR#u%l zT-Ulfzs38>cl{S6qxy~3r`@C3uatMV?NcB%$JoBS;??)}WF94(k z-5%`&q(;5&;y5_jDQ;RdcO;OpF}x!qZX@S)t+l7Uv5QlE4%A)#w7l-V*-P*GU8M7z zwc^IQnBq~3Y@;JfM=7`|nl9VWl#!3pVzU8ju`x|!#evieL_H$%eA#-iaO>o#MBjNE zrpKf?zqWz<+1PN%WqzK4``V zZodr=_}%>3EB9qxaDb2ZIB`9bpka1w=}# zpF^0^cfU|q?>MQB2|_B^q+;2ZB88lxWe!|bT1gG!Rr*yArMNw$h8P&ax3bBeq zztQ;2-!f{^-g~vSZ|I6~_vmcSnk>)AeF5P+gi%&h+VJT?oA!%L_l-z%3s1*CTAw%4 zki$JD&XLS!V^t0x zsVBU&6r^@CSVn2HMr(%am;rD^>c*;SkeY$2z+dtfgC3m2>^Dd)Xc9E?QdCYNVEM-N z6Wnojxw-Y~*>3y)n$}MaT_2#`&swT$WY(Cd97jiu59UT`bM7_gj*8sN-kER zv$;iNInCb85r3}px7;&xy|*rvJ#k-~oydKxd^<{$J5u`(jzG7_G+5*onL(9tKn;!r zNeAmS=NH$Ef9>N3X1?)T-HNBQZ*I*$l6&aX>8ctKgb88VGb}=8;{R7l&ReY)l{Wg| z0N@*d3&>$9iV?QNl%s3M?C7~Xjv-&2A8MI;g$zaZ_fLJ}A3(GEC$k**fj@PwUecx( zU-eLg+dyhKqs|JdrB>5aLx$;rNM;OF_>*i`%i`!E4!=?tvb_x`)G)LAXQCmiDL7>C z4BdVpTUORTht${rVTuV-vs$ejBE;;UVkwk=zGX*M-^AJPjW;Gch3yAc_LX-V8Yof@RR(#|MiaHM7?O@bHl zNi3L4m_`HTDs8bP9B3XtQ5rQg(z)MT?!YgG82aWg;u z-i+mm=?BUyjx;vZw6!;4bk%azex}X-a>DkIXW#akyJfT~@9QS(2oPu3jgw5rgl9}N zqzC*pe%bDlyu+t!E;InsJsqvecvY5&LWp^9{=+f2{YoEU{w<(d{u9@fb@uhPa_h?Z zmcy;~8E+@~{Xy^c?AuN=)?@y`ab)*I72d5W;yohDIxogPX(DvK}aE)n?QZO*7j z>!`?lr^r0#(0wl9NnZNYk&BWz8D>OS^2o@HyTjAr8;*>hTV?4rB zgTnVt3EkxPRLm1E#jQv!U7eI}DL-`R1ZVp;Am>#U(W)Iqs2cw7<5Bw^17?J+Bk)N? z00?;SOAisGOeVhLh?;cd^RFoyc#0M|0I4C&5yc$+l5F5_z!WhwOM+F;?IAT+UGT*T*j{d>w;#PCK?f8_DA(PrF9BI4JFI(3?i`0l!fz(`uj9QJz z6>xWF4j#L7p_zT(!-Q#yAYk#!kh-O}AE{jyCW@u@s9WGC^xufoK(3-4 zkw0w2Iq1}i{h|1k3yz5g!<8jnfz(~tMhUyD&nnvdXMKQ`J~m^c7G%1FWwXT(Hzu5w z)@&TdVc|wbN++q!06yU1h^UOOvBg`n$NNv_7o*pvq!%AMaHzSduBE-{B1hZwT&-^E zTd}=(%9AGFSJsX(TmCb)^llC5+(MDrKFldz<6c|!{5!kTj@F;9Z$jW)?&RKc#;e$p z(FsJ6DWja;|7ww%3MK=F1>(B(tKHW)#-`_DXLI+}J}y74Y`&VXI`x77(~Ns|IoGZQ z8&mFjWz&dA%iWO$!bREcjmjMnnGN6A*WmL1*n1D~If6O zd6PVGoZ>i6;>ea&DUlLM^ov_i*wiV>qIwr4u{W`T=)DpE!3y>Uk{~+Kd&hpi*#oSu z2oeHm7Ws?!Ib5E*_hL_<|ID13Ink*`N(+q1pnLh5cT5R(cR22OTH}eNhwT}5XkJn2 z#G?0bWO^^i9i5mwtjBJ2QDr1Htac0Om_V)vRGVgz4-rkT|5}%n}yu0As znd1%hb<%-OaU*YaSyeN0ZAeY;jh5EUcV1N|PywcpsxXZ*GoyizC!jg(inHq5 zxlvbD?$!QSwT?Tbo85caN}3PV?79Y|Wr!6(WK~XHc17j6hWZ-Oj_Umt7tS9& zU!8dL;@!VlLilS=4uTYn|NT_Pb5WsdWXj!(Gyll8;UA(ti96bOpu8TB8^P%QHod3C zU_1m&IwUZs(A~bKHX@`n)m1mOH*e1?{OSpvHKs5p7#H8N$ zTysW-`|+ zIzKQf{W~!`{>J|4&J)e070sx6dOKQVGe}$^WR|LBa+8pne#28scBcnAhA^B*7vG36 z8`$02JaFhlOUQGp@B2mcT~E9|E$q{2ixXI1zA?LiVDDJcF10-2xPWOmMiQ(hYsvuh zy`HgR35L+^X-)ICXApxFM#a;SiNPm-cu5-Jop=rdK(7iz#d4VHNWH_p0H~%xaq%UJja@;4;n(e?mW)Z{}_0 z3(be)$?#Xa$3$w?=VNdn%65@PnWY;g57W}|lz7d*p`*Acj+p?rpctXCyGzZkYeQ;- zFo<8Qag?w@Y$Y6l93+WA9aq-#{m4&d1g)ALi)fjv*|NM@^)cC_6L6-qj(p`Eo#hpk z$sLL@$)0>?*y`^+ws1?)p=}8}4;8_W+KYAjD_b9YdHvK`?@zHN zpl4HW;Dxexwm=vI?xRcOiC1in`=S!}n0(aocSUXc*1Wf$-LZF1RY!eWPk&dt-UUqK zS4~-cY`fDUX{=K1W3|)XLTK=srkYK8g+H7hGwGql0YRVmIFekWay4v;@q&5wfWJ*d ziOV82ty48r_GZIXU6|>+B-Q)rRF8$}NGn*~_|97G`>)Uc-IH%^N;sIET6A<*VfE4d zEmh|_+MC+3d=oUgifas{rd^2KLw)^tX<<=z_pBG$r}m1?_Kv;GU|qH|dFUUV?mB3LLe6?cXESZkLSVqmj(I?AYCvqVw`0eo zpyhx1KUm>8rpPs`27r`$Zkc2SMs#KR5^++tpV!URN=+>ZdG2k>KS6 zh9h_@^uS;$d$x`?9-Teec>bdPFY{lS_8-;>k32Ue;NZ!$f^toSjj!OPfjKbv;Kk$jpbFt=3|Lt+S zy);W22V`?(_QddQcSUS)`&rCi1ic=!GA-#~`GFJX4j$N7U3N?+z}GM4*p)^>QCjt_ zl26AVvkIxXQR3(ipQXCFi|F+ni*a@ zHc~rtEEK0cUdNVFI+diVyxgp|YL|MbO5_RP2%vlt&UI0*MoipNJCpBKJ1;=w-dSWqrvV^FEpo`Z=bdz6<1dohufr9eBk-VUs;j9_i#pLa>bb=tt|~0%CH+Ki@L7^EoM!}zwlj`-~7FKvn|tvy=ah^3a! z**$_Cg49OPFCl^8HQz{^sY6T6U|(x_L-q2MtnWTzo$%`=cg1Y?vBclDv{Va9)#j%W z-$}&1%gNMc4OJ!iDEvuGnijOmWAV<(FXT*!O7xqvX7aD!`8WHfmGNao`DacP9;rQa zr2YJSt<{&kkknrg2FTfi0i#Jp60Ft1D4Jq%{ z9h(l$ocDo$)DE8|`M%M+{cOb`b)X~LfN8)2n9c)4R8oSQUrZ(p0}gJJVpAr^CfxmO zO5h_)pL}_BW`61E1BW~6YPva-X+X9@(GTlg9bL^`o6`>5d;h|TmMt8(CL1E-o20agyPMQD5a6j)PfVU0%dB4+sp;W?#%z60z*B>~DJfPwd^c&u7?^wWl__MI?JTay1Jv*@~w;w|heLFj7y9N}2%M z9FsSK)Wv>L1(Krk;FK5$l@#x!?&d>A$M@;|T4c6n%L!au>>d_J;NSbAwoiQM)q5X) zan4&i*B6!*o~${2zPh!sVX&jIul3^ZDN=(D$fuX3uIeEKRw11NL}zHY{93*7PeBT* zLCukusTHs_MiWfPqZRy#svQtx0<@VK4^q=7bchmlc_A;qUd^R+Q=q04v)ax>Vy=Gd-dNyrw z&~UeB5mCVzD4p}*lyg#FK_w8V1OGkZ!_<=e(j!F$+4YrYx;iCdJUA(fdZ25t6Gu3` zq^jpHgWi}v=OYdy;BNuPOJ45$(ab}Cw8)&m7fRjG0Y)W!V@cdM=Dqn|#_4@$*#u{| zvCR;uvEwC*gjgvL3<-iXbnCq!HIKTQ*aqw$=s4Hdn0WO3pFh6P^WPoXuU_{I+B)^= zebbko&?0gv!Ys}?W7bdrIx3Uo>B#VmO7U3~KlS;P0LSO|{cj$$!`u80x?{IwX9hK-Boe5HVgy#whL}eq#DUnSu zI=av+rohdf17fmY;Oj`o6rb3$Q=${6SU(R$*{xwiVMq4q}3Wn+0Lq^4Y%LpSu|^^Bvzy}>u*Tiq++Rt#Hucp+HKKE1ZO zqq<#Rp1k*k_@cXh6Lr^xZw*!q4Q zkeZrPf5d9#&_u<6?8{c0hbH6!bD*2*K>pkWXfwk@=<}7{9rtr=CestXTKTrL3+;7mWt}m_STL8ta5bBa=6PW32-CKQIxZ)u|vI`{T&T` z_&T&Uop0_~lXv7VWg$MGX|9o3zEb**}Ho8E~-0eiYSY$$1@+ec4?%RKo?q{iAy zX}?XRri;ACo&2IQt`e!m+5n{Hpi#qj04p*)2IPdMWeNLVE^M3`^66dAW*{bO5h>nL zyS%JTOF6uqI)99~imA_sI`uJhAjI<}6Cx zTefG<(T4Jxq0TON8wRnB62YzRcA`qP_v%YlWlx{;mUrj|Z+qg^%^yqZ2sF@iaj)Bw)ohgg=kVmXm z9df;f7?|dTymmBFt0r()Lqi4~f?2M>^N6XB`S6Bj%o6Fban2vrd)J`-Hjo+v*Ioz_ zf`cJwGH-|42XtIQeq?!nX4odUZq1hO9$O5(W$pV$UmmO#RC(ChpB+YOGLtNy-~G^% zg)4VvmYzCs{zCcrGdO3pw+=I4L~R`G=^z|a&wyUnr)QjQ{*&1+5siUAM5U}=sF0f1 zs?4Z+Hri=);96{^wum_1+opxB_=|b(e42LV__+=?1c)r!s}s1|Kx%^qqQHdC(_R{D zG+)AWbau4WHZ-58YTA%@eEX@sKMVfARI{%p~QI}!?xoIZE4qP)7NtqYGQsw2kUMzn0I!3F@ddHmNHNUcJJ zJ0mq-S{~7vHx{XfBXqU~i&@f{${_aKUkqmB9x!r%Oxmv#nPHuyLa5ue>7G6fx? z3V;k_3T1mm=K|9Pd=$yukq>bDII?`Lsel3pq521J^myQvyB~^Luwr|`p|aB_D+z@S zBhb>9hOY1o+kQ3kCkwM@JduGmn1q0!jo+I8!Fy>( zHY8@1oj%iiv8K0&4Ix8*mqB80h?0f2->6FlcsQZ*0jv$ClG(~E#kzi=tA(8@;>iqx zk7w)KPc#qCdwuit|BCre#OmpmZQA3X`#p2eb@4uz1-m^_EJUXTIuZ?}PG%ab-i9fn zpMhXFCHN)3sH^}-MnF^=U`>XPB*jPZ8-A&UrLghsZ%djIwrSF%uiyR1^ZyX>>YH%| zMW<@_pC~V{zDUSkx}>|aM;t7!YBt}fP8{!hA+TJ~Tg1{aFwVpU$SirF1R%RajvH^0 zH|BTL2Xv!uW3)oSoN9|RQkdvwX6Tc#ks27KD|jJywHIJ+eE;t4Q$S1+suWdW?y5wZ zsmkREd1qN(;ilP&-@PVZ`3AErdhEs{HEb}_P&c#y!e`Jv9jj9`j2UOU@A}OPocaV4 zt_5Xkj$L?GPF|2Y26BN}&d5c6Qs}yGJz(FMzdxa{q^zo@rmh-HG&#EdUi^Pp-h-_5 z>elYltwTQwdddH(75pJGHE(mbrGb**AWtp}mymq|9=b-RY74Wp#TlAo=iQ4F?|x|6 zb8AcX9B-|xMgAb*R3}L&9@tDf#gtc6b>hdYwjKH0O)$1j=*+S67fUL-Kige*_aiTQ z-~TeyDZri#k7_SpQCn5v31Qpsee8qpKlBU z9lh)+K^7E~08KMEhpQrPLd6ZufZ^@Sn}kZLvAYDR?|k(6n}gJb;nQGCA12?7roB(IzvX+!9RG$Gt_;gDEhaj9}94qFxXnO5>2bQs;PT#&A<=my?pm$%kGHS>}|oC@qlJ6 z)S?RAV)NMuz*qvYI?#~}7Q-6R;YP}(^9>eGxF)}-G?hShJ|c{R^6tjy@MB=wGcxhE zn8fKppSu4v?3?#n7k#=TdH3OiCr(#Z67#Rk@Xj-;Z15H%)%`vAUvS#E6w(0=CN7N5 zD1hLu+>yRkNNt+KDZCzCdG$nrAb9|e`l}H#;l|9+C1WGCl6F;DSh6A5@+a48yg_91 zQq?v;Qh&-)1HnV`;G3*DV9^Gpgxcz zLz7A9O-=^T-%dXCow@JMT#)U(aK9Fo=N40psTEs?zK+z`9pvYdP{~^ zDGvsqxZsN0N%l;yBT9CSS)@?o$uJX@Q@E4FjzbABFv* zE*+NV?HxzHZT-a8vB_g`nr2Oz6jS6Eo=tFdoP#ilC(eck(<3^^6*GgF0xhP{HM$U> zbhBl9TGA#(W#Jq*DQwH+;7#8O`RIp_N9@QeC@3zyaK4@ZrJ^4(`cTxu6ox56zYbEL zZqes|oH+T>7q!_d#y@|kjC*7PMrfKX&vVIM0<+u|zW%|NHd$Z#aL>Ub7cNw`b~zz6 zmX?E9gWq7Jc7|yg@8N0D-9z*h`NWPGyXP=ygKaHU71g^>*FF5qa=(AJ1U&XWA^u!r z_h`|3wb*_1D*f#5NSa{ZIl-Rb?||XVV*lDTCP#~vJEk2TF^om3m!xD8dC%x{x0p=V zm@IyyVXhe?=Y438ubdRT+V}ovXa2YKhqLVOZQ7ZVlXvo1XO_j`kSR`jtq{4RWz>=xu86&G(oY znl?64gU$*l=`=jhdE0gD0W}I#)vT>TH}3ET3aR;xY6SyFwax1~R^zH(MFrsBsGh3x zm0+6Zsx8-o)GRQxh(mJN4Mc!t1{rJ~)Xxp+zg)WcTb8wM^SAjg-ly4%{Fdx@4UWU} z6q=7S2$UAhD(jjUNB;J7e|sh&EFcAL2*ObrKC$TmQOSN`TV_7-)?-hesnZwR zI;t<$_lTk$cTq0*0@1XS)R|YOE2`J!9hv;#i-BRA1EW%*>g*n(*%sq!M=GSoH!9f& zI&TmhXpUe|6fqej+Joma`I*i$KmiFG}L8v;- z6W?HV;2Vbe+h{LU5x^9Yi8}T5qm~~Stf_6d(9*v#|HyZKG4IabES_Qc9MzwnJ;lc^ zE~q%4B7(U`Wn-vJ={%wNf%cRDOT5Rtje!rm{r3<5HX-%o_N{pbN=i$MbKB}q4)j&^ z>lX=tt&p1SRiVDp*8_SF3e~HCYW`4=nm-p{{*p{RjMM{z>|79|Opw~T-5p-yYLMDT zkoxo6o_x>AON&6h(o4ogiFB5P0TGH!JqVQ43z^ni2iYqYu7goM-=c>v-!&!VQ#bn- z&AO9_rjw%cT<0eEM&(XeQfv%gmcnS)=mNKB=8_C0wq)+sOfOs3fQDl^vP7KC9SX7~$xHMj_DCL@z(Ms5G|h!1`m@p5|U zxsw;_TRLT{!Vstlb7#atk-2i?E{YPJkIYEvUZbPA8-p%W#<1M#fn^!$@2tPb56;&# zrj?fe_3Y;-|K^oD7G!84$?i)^wT1iW+fhiJX>dmZ(_k@(3{oqwHZU5PPUWLBQnSV< z+7f1jt^Y>Er!#&XJNMnq3*KK9pOtg+#F2*b)4dlfIAvDv=GZS8da6f~$@zP7DYWGd zF@lOBDvm*8p~DKPK{1FWf5mkR8!8lgMBo9bRrSWGKNw-4pQxwx>Pc-CpeC*sDdAXt8qio_kE9pCg_qpi{%s z{KK+1fKQ7^cPH>sOv22VZBrgx_MKlk)+Ofc-cwRhRoT*p-3dXYdxxNXiV(4?g&fgP z@qlY>Z#!Mr_Wg(Ke?0%)dmK9h#jkmnX4{2K9bk(m;3q;NCR?DS7PCu>F2u&w1e(|CptcQ{@j6 z7c{q2Of~_#*?p^QY>Ue({K=e{yJx@UGy5~Ir`F9_km(wh$k~7Hv4xr?3!8JINua8o zVo979wCT?ItF@mj`0KfEZAdLm%P20{ec<%TGxarQkTUO%LNeq!M6c^|_kcsr8Vq-F}S zeeY*WbHzL>U!#zflRjv9+V6r~g>h#h=W!fAg`I?+RW$Gi>t|OZ)^| zx<^DR=r4F}PoXCM_IPG26@#DDVse>CRE8~bK6*qac|^ziL~WaFTYqoF$MZhP*i+qK zexYWl9bZ2p(~8QS&3M{-<1RygY#=o~O5=>C%ALFvEjDIwL_8SAM1I!We(KEW_3n#-RIvXQ=W`#;MbC zLZNYM0ou6-gl-yOO_h}P^-7iJIrTS@n#L-AgSV+SIA?g<7)Y(qlNXXv#a)wxc-7@n ze;5o3Rs51-t8VRBn5EN)s{hp_8G97?%{BBG%gV3>f)w=V?R9!r6GY&YuHXM*(UeGF zF%kF^`i4+xV-LE}#lFwQUaCc*Udz`Oq`AgI_u{5TBu)>@m~1HuSa3jd^UQV&1BmCg-kkMGauV`pr{Ql=N{w;LIyww<>x-Bf# z93@DvevxrF>_~KOiA(}g7b-e$AoT(2<73O5NQ}hDZ6waM2dw{Q$+k5|+K$z>)l^^T zX{s7%Z-A;H#d5#W1&2m8;2GG*p`NgdYvOZm`&rn;U%&EaixONOdY{7qwUBs>>s(`Z z6CK6FmO~t~X+ayNKKSOh9(ncuhQ9ySj(s^LNA~aEKhE=}uT+yOJ*V<28O#PkG_rAvN z-m`;x@TNl(gI0lzYz;7Z0&Q_5P{SCkVpqp5lJHm2B`(pq-i{O)Fd5va1W#Lv$AaBj zSjJTA&S?+4^dFX`8CG?45Z%WZZC1S?R9k&YO&ec zf)w`{c=h;+ktq`+vM1Q~xHO@(2V_T2-N}=v$ zuh=M2-6`74pxCTx9ZWyoIQ?glw*{~Fu~Ec9&9T>Kafyc|0csD;p-O_((UAIlkj0%) z53mhUB_K6aWwLcUiOiJ9?Gqk(?d7cV1!wDzo;=asP}$#BPb&$4GRB1xOc`1L*~tEE z<&@WVY}s4!{n<-BeiG{TA4~q~wcUP}B<;y<_=Wi{B#uYM?NP}S9(;4=FQ5ML+?N+G zPb@fEb@FT_=S{PfqijUY(Hx`P@qfj#RLSVJuLV+5A%N15@dvBgdh%-qzaO<`nh4Zs zBGxf^M68Q9kXmGFPf^ZfyF`iA6XD>LOpP)mAT~|2q-xU+)+zg#$N-baC9pL1>(?$RDH z#R&3jTOilNbCTG|7^wrC!w6F2^c@@TvLN0yCMm$a?VBOXt;^F-U1;oYY0}&3ap=Rd zh1D^PkK-S+tNEouYO&3O4PvgUmU5?!q5wxN1C9%n3xQTsLAs#-beo=1t^doL`KTk< z>z5sWB~u$}1XylZk!wI|`igTc|2XWE7gEYr7I4gH`{CoKS{q>LTXiBA!8nYl<&Du0 z2I^{>dnUy=)(JY;=yU{W=YaKEmUQ)si z_ps-9rcICBu;;ekzv@NjZN~97QEb)G#As-qFF= z_lS4cPh(f!6}HhgGDEW#YxX@}OZK}&rs5~-YfErw5S|6M-~Fmh+$><@qSPRh0e=Q$3$rt+NL--&XYJ@GMy!`!&)oN$r?tP0m=v(0qCK{H!s8zX{^!Dfv%mZDnv^{!%1@uIxL7ZG zA+%)7c5t6TRM!~gj{hq~n~gR=8pnmy4C43`U3#@Lwcv$NXt8&y>eXLP*f-;ex2MM> zQ>Y6j4KjHW{j3Szwq!n{m1U&xm?q8%d7dz!;sI?>L=CH1v)vXS)I!syM8>h{@NxFZ z-6yN}?mty^uCAv|1kEqa7y}ywpp6OC+djw$S2Pb6cj`ZSdgX0F@A?LypS{_UG zxx^H^+4E3?`&!ePu1qa2YYvmy%~s@Qga4Fzx<@5yF{ETUI@7-MzR0!z7W--DzB3i) z&i6F4BixNb0kEdD8+p-{=t(GQWS?5K8UU10XZ6Sigz#w?w(*c(4fgW+M5n&~^x!|d zmOnW%p7^(#g+Z4ELg%w;SfuWbR4rQL1os!zU#NNw(nE2LI;v(DFN zPF&?%ZYEMwHRfwa8|L4=1O2^igZj}<{jcqxa%3~)6haChiieaf)j;YT=$mh37KDz4 z?-rFvBEv%uYmpYYR|_xF79G&+nVyy{0gu1^_fadh?yW05ap7WhOR{P z*c6tG(?jI$Q|CjMhMJ0V$M$u$%3-NYbwqOYPTs?H zm9yaTKUY0xyzA?M)Zms-YyKN-?CP)7^?zIP*|fRK83=$F*C)kL8Ju1!*g@he|Hwoy zTLxc&*W4Ldl4j3xi7nC`B6R!BS^dMewG~0 z3h|08V&1}bdI(3#d=`w>VqrmXvQEC;vgyy}zqvB~;NcTzTk2~Ex^Y7r>=4Jk8+rlE zFkmDy#xgPBctlj?A+T)x02Koc%vkgdNRXoA1G;7N;cwVB`-R340#pmnpl@lHv2v4* zg_90{t61FeBendYWpiNIsvkeSWqD!U-cuci4xSxs>*;N5G=ebn;U?E9T)u(O)Q)t6 zJLr1#zFLxhKx&gTnHl=z_X4TeZNFZV;o9CqN2x!g>u$76Ez3$4nUI5~uHIvf{kyyL z`$9gRXxYlvp5`ck-U_j`r5h>3+nON~bYv<=0JuAn-J%3K1uJd4HB{gBJ%n6vu_pP> z|7^-bOCNuI$Id)#7{^A7tq*N6mQ8Wsz?1#ki3j?n=)7?%l=s6G&}0d7GPL(mok(QLWi961`6 zKEami_wbvKyq&Uf*YQ0k&K@s2UDHs-Q7-t|;njxj7v(T_o~V5H07sI^ldj&j@|OBD zy1wdoh3C)b2F`tJ=5rYy3-h&*bZs%l6}w&RMFdInjRdSodA^oi-jQIp%oZTYB`Ot+ z7Vo4OR7M#AAsfFP^x2aB*`x_-ZwIVSQ%#Z+->OuD5k<#)c9BuC(mE?&_{V;AMD6GR(_$n zj)NwL+5aoAB*jlEW=VwNo({dGw(7{<+R6&Z;-QHestC zdow=cWIf(m?I5+d4~$5=*EoP*`DepOZEQ)4gi1nTL6VC$B1%&S@$4p{RnTj6y>v)l zl6LOQ1km|p{o3~y_*>K2ko~SBa>t)8h9npS6I)tWYlk9 z5){F_sA`KCs)@rw6%80$|*;fD--X%Ki2#HrPzjH|05?+LdXYfYnWBr4NJ~F$|*c${jzS{PC{A8J5UJFu-UvvM3_P(Qi`adjL^R4L3 zV7<6YV>1>FQVXXCUYJPjXGws+`U0s1ronV3TNVR7DSXrPS<8Mf@5MElCHoE^Zf&S; zsHnstei*KltphX1NJE4{QF)#tZFivy@9pmGsO;{1epAw&561XD`oJz-%_o!(KBiGM-uwmlEOKa27{f?5@tmJ&B8bh zGeuX2)JzGy-L>EyQ>{BDJp9%}?_@1ll@q_e0^^OQp1#h0f+Jx0K?Q{cmn`WINPXjG z$Cux1kQwQ2D9r!wWom46on>l-YkaG}+#fgllgXbj5H~~njn27Gwz@tkF2CogSEh!q z^oiUigbSn=m=;L{`I_K` zh#Tzb(vAwCcqFb1>pOYUOQIy8uT)c!M7-}}XEzn=zwD{>v? zNm_VL)i$o&8Sq z$2*D+9IC6RfJJfk(i+q|2<@#9L>el_286xP&-Ll+Pqg0?^!}uXEgsfnEb|SSS`55R zvD(1L6obu^fg6^og#it=f!mi>AMO~9xCo_u4=y?V%u?7$nuBZNyt3Y)W9*Nja48uVd_T@+NING^e@Kyga)X^fu_mG z8DK3_RtBCOL<}S8ew1KCz%+V{O=tBVJiT@D><{jZP4o?ma}7`STU3Il+b~$uD8Xoz zB!5*hHQFjdwYvrL<{i^*TV~Av;Jd-ESypEj)%Kom?XRwHH98z!hk!NqsMPWI>tbOd zQ>!2z&T`^ti4thw!lA>Y&$qm#&a;kIQ0Fm%w@`V0fa;iw_L|nS=1a^B4ZI2a)T6r* zI;ld?jP87%Aj0EMO)Hde&6EFiNIj@`_Ufm4^he)I@p|}`0LK;&N1_&)EQHHeDAv~` zm~$jqp>GL*xR5){bglfr&|4x9NjQZ>|FE?)AAkKXpLp&c9|>E#b>|V3##LttoY7?* zNTJC4*mt2wgB(BHc;>=|C!(MGS=3vTfA#bX>t-!%he1dw4w^HpzB6dfu&`!G4G;MA!zXUfiUXra_V+NjB5itq?VcAjk+( zyGEw?&Rc!Qtfhba>#&cu#P8WxTzmG=V0#VBD#m0W!FZDNPG38A1;;KlJ+%0v2|r&r zJ$R#cSfUo3q@+s&ofF&~@vc$vT6BV|1GS7oYLvswE(58#JMvv@X&zx)ri8Egn}uta z7o9(Gv7@EFW{?BTxh&uyo_%?ZpRb2O2RZQ`~m%zz|0z6X|pShrQpYOQFMfkQ!)E zNPWHZW50VhnbVI9%S55rWnoTLUfsX8NX;S|1F5OJLTc)daLvd6T}aJz8Psdq^c|=B zzZ3S6+uTpR7qDSRkctfSgl^V+x5#2wL26cgrYliL9LTmpVBI70-6IQJtvp9zn5#vn zc|`4)6!zI|4?Oe8^DD!jej_;}=Sb)nkXoQz_zJcfsaWt% zB1m&UQuLafy=66ZjdF^*qN_}AlfasD{*vVb=Kv`ZYJ{N=x>dwS>I^1#wRF|jbT-wB zrFU0nd;bugwnV=LvxKf*BA8$D(%<2uf@y;oeoc^iko`&&GO4xteZe102;Yn->bW3a zi!jD(c*taupq3GBb0o3cbIAkKB;l{b`~cBAKX6g*l(5zJKJv`0=iW=qFJ$s`w^Zx> z&8;2v?R{-T`zHPhcaAgf9^&9jLYx9!mnM8}j5D(PYukoaIRtMg-cKT38#79#3@d1GsJpAbp0BucDTNFcMU_MeOi@pDqTD;0Ztgl%LDodsQDVxhteL^<(Df->L?i z6@ZT67E1L%u}kXg{84Q&^BdaxHI%7o1!Lh{;Y;#BvudM4YVKwa+>#-1hL4+|{RTFV z)#zcXOQy{I*l%H)h6QY7qI+z%M`W6(CCejXm#d}7*yh6&JW+GRYoZv>akJ#PS@K;i zMEgXb&e5XrmfAAavf|#yUVLFw;hU?IGK&tLxKL5kRMXSlHq^^LBW5s$OGjUaPGX0R zC!-RkZB1>RZGD3k^^N<^Ru$Cref#le0%m{c84*XJ5&+Fcz{ynLfWxw}K_a%}DpSR+l7p;!pclOx1%I0=lZA7eQl%2c!lCkDnE?^f)SqaOA zyw9N!?Rp1stD1=CCh=E$bL(G{OQTfD1%r;B5!CNg!h7M18>+v#bICqRmXuC)?+uE@oT zF9QcX=ejylJPC*L#0P)(+@>AJ>cv_9{MoLyOHVgoo?JJi9%04!pScH2)76H(RzFk> z(=8?;+~B?@-LWx0H16Qc&<{D!okQ;Y@tO=zkSO#Ei3pU73B7czjrBqz{7a6jHOnnB zLptGV5=0=-lIa(b>4K637TuAe*>`w^ue&YyqhG$fZ9^Uge|_EUIzt3fQ#UaJzhohO zy+1+$VBOJaD~$e1q`oZ1-Kr)s@l?@FKbioFab1FL&L5qTdNjXbzD@Os^B+3r)k}C{ z_7xyy64LQ^h509Dxn#!Bx>KSvQqxi@aNXA3`0MTTOXnusXryMO+k5o=)%suB)_Bif z>#`_E;{-`UN?McAcln01^$a3I!9ZkOX%dCL0p+$V4@;g$M813lQp@Q)$(n7`Wb5kx z6S@3@ysFiir&148@2l%9>*%X%ZEtODZf|cTwY9a7SBd=S#DUV)z50a#y{u*Ec#iH5E7s^8(jOGV|)M*~pc#>vG(JYy6_;*KS zPPN2+`>A(Ui#cfAwCGyMAwigT=I>f8R*606*dEFc4dbw zUn#l@X&qiXUwX}T`@qXp8vj1^)lufJLTbXIe}U9}7;p_$b`BiZ^?T>NH6i?Sj@yt; z=kR3zB?ZPPBr;wG2PN}FkOHJ;)C9E|CP7bQUSZh3i}4B!UH4~UZ+(z=H0AKwz31yr zwd$2!dUH!hcN3?qw32$7Tgai6^`{VNd8}0c$~O8f79iY*HHOs=%7xdxxj^SPa~^qOHP(EgSdDNtTT> zA6*vwerm~uzKgATQxivy^>^cmDYgH7x)?YNM-fPsnC1*gqw}BxU?GO4#>LRz!ltT; zrz(Kxp-^meoy{lU8W$gF1^mX>2dNnXvnT0Wv%;5TROjdg&YR`x~?{Fui zUVwPA#n-axN6*B)l2-L@TKS6ns;#FxQ>yw-b?fK4_48f&`5wL8$e-)f&vxl&JM=O# zU%sF0()V`i`AvFJot|0Vz5PtDCGO-D%Vy5Z6=Lq#CA){#M1&wijvhg3k*^g}XMx(@ z)*U2*PHUEIZBeNfnjL7*m^u4{7q{&_T-|Zu;&7OKy4QJH7>b9)pIO zHcZ1r)x=KTaHE$l?^o#-A~l}NkSgIxdIx)YhmKtAJgDmvpLla3R@Onu+S7;7W+1() zQ7{-P*e8&B7h)YrkeZO`1f7da6hO2yvb(h?P%>kxeaGKE`}v!BWgGUMODk*5tkd_m z>t*0|t6tTjSGCEVd}XsvnO?HaN2#9|~z z!U#lVxrQf!+Jwp%ErEg5ra;ZfVx+4=YFTBWahMQrmWp`CM{}em!H9BwEW`kO|DRvj zy!B|)sg@xW^5`+zYU+o>8C`X=Z`mI(d{BGH?D&xyxz8B(;i11(RabRTrBfy94}>W! zz69gcN4`>R1mh6EO=*<(sF#=-sNxv1E$>k%X_oan%GA`vESj;nY~^`qA~hM+STZKp zbW29zW+F9`U_B8ax1YK_cpbJVa%RDjy)G|cMHcTLzI|dyoPS8VM_8T~DLZ#sRFW2j zY@4L9;TV?f9h&DJULYhcT4I1}OA@vDpZ(Rd$@jmO_rzOyPrRG|)Y^S>KQ9g1SQ@n9 zV95G|!5d3MHenP!RrppUw`0|`@Hp~AzRPQU3)lc;(?rfE8)2N9$8mXBxJcQw74lrFYml_&q85(Hr?`iJrAhi(@yr+AhyKA7UbFd3H z6;$aRT>~9$gYB(DolS#XEu2V*%+AGM^AcWV4(RVbovs0?3B)@7B)xhC?Kdi36b#7J z&Pa`$)W=DAujZef%~I$Qp6eHu7kCU##;6o*kswTr|RFACHMq=qFJ`MzO+}SeRL5H)R<5T z3UfS1geWVdjgi?}WUkThOj=E!)8PWUEA8#F+I zF=DTxWHW@LLoNCbts4U7ZWIFh?0yZ;=>I7NST$c zkUG~r9QuaB6Izk(^?bfI>yvLRNWJ5!wcnb%=AI{4+!?ZFTJWmrA#0}wuTzN_N;ASX za-SBm{z_?T(59(RuJ~T$+S?yl_NUf0*tJeVOKCxsr;s`wYU5=|z;9HjkTqA49Rm(P zfpoCO+p^s!V!KN?MPj~4@S_Vp+h7PysN89z%R=u=Ey6$MReymwP z)vTXs9xQ9_=YG6RKi;mNY}d=%_4;5-+XTkGJkVaG<{8JYHJtOtS?* zN6A*e5HYc^#WuveKE1AA|NF3)?tJR?fUr$k7@Xc-k*Td{U)ep`%0S2q1*v6kdKjrA z^T2DOrh7-ILB!V&F>N<+;~ANJU(|M7;J-QVU50+*tPf{|eLgvKV_@h8mGHKn9Pv5# ziD4Tro2G}Xx_ADY_dNOPx2&sgw{3QtzlEJ~FAmHK&2q8ix>~Z`BQiKGJA&HNSlsn%V z$yK1-_;XvT*J6qAkCmqAJshQ)^&oo$uC{zJ@}K+RH$s*zO*ycqs_V$9+KyWGDtZmE znhBzsF+AZ_Go8CYJ&{)4>I-xj4^k^x5~KzeA<*PAqfy0`k(;SKqEb zo7p_o60gnve8OUIEm;dr@L#gaD=Jf@p70c}aAc5lR|_U3vYcf_TUhnkz&8n`b^*iz zYlC%%8u)~z`iG_jh9m`sB>0CV_=WET@%_TLk2}Q??%O{!2__*hG;RW{LRgB2kk&k? zC=3Ji7Fx;^=&fr+E+m&i6=9)Ta(gyi)U!gpYt@k=?+7-hpPlx>cX~$kIvSAKw=7$?f5vP7nQbTG)zdp{u5a zuEscdO6b}tq3g|L@EdEVhpYx8jI?@k$c7mq8}695{JXQ3ew4CrfXtt;1VGa# zB5s_CX@>pzgs`ptVN9eXW}|mlrgvyA$tz5fM>rD(O^>Gc(GXPG4-sphEb084fJa+l){o5~_<{8XjU9WdpB< zaa_8O2P!dkmre35p8MDWuztImC06JFr^chY5TC4^2K`@O+R33X^oAD7J`{d%2A@ov zK$|R2fS6^gWM?frQL`ko6M>B-h9xWn*T@|B7CEzQ?z#z2?{eoLkEh}^Obgfu2v20m zpyiO>4i^rJWiIO)l!rOD#|f7%h|fqBgVd4$n5 zSMTP~>Som;J$;-;FY}W`dqRuKsh`a&JA=dFrkX^y_ zEd*<&)uG#{1KTkG8TCirylmxpXjYyK^;iAP-*TCGm7zD7+he>(m7+kOpIw{wTa`8X zj>6OAH^`_CH_IAbE8aj8s56)OHs`$g@VaNru462yCqpnsJyp%=IV#uL{HEYc75DQ7z4!{m<3%@gc8l13K~{vUQ$)gfS@fTJWaT3K|3*z z`EE@7=UL}!&ewJ~R<<;Pd%&!>7Ja;~w6y4A`JwKPdTiQxuQ0DvyXT_b z3up`i-{*Awzn3Khgl;jQ8Fc<~x@@69;TMxf!SwZ=Kcesvp3Ne>9L#`h(-`SXFwHQD zgP38@j9a%MSB^lo!H$Z#I3aU6>{a%xVe{OAw}N5>+Wn~L+_A>?`mR1s#5PPAI>nbk zqKrx)`!9x=?t*d%J`GEk(tjgK!L))ZbyrXL0bBq4Qr_H+a{=*hv1c5t?$LL*>QAoT zeP_fvSYI#po8X9onVGmHs#dVd1gVK8N&v$6t0xA{Eu z_CGwcz$Gy)j0QUEi;qyN)3Mse#}z>UkNYHvEx?l~1e$=!7A=iNt7l0yp)5)OtrZ z0b%sC!>yB_T&V>mNH7ZIi?9^&$3&YQlwg1|6z@w38fYLFB!aDB628@!OM-4H@q2?x zKq$tO1Q4BzxZKMr(djn^S^iQbRh^|3;n>3@V+u>740S=`)cNb9KTJJYR?9h6pc|cQ)v!T6B*m-qq~efoWH3g0qs)iKIJ|cc(n{kHlFx4`FcXqi;XI zA-nW+Sxfb)p|(njP$Dp6B6L_Hs7kq4cL~HBF`q|}8fcIg%JX(zJe&LK2K0h9ed2>l zeZ#j%=&dhcXngtk+x=&~v*2T7>fLqaM|wKyl}ybRHMCdnZ9vMS#OeV(`Aqj+kGL@)RTEWB_hc^ zEDpS$_|zx!KH6Da(NNyf-Q2-m0IUlqWf&fa22y`X%Q1}9Um9U!rm6X6z_H^=IRc-2TKHeouZjF&eLM!yFF#J#lt0+6y}hQb({EjaV&8 zY{Qn1H3(8;$DWQK1W4^3o-)O@ePZ}p?Z02v9)4eY@B?r371o4+s5Fq;5XSji(VM|g z4exn@(YBq#>JeefF-fmfX zgZkiJ#t|ygWTwp}iHEoFGKno2!1pUDEvTVLF;H@AZJEqY1EJ6WD}fHM9?f8wPfXOK z^5*ug*#o?gyn5}eMQS=0k)N&>;nPqNP;)M`A(vzrIGSTt-prU?bb~U^1ySc~L28z| z;^Niv80mgPz=q4ka2JK0Ue~3UH4Z-c+E%|OJ_Dn1V-YM1Ndo4SH_as&tv(7tlilj1 zktAVK#!R63$Tp?gtQ`B!k8z**ig&6KjXKyxhPrH3r9~jM!F!Mw|Df>HNkJR`G5np( z{b!GzJzrjNwz0LPR}Kde=p549df|*3`q_GRfBY@Ywp~1WP@#*(nn}jLGLxx=XL;Il z{lgO{KJw-w!h#<;)=+s;Zx@+bsYYc$jMKoc9jQfv69z*`aL!1LKN&~C?P}L2KfKg8 zcmpwEL;z|)mA|1q?)nQSHh+ijtoLF+-h7~RFWPUA8UY@#mQs-8dm2%{Q|_LNL*buf z-Z}dn6wc#+zro<$(D{Q5XrQn-|C(%`0nG~0z-9H7+?i?2PXoT4x`p!-@=k*{wH-|*MLuWZ?Svb3tHvayY`--bHcWHe<9MP%wrk=o#sN7D+mD4p-a zzcD5U;dI1~!ie|P&^?IL;`Y;Be;N7lgvZ{Q92qAu`9qWB3^Hu#5r-990#eIPw6PhD zL`?m~nH?sCJ5HCP?f`s!B9gslz32Vl%Xde7_QO}xiJCHT-ly85ANq!F1*yU45j!*l zYC~y8R~Qy|vX?<#1Z|8%P?+Zmxrk=JBX083DH9{tPYGFmSI9^AzaAfd@IrM9Cy@5F zwG;0M#Zg~>7t;sro+!PUv?S(|YC8`{cg{_F09)|UXZ^G9_}ezOb=`oRAqi-P}Q(YvrrX6-OAP5pYUt{2zp z-+A5$Rf3s#kPA`O!&evYa|Zq%tG16KbX};M)nuk(<~ML`Ns4 zw&S@&c@$EcFB!>vQP4=~Bj#&X*$yF_~+Bf-{e*!^bmkwc~LdFX`?GY;Xdd*VXn z#rl@679z2LdF?}bQ)hqU#fBbC#ay3wg9s0}v|uzY;N?WdzbcB5Nmat$&y?*OJHy12Ye;exC*L@;D+*$wX_R2nk%ZL?nS zoxjd7AAo43<<*85S*x9&Z(zqb51NDW&clDq7!6hTVcBMg{IPWu|7v6tbNJzqyA7S!Sp z5t?A&b+UUz^2FfvcR#e~&7|GC&NU%C_Vl7CB!&+f5;{qEKE;eNG;#?CD3~;YO6sY) z8z!B6E#F;oH&&}YSXO?as;w{MSk2mfb>Dg76~EssyJt}<$JmLQ2ql0e4Pz1`KEH5c z^z8^z%jS{M)dr(N^MP`HU=z(!pe13(6K@Cpr{k$rg-@rS|C9M|OnvZquU{?YFn0|6 zSR;nKEGF@2z<_&^%`rc-a!1gn2t(FJIVQXO8QQ`uEo8G66R(A>4_LSZ=kD9XK8oE? zy!%2|UAJD_*s2pFou0vbLX0bf^3XQAh`TXqnapHw8CaXdmN5Vwlw>-Zx~eC9tLU)8 z4iwJlJe^1M=I7D+Lh~;XKd)4ORe634u9Pd~Hst`r4hARzVw z&IWR3({A)|m<3T=m>-4ISL%H8`InH|nENaQR)j&xF?8X76m%VWTQmFDC^^d8^h#Y{ zccOd7qS>>1tncbUlXwTH&>{E-aM>a^B*dbKi+vzl-Q+`_IC#_4GDi0E2Ne zo3Y494b_dE`&)GPCzhf8mV*()FhFuvjgAAg!%}^0nIQFqhu?@=kzR24R6|u6)&b0% zVNn9e<9sgCHx{lLD4OeBnmA{m( zP-yB6pFiT7q_$d=uG^HXjY%bD@Bk2s;&iWY5kh5t%ASjnhWFNuQI^O#f>7W!HV+&r zf@_k0@P=>9dDXfyCH+kE*_NR;VzwbEN&p;23hQ>f5^`DXdVpJ7=t2)DbK!7sYck61$-$ex`S`Lw`nCPVZ6$9cm;U&vB~$+C$!Yg5zCCya z+uzb}oXCS6J|Tjw*@k6if-!#treOf+t}oaCcz`7s5bo4sU>-KPEkSsX^A1`2!25YS zj`v*X*X!B9?}Ckifo#%yTNP5P89R({z_j$+Eko)r#>7AeK%)(Xj4o_8ykB0tDhz1FYAwM25 z#x@qd*t(3FQj9;8KbOB1ZJre5T*OGZ2Hj9`4lh?#>QAg=iRa9>G|*@xjlIjU;r~9j zX>(am!hy=V+P(n@N>`8G15!7%4mDIXwd`%tJ!ik-X5Z!?nd=jlPcGH)5YiMuS{9&UuOdJ#3Bg7|5ghbM?m^>_XdWWUsdpIFDGcY*Q zFO*q20@Jcvt&)M%VaY@B#i3Wd%m=_(teQ|N8W2>kiZ&s@JQVI2TnP z!q@@(Ksm@o{sW9IL27z$m>SCP1IL2Ml8m7o&Z{TJ!_MvwOiAGFHXNw?rzLBD@N9zn zW1mcn%EJCZtjHpB2y8+K7tgRA%x5?s8YoE0dI@L6;SiyW^a%ZpVj+!~sP2(FJwms6 z&fhfY@el9(x#f|CZ>~+>lURK0z0D~iet5|< zPM~w3OER7K08F!8AiT=0zaYGbW{~|W5nEGeBBN+BI?r2MZ+57uiIO^1^~T^d)Gztj zC8}=|+RO}H0s362A9xRN!?&sv$c$JrU$@Qxsnu5XmFnR9oaWOgevfQxHo?qXw>ph_ z5tUTWlFvOpL@Z3kTJmI}`9xQ{nOtAZv{6u%F8? z1PJ9f43PAGqHrJMaEe3Cx6OGiFns;hA~i%1N8bafiw_^IxKP&9-iY2?fCiuN zc0y!{pqJI5|FIR<_|GTX6Nx%I8m4)2S)>-Z%<%8Kaq~wky$zo%!y!u`MkOT`!eKIt z{6jJWgR&>j&z=x$=uE`!P67Hbtb=_3G)eT#oHi1Yqy-bTECu(dnIWIvH~Zz+v(M#M z^qr_ek;rK+tTRDgbpRH_GcqoMM{3-;8+}MWj=;1GnM$S-SmbNqo=&dl*3ZC8zn41g z(bw*<@9>4)<*bdTlKq}L;vQS9J+<9GIukEEVudN^=nQ?K?K*xmks2m}Dp60a zt3zr-rdCLemGBoxjSz>;OTS*(q`$o5h&8Eda^wat$4+;91}ft5CL&FR@A9wB1sM(7X z4xX)UXz1^0hXfn68ht4SNUchy9wzBmH-SV35jr;v{e0k^jCvnYR_goov%3D|Cz*d_ zUp?8n4U1)t{zQ2@I^nZMZ>vOJeZ*)=o3&>0!>_-(eb=sohia-deKxD=_DHFpBy+f!^j+`9FLEa8^&%(0$ zl7uv^lAkqsrhPNVaQ}VmXYr@H%bNA3Ht}}U#af#+CxLXFks2IV!^C(QqtDPOq!x_s z?GU>WQh%R>y@G`Db9SO=xq~G0|ZLf#5$m6N)_gc38AZp#(eT}CY2P$eC8fvSC zdOQ0J_cJ=Di>9mY;2b^KQjz&Q{_9FanCB+em~Z0=6!ns?c&J`tX4LNiK1FY#{J;cv z6BN{QK0=DYJMKI|=LtZlzvWe2&gGi<8fK_#D@55;(*4TR&P{1xCDvF9-lic4;xyg;`#U#c? z=NvkR-mAT9GAg4g{NLFF+Y>C8-1vOC-+mUu?0sg>tXVU&-Zf>< zP&tEnYK^ePq3J=s@GCCO*=m~2S15VN1Q#nJHfGwP2A}Mu$=kDj8mwy+0*!(BmKv5h z&X2`*7}!dIjDABcKr1{}=T)iSb2vSld#TTkb2!NkO_J$8h|UGeLh#F(C_SKTDAO9ZSXARvuVwDV=jH$I36Gz`Wt-?6;@&d#&rcAs5r zb?SKZ&5EMtNB0WVjb)G2^<^DZSkRkQryjD!c8K}$!P{f|Zxi*yagA2|UQ%C6K9IV< zc^q~cANtd&PlInVG!!7d^qM_&2PRUbjg@@x5W0 z_?D&eZ422u=HgdXe^9~tSqVX?Y;W7}``E_yv5k3?L+BlQe0Fplkc~d_P^aX+7P29> zDFdvPs2Fcq$M><0CoX9VERjAnB{KTWP(RDq!R8l-{d{ot?t=mGcaw@bi>o^@E%3M% z!{8`_t^sh?0E6;|pO!KyX!6H^IeOFNWN!wkvC$mVCeR+Ig)yJ5XEdojuBR=vJv!#+ z!^3uC6MO8@hq2|v*K87Bx0a&~LcFl423kac`dYK30~WJ zc8JZ@Nt{cAw)nojX6K|&?CnpAFD0bj%D-3j@WG?na&>bRtc9YQrik=Xy`O^K_}Fi> zy%+=j7=^&mW+Uw5Ui;zHYqmHG0HsF8{|B1K4>7|^@2J7%NIDut53!K6kfKH6+vX|# z%o0a%6hpRO9QE~{Eg^9i(ktY*%ZqE8tLw2-43o!4WCV-s+Jg*Z{1B!Lk;#95L3vXB zNj=ZHY}7q|!gD-9#byHlo}lfa`PqxrwDbvXp=kjMaPb6Cg7Aohjp6@G50ZW^QnNM& zm}L2f2Z8DCYHY?S=PduM2QvBFks8bZ&M5y7b&tGg=8OJ{LP5qcao?i|5D%^%5C4l> z$OKo97tw6NBxL{`(o2)KXZ-x%ZNSi< zjt%5swMje<;(=PDc={h*a##|+rreF=kjOU9Z*b+L3FCMji|DtlV*6S}Q@z3HJ#s=c z2*>(>prU)}(zo8S<|7iKf=IN`MX~QXh|%jIdoJOeAZ(wwQ}Eg@Y|tcs(?;5R{t|uoN$uu4HNs{&Zm`TJt(iLt8Za&nV>2~>h=cgJ%fVzv(_dXBYJM+FM9YkCRw)Oqak#`FcXR$Vg-FT;&(Vg zoSN~9>W`q0b!;D-s6IB=-?GJavY;z(a0tES5cN9eI@uU=_mwy8u|Y0Y7-F#*zmE<7 zZR~|>9mlwQvO8ZF5!+Ieh#6oV_pVJerWK}bKm5&}_?Yba+hy1sUfqr_lCWI?+3N$1 ztP6-BHx$+jks2QcVreu}ju0$bE96`CL|vp-2Z-((bBEsL<5TOwFmE^s z*i!XP8`28iwTK&P9y8qR#!&Mc?^?tRvWV+%nZVfR@_}ZmLA#R%nW^5j5Dnga9Wx_3 zJC1(6H{SMGY+P>Xy}AzMj^Z;>oM;Q}kH~57-Ich94(!b>G%(el)MZ~`A2Le%X#(_C z^C69aeG!V6MW}AQ+XZ&e##HOF&+!D%0QdtsXzFmp$wv4JJ(|%{K9MvS(1Z!fA)e5y z2gB%4voq9S3_Q~~*_c@meq!bDEY=`$2m#OGp}%(F&MV3-%LY3OPi6irC+rg%0Q_K_ zfdy+?4G+v_8EN!SnJ9UBoEb$@F?Z``+SMSa~;Uvo2MZ9hu z)5lTr4ln6VUg}%UiD0QWoIed?nK0B|3Pm@;{NgI}1DA!_bq~urYf751ClnS=S9d(9 zQLlB{JAU`xk>=4DCLLf!B?A%tXF`X1fJOWeTkMt@Gtn+?)~-W)gtyWPE6eH{n;w&+ zGrN$QjD9zx0|umq`s)3K2xxJ3s{_C^MQSz9$gX&#PN`FSC)}N|HGH(?<-uGsii?sZ zT)luOq|#sEAG$kY%(r3lzvG>bSLNj2DJv_(78ZaTW`}gFM^vXbsIj9aK1&Bi54GhF zv56mK75}2hpM8$awcc=4_Vvmd=#~D49gsTeE$i#3KX2{){T0=pNK)}EfA42?y1ymp z6d|jV{j5&Cw)1Fz&ZU0#*WTnt_IDM%ZZCM0n?@D9)22R}Uh`hijR`;RAG_=Kp_XLBz<~})*ufqLa9}eZh!g^6WFF7( zmhg^kEQnzhR+Eg<04ovtyb~Q_ChR&s@E;sgtFTjwJ7*Iz_=>E14=Nk6m3t#rN?>fK zzO$|ZWA8BF@o^&eLdxhZK104cFyNOnqa6e&-@$g0H#vgWxguEONE#zW!z^M)n8yyY zK+}k2I7vVQ8DvT3FNT^ahMLLV`Za2VolwhFI^OJp&d%d=wuf?0OCK{F7Y3*K=)B6U{9TKXN#Tq=Lx0pTv#9%-YsDulu9=Bvpp?jpa`|Ym(JtDzV z#EG$1s(YWSeyOH~i!cZYtOPn}A|T@Ik;-4crF^pS&?VnUnzE|N62%CL)D%*Y3z`uy ziQKV~AWmGkrLLw2!TuMJ8l{GD1LO|;zXbc(pAZsRezj(Urnofyr1rM7py-hzBjB#@ zzFB5ouZN4+CzoathtNUGbOU{!Etr&{Z4-jv-Z$8q9_;cb_M18oP{ zCJeF__Qo9u0~-ed?uvNFChE1VC;IF-_1c!8zCVQb`!?|HFTMJH>Cx{C54e55@Ot}8 zpFUst^!d{N?JdE5KM(08AuwLSi+CN8fM|q>{GG4;-}yf5wQu*l_RZecww>&r`O)gAa6xuLwHv|NqT7$$5B z7-?}0AqUw&J`hfCX(&fLgex6jBOYoVrM>;o?xTERUh&=XT6}neZZ#i-$n~=XbK+fV!62&yxbTDE zAHM67_76eJe{{OQSL7Ak#sU>oNJNglBF?0!>QM6^s^^#;8M5;dj)54?x;F&G`{v6Sp98q7}*ipOA zPTv~leK9TZR$WC!OJ#BSla{6@otS1KO%G)XG(u^E82|H-nzT&vYjqPQLdZ8+1vQVe zn$_?7Uz=oha>TCRM|0z_$q8&N9N7tT8Wk9J(NLS1q1Lg)K(Zw(!25C~{kZWsm$N@7 z0lW>gkqxv_z=iyWm|fShj~u$iYx1XD&-0Rt!n6c&(!JY7d5qz~Iyn1xLKE^xxm)5FZJp<)c=$}qnVf)EhraI1t7R`J8F;&EusVB2^M z%0Wbol*q3`tq2XX6%OSlpua!LPVnyba}#&|w$|-pF#l#saeZ-hZA&B8wIW3f^pR89 z{);gssxUQSnm*B-x250VLMuXHLfZqiHNljIhs%If7htgu5uU1FL_(E6BB4=HHA`JQ zL@;`xjj*q?z{fuM>mJ0(f-L;V4x2jVjb)79f-8VHTs)^Rhuar1#y)2~|075Zxk0eV z#eYOww!FV6opc*D;QR}$p63i6?>+Sr8gz^zBDSTE}AgdpIX>8SyX9h=19R`ownZ$JXONvYzlEq46KtPT9g6_Mv0n4_!w7 zw14RKE!r>3% z^84HI``O2V2H3?7;>JOGpfOIOe%Quv$MtueRak^J#x7pp=DgY2!)S7(KZZ$H3OtG1L)}x8k@W03~L(IsUX8gVJQ^~U-X>XdsG?lPsJ$X5wG$RN@ zks9-@?PLiV8Xz-A4P8K1e3L^KG9RnAo)(P%HE4!=%vfg$R*DYfBoE_AF&EZL8fzOn z!{+LYohK%K9Xk0-zbT(O>woU7`;pb`4|f@Uy4&c}os0j~MMj_Q#uLNOb{c-R-SFSP z7=89@uUrIUUc~EcZ1CXW%>Ual{ht;{ZuSrUTHgkZ`NDtl4+nAL23YDP^9VMABN}I; z7{y6`gOh||%o+B-ee88OR+U;K-|L}VJ}1XpLB&dV)#MuV|sBd z=g4Q~ycn_K_U+rKROm{h@?g{N>V}rWCbjKp<&51Y$JhymI>_I(jGX9Fbg>)mf;&`{chIPDRS^7Tl>opSr!i_A&MVCw*#y)E&&HZGSAU zo=A;gr~`Nh>-3cO>b*`zV}mbkPQ)lD5%3WoOAd5N9q61g&`vVKK`@pRHPQA8h|F7Y zFfJ|a>yXmNDY>7cXn<4vKnKAfd&yus`4FxgEqau#V1jkzn5}#De)9X;^H`)jGyi5m zVQOMkUS?}!6G<0i^!OM7%c9%KmUpcURaoCv)6#xcm_F+>tFc@BwK=hqJ#t>#&WEvz znGQ6ZQMRJdHpIm(tcU@Qg1*lDKCba^yTtZ$jve3>J=ig7h(pvc`{;hwH~Kp#_Hj&k z-9CAMoeUeGeHa{jMpoA1H7=f%B?4<|F6AF_e3tWtH(@9%E z5-xz0=0%k!0zf^|!Emas5yNx!HZT_r;g%vxp^X!HE z(hEPqgE{~tMRCA3>rupP9$zGlXP@I0_APi2Eh480fh$NDE}J?P__G|cPiO(5M8Fuf z+`{h6q)&~llkiy|huxsW(2hlj|Gc&fj?~Rn^J*>J{*V+Pu3nvZMtItTY zXZ_+n*5daOb_oP`I8ur}&{5CGidEwbrgNnOt%Vc3vfj3mqO&>K?7a5(0l)5zj7WQ! zQ>VV)sIF~!glR!?QpzJ7#YD=f+oEOa2)%i!iyv8nvc>dt!y|RYV|C2UYLj1mj5#N? z&3+qhc6q3SY_MC_Yv^RzONZDIw%G!O9FUQb4ssYFq`PD%8D%fUqTdl#v6Hr)`oiW?^y)IDKt zr10i-!Oa^9`O*CR82(MT@sj(O<8NP(6bD}|n7PGU`@8V@oNHP(*T>odrsGF(VnN6b zlOy8CLsXtFq-O9Mc?3ee%M>Kv%gZZlsl)0l?8Jp41$AP+ z05&p+npL#Om@;O1vdla+mK5Ub3Y@5Nt4$pkoo)D&&y*j6M_XMT?kvO11r}hu>zdNf zPKxia#<@twa;}djFnwhlkeVBh8RUKriG3ZFK+J)T@q@aMS^`mzw&hQI`VbExr?%lvYM)v#wzT?1}(~TCkQ89Vjpab5bF;foVzS;}CQJVxjAVoH5O_nH=lx_IIHfh2wEyx|1p?Rc!mN)j6^&p|Y z7pYM+xG0AxU&t1jWwZHQ56v&C9R(wu_@L1a{IT|e@f^`4u51cdKG{w_fh)u~=SaJl@!Uu~>kIRC9@hTQ`i$cK zkxOxrG5pNT?7X~NIr(=p3m&Ewl!Gz~igRu~xOMXmEO|_K<`&%TB_VKre*Ufe+t~$$ znYT;Q?o@!X3QBVGiyju0B_*ci78ELTi(>NX*O`aw{unaT_QGiHHJI@u?ZC5eqMZaZ zfg>1e8$Z?|ZnR^}D95-_j(p^9w7qmJS22MjpX|V&<|Y~9ARgu*n&Ql#w)^=?vQ#t*=9Q zM`FSc|1Og!R#ueN*HyK&wL+s7b*jT+Gq#_Qns`J{vA#CSCJtGKz(?7}Ot2?3&K}i9 zfQmHIkyNMA_QJ8;1jq`~9?ykoB$(hR8|S2$U?-Sveqrv8Lx$gb23%4^D|3?4vvYFt zURC`;%_+E*kB^1(@(WRIG7Bm|Sp{Xe`Najd3v+MXN2R(bxw*ydl+HIkusQWyMB{9Q zBW;9ZZTOSy5~kVlr*LB?*xne=VRD2FcISvxA(BDCC|B_)C*fFozK&z;9PXtx4!>W^ zZIR^^7Zw&_9ksf#gq%J4gqUIIFrwWxcRa>N7bq_fQJ1*LoCSuwS{myrG4zcRbcjgP z*?Dl5w;Z+sn&EIKkZ>3wFeHQMCTLfKjnmQ(`7keU8BHv=e8?KNcUO(Kik#*snBX8D>nO$S(r6dKXqPz9SSS7jpqQOhi>uJ)sNhbv7f)~$ zjCGEk>=+4f1VsMR{?J)TcC0{>kt~0hpHW{{2!>0m>WZpc3#;3UtC}h*YwOEPu~MtL zs>>XuOupPj;JV7<+N$F6>Kc58Sy+pe*d1k6&8T`!0FIIe&^E%;WQx6Ps=aJ7SA;xHaEt@PWAGEnkq9_D!7gc%of5O#Q{Cc5+9!-~ z5KVHCVTI}%mrG$cva;_yY_2J5uPW+jZMa+8zH?8+)OU(Dbh-Y` z$<$y)Wz>Vtq>4xP8Xr}*wAHoX=ux85pG(+N8r0bK1cdpFZhG9(@wm3N<6(XKy=L{@ zC*^44bd0m$Pmq%c zBR}JK3UvRcxhtn|qvzUP*7@3V`FHkC;U~~Sb91sPOCPp2Hng?0W3Q1v+6>S`3{o@j zS5?<|rv&F}s8zQsKilQ9=|`@?SC0DTCv=?R#ycd8c9M_erNjIi>5_;Y$YFzN*+);e zy9%0SAB|SP6ulJBNud+ziBJ`#TRx9 z5fTH_U8m1Y;j)MEQaXkpmsj z0jICLJbq0LjI{6;paDqt+_+x?2Y`$ozv330ASz@N(IRq|6E;)N%{79dHNge{U$m7c`D9R)|@qu_W z4S?q+t@)739~g~}IV}Rn6Kv3nmIdolmT*fwFLG)4E~I9*Jt3cJ;`|z%S^T6Kz+LoM z?Gc%?*#5k}W9(FCF*L1?N8%)IoVK%Qva<{Z^8{D%c%BezY(NuSg_E77T26`Dj>$Uq z$yyFc)0|{eTqRT71UkGMGp$bRf9vCMG4Z@8Ejc}-^nQMIQ9e$%z_KP7<>(`Tu&NW| z?rMC8-rkC%mmr^BUI>i+s~R42tWM+LZ@>MWh?BAn!!FoDOPz{9W7NzSUtPRUc9R6uGS4?czy zM8VX_O7M*IpSF~LPO(Mb+Jn3?1xo#Y^zY!|QX5Hr)^`t)5V7TTOx zV}JaoJ&~sp3)5=UHyhMBRUL4jONE_k9CwI<1Hp5@Lw&DZeWz8OTc>{TSe@UYzK~V7 z>zHVb<7q?A@2~`P9ip^hMK}q7iGb1ZgydsgrK8=YW8B1$hK^H$o;^sYOjV>|l(tKqQps<=iYUEhD3CosR)GIDKrvHvgHH$B~K-Pl5p% z7&%C2GV?AYiiAlnV#s;CE2&PCTp)k(H0OkAj{K<(@mek-ZJunry=aX26}{c34Yq~a z9*w`AbnEVeqK3+1?7#7<>JQnR97~Hk$zDvD7l73Y!lVXzwb&*OiodVX%#TbkUI44XrKdbfA9<9%~mSJaq zkC9~N-YPD<+d_`f#78=$Q~x5QMkfWoLRY}Nxl`RC$t^w}ojCvB7BhYdo#Pxm&L(oI zn{te6GQJd>?Sd(Hh>_H^X-=e3;0dV@u2M9UxgPOTe?73? z<+S@{WpYtt&fVhnR?Lsr!d$`jZ0aXiZHYY}FlmksFHBd)wqcMOEJ23M$1K#OCAfp~ z1qOjCc*$;5D6RSb3JULtmkh>YH)(`)#QiH4ztCL z4B`T6zXYkNaA-(~g5ovm45GqCQM*S0Aw^txNF@*L2La+m+J9%Ijo2V$+@dbwf(K!6 zQOUExp6j9fP^5-2M;aqGtU#TA+=L-kD1^KQH5MVyv;1w2s}MR9T`FyN71YsmSBaLZ zdyIjjdr0*6zbLYV|mix}A9>k^G z%DZ*5p|YsCvXC4P!F-&8)R7z-7pZeZHK3ln%%Xdy@*ptcz$qf+A0kC;#G=OPmqzR! z-14NEY(!Irt;-*&e+Y@3xpTh`FKVKPaH^YZs;gp}vyvDX&MIx5Vk%EO#SM88z@5sI z;#V!_6#S&+9H-|knd~Va@21r9N}cX3m~V6LJ%=L^vfR5xCFqm^uZ!y1@|x7|+3lab ztd6rn$5pB2EQ9{Rhoag%$rM)+;_oIzE(c*!55m-Ol>y79^N2^=MGBCD;+pOh zx7bH);wvz6xU|6Hu&MotkG#%(6?l2u-YDmb$qc3TaBY8+b56@RrxkFmPf9J033eUg z?>G?msrwmI%l!sF2N~`@VB#FH(lgG`End$dM%Pt{bio_ScbXd^_@}x{CU}TJQ+Yxi z7oonBSl3AkAxz?7d|oxiJ8hg#@)*Z>9lOY-F4w1h?rnV_fiKTdN)&f)km=*s5?Zx;~%I?Rl&@| zuBg}-to_N|cJ=ms*JuA6GJV%6Q~+&P<#e7>+gYOHD4gLU)O8i<0EU1sq-h{83RE6a zzJ$b6oa3js3ILHayc1!EXj@!Z?{;mYdB|_ks{A_-8Y)WF&9#{MCF+ixV27Q@(DrF7 zAOOwOW%6ZxMVmUMv}H&5<(1r{i(IdbvxxxOPWDMhLZ~*qBru7FIl(z$x|agh<5Zi7 z(cgz@f9<*1CggZra#HT?l9H0Ts&aBPC$rG4gE8a54Vouup-d|!jTC2iwUTKvw6&_n zb}UOMtbdYQ-sW>or2m7Dp4DlrbJO=i;i|9~!9>ptjMzXdkcN({fRGD5pcbRh!94sk zTp&`SLr@dY`-Y2_GRs|neG!-0o&Klm$?)jZQ?W`MV}0*oSwl-}OItHp*oJvJtg`9u zR)Z6$5lWQd?!hM_LugubGpXKtu1aJdvY-YJRqxQKP{N4hKVHz-(A5+m*a&-g5G{M* zCnN#w4G;l)P{>G#LN-N#m$)o52t$zqNn^70**re`M3W`_3Vr|_KqbV(rpU(M!-D|y z3G4aWksADf2V5+x;EmYcZEX+;1w>>MxkgSk^Zu+K!B8A*V7!acgm6$ghzb&hlu$;9 z86Mo?LaE_b7M<}fE&|Daj0Z`hlyOl}<3+rJkk9g<`GkqAYwb6!)npUMM=g)B*+6>> zlqdT^;hv`LlB(qhbW73U zsiwOtblgQ4!qWS}4?WO`q`TO9t04boJ30~Q6X8hBNBH=IED~n46X`xMJMhC)Ce~3e zF9c?+Ytkb}TS8QDv6_}FR7DpA`~0_}oAMZIsP46^k0~GMeCwg>9054ia+hiWd0kY~ zoD;QO6SdtFNiN*FG6l@iaaHKJBu;lx=(-E_eWcU8loLG?r+KI9c`D}HUo){fOlUtGbvy43!{ zQipTTy2~6dEqA^MEH-huwA|@3!WePRF0?&kXm@#u>x~sYlI4D~xi0)E_!tKR?4F5) zF?Ts!;Nx^R@eDVS9#1gcT`<{0G|5w>?It4ZxyT@aX|BnW+)^iaWsG!Hj7NB$aJEB) zk@bn0TX_2;)1->@45jMf-TV0J7FbiR#_&bEiADHQ$BXD&X*&ym(UV=}ObwCgdPsG6 zA`m1DIY1f=DbfGJpbe=rFj`ziv)!d2ZBESO?WgAb685pf!KjRf>Gw)%swzy*qMWSmTyU0Fb+3vmGX9O6QDX*yMY(aL~ z$xsr2hHmx_fF|cgVeppBmo;~&%bDHed~akg*dAu+aB-n0e~eWG<{)70AZZj+FKN1~ z45lDv8RmFNXS>Es*?xG!7Pmz|xO@H1k4enVzxSZJs;s3RgHb>{bvss;z8I;&8+N&A z$C_*gA8(h`;%kMBD)maUVC^6M4IC~k@J!J4kk9bToZyx+(LHsNTQW)++5<8nVqr`~ z+`?i+6Mz`uCu3Ibi6GPpJrBtuFQGB-n&Iw!-}qnp(eqezMsZeAT~%{OQyUq1BMlz~ zM8KL98X7(21guk?M*eqO{(wJdU396SKcNXoh3P`fkOxfazOTR zffLBK2Yc)-%OsT^p5qk&E1uJfhNQnDPR(2R5r#>mt9Et2)MXyvExdx*5C(M#(gxf^ z>@<>>xHKLrF{XxLppER9)Y;L3dS23@J|w)k%;La8$IC!!=ufJDfFS7UKus|uf>zg| z;;If2z<>I#97>#S}P4i-k)fz#kT00jWvPs1xIvx2oGj_nY*-u+!t7)pCuU z;Vwa64;BRj)5+64lL1&TEs!bD44!xfPddX@IfEzH^APEJil%xhCV8qRdnHfzQq6ab zU1ED`*S^S@^!pXfoh6kur8Q0Ws+uC?S$ZG*VqkW{z$tE#hh#2KqQ?{Kd8o8Klh93= z?2$CZJ!zV|3iwD=Jx{FfDw^dgnB^Ql(>X@pIZmG^KwlDao8bW%RqA@D>J!~gG@C(S z>O#LHJ*RkW+sJvY@$+0`pLO-^qcCPZ+bL$QOAP&Wu1nl(7yd$T6>Ns74hiU@lF@j; zhewj0Upmw#gDHq#qzhBQHGZZ`tS&DWBO%i~#5(Sb1bFi4Jk>O}l*#UCSiC*T3Gga0 z@DVO?zF_c6pvjMJr=ye8Q?qWRCYKf#Hn!laZ*{R+eNb7v(($*2&XKw?J}fxWsJW!FmxwEMQ*OCIa6e8+`9+9&$E5^L{QioT(|t z&T#5ZoJG}j*3v7eKY(bW&q?af)w4g{J?S$?U90mD z*KEwx^DwU=0vMr)!8v-_48bEuwIP*<)E_BY0qV~rXMv7a(i9ijEDzaS`^aUS)8+@` zZlphaP>D~02q-fz;cV9J?YwP2-*6MrP{kQsk2$D}-%4zuh)%~<`e2o!%D9bp+ z4boDOwaL?sjRwxo_5*j)x?R0kP0GNWqKz0IV zu1K^gtDvWk6&$YPFv&64PDkiogG<6WQ3&ZHF@7qc6-cC+dlp70e@(JI+?@wQu@ww> zFj*^YV}@#*UTw=I?rh4ykQQmTShsPL=42K8n`O6DDlVy(9?_NOZj+9^D*S2J2rbv_ z$~y?l8@mz@J;w5%5C7z_uO762W^l?UKi74h*a=+}hB`St(FQHVQQPV`{JI1AV6v4} z*=D#0FQ4TeqgNP(nv?>n9;q0EA_|?vEKNy}M`xEKoqq0j`nBvc>6V^iCui>$&)rHd zT}uW;=U<9(PmC_p@?Mgx(z-+5o!ERu6+>(4+FR=`SLsrox!2w%*4stDE`JP}ukiN7 zu;qvvkE%Q+RA2mVwr}qYuV2U3JM&Obue~m;_okC$5u=dMZU4eLon)zZjLo}zEgf0~ z5MgATmTT*!>+98J%pHL)5?*NJ+h+l-3a%_-(uuE87_Rci?+gqOs#*mPWDs!pLZ6Rt z95UBULiDN{g^UF6nYvR4RA_FF&1W$Umt~C0EC{iK-A6`&}m)ax^VQ;Gty-kBn?t4xy+vvV_Y#X*yI6EgSW(Pm#A*yvAheKKson6LGvIQoN!tx%6j0$$wjTgZR6)9&S>`lh9E7s%WaK?!JL#K?o7QBZ_;Gf>yU+ zG>|KT?yRx2=+@Qq6LLKz4ZDIAXk)17>+WSTDv{w;h3>Pcl|`mTtuk7Jko@bETEGAj zn7i^&2BlYy-5walUAv!DHzQ-Uhxu!Y!mjx?q&loP6@JaBf-sql`E+V*0fa1+9kD2s zOQh9nUet<2!i+lLw~7c2Sb07|`P2_}nmGzp4iZLIcAW~{e4u_sNRF@0PlKkByPGFV zYM3B02PKPMx>tOKqi~u8-;0nO9T$ynOgxi*p+oxP`yWF(ATVc z0LXn~&evk7CVMZ&1n;R(`}`&iSudEi0t(~f-Et~S#fY|zP1BPFY`;QKyzqJV5gLTx z9wi$!pFcy+{O&1A;{lyspICgx^HrEXfk8({aier~Opk6)pVy_;vdn}Js$}W3Of!H} zW(!YCm3>|&)Lw+qg?(9ucUeXfRsp8_sYw3udl|i3m=?oJ}y@4zYxVR$}N1U}T17o#Kv-Ys3$X%XgW39e-h&lUwZuld_R=R=4? zf4-TwxXxA3bPeCw1!8mEEfc=2J;IABe^#GQRiBO!x(L@Xo)(=Xc9Jk z+F#<#!=MT(GM`BV-mgJ%!f1+XH!+INS~?6?mtc@i_Wx7G4`<| zzhl2woFb{*rcsNWB9;4>NtbbH;4jZ@E`{6bURSTjOV0WVJ!EAQ!)KBH{DBIR#CUG@ zN-lB}>{(mHl~eId=oE^6%ctthmvGR3kII0cYJ>nS7R3KIaHbPS9t=%?4D}SPTd94Q z=bM=8Io(PG6k6?`3N39Zne`a9cQV2;#&UDG-7=v<yo#}fyaq$|00CbQGIhVETnY|7v!e=yAU5M z^-ocy`BdDwBGUu`GbUJ^@FV^ZG;zo$vn3tF#H5=MtJcKjRA2Mf+3Qj2W%v~b8z~2F z_4cDD6RTH~0dm)A9@zCj9PF;7nI*-oEBu~>l-+E^S2th5P)CdJp%DmKh3a1MQ}?mZ zko~Wdo~GZhCjz@k67{jUz1PPP{6B?Yk>znhz;wS6eE~lueY+3uPAK7DxKr7Hp_6e$ zZuPgZ@J8M8>&TmtOlLwX$#ArKv3#4kz3Zp*6?3w|=Iv8x!jtq4yh|pe@2|Vubv239 zW7Pnj;TowKT;UzTU0a-Z~=T%&Z(hB!dzU(05gg5mK4N+6vkA5mB$b;BcyLN@!K z`JD=`f|w6N_dp0RLre@s-HUsE`#T#>xo^JKNTI1(9w8fc7c}P|z{W(392%J5AiXdb z9XH+;bX?yYB8(=AOP5!M?hvKy3*H;5=E`=&8xBU6q%_^6aBW?ww@cK(Cg6HS9=v`B zt3G%##}3{5eXB&=2qH(Sz_cE+X#{S+mxSEF`v=H1!2vstNgr&mH^kxE^J4#5X|6Ic z*eYEw$8m=21TfGn{uDcILaGM-A=IAYYwTyU3Yd>x^mb+xg&oa2O|567w04vn-t{LF zAsQ2Y^Z@6m!cU~Xi4Q{XNrvi_GqRp9dw4u7VyjPV<<0=ZhJ!Rli*{;JJB zlB*0yl6#uVIxXOs(=*qrV7E=dc83;p;1OwN81Ur_19ImW8BKi!QK@u@77P57RuN}2 z-^5C?(4xBcE*|*M$z_I7`-T%<4&U zBm0WN;Pg+20};mx1M{^z0E}p!!Gd) zt8S{>&P0UHq^KEa2wbmmEHA2Woe2ltl`}M=Vu4)28HIV7+(@#CW zSw5a#p@_1`r-!PoNRjGAS&or`da`#nWS5$?^|UZBK$vmjkS63!(L&(c zdd#pi^NLuCrEB_(G|VH#J7Po)|Fb=wOH8zAqxW#c1+PQhAJv$a770ppop4qlrpDx z#Bk`%V6DHTg*?Qtw!_z;UK5h@j!^=iM7>#Dfp-ls+lE|R@falmliO{NeChERb!&=; zpda*i=@YQ_0O(Tst@pnHg1G!{0vV6-stzy3PO$2y8^S=6MDEO$@JIPE;NRj9baW`e z#I>fGe6Qx6YYD{$LJdiS<1B@d*|>+cp@+fu;pnUJJSru4&*-A#Hc1#gy9o5dcte$t zDw(c*qwC6iq8{6$?NVjCc7OT|M!l(~5wl%UKzx!23<>+K_JhElJr{QiLui~tF*1Yu zC3nXPe+{f9wR4=j#`UcZ)%Jn;&$H1f-oCLauS~ zr_`TVupc4QmhNv(Ncm1_Q+M;?NmJtp3B{o#uJ4!y0tY|X!NkMgXoL~ zxbVSoljQu=#zd=5_7U~5Ca@hHzRU@lp$K5;x8SP&bTh(!kPSWkEC+nK))(>VVSncn zZ==R(D!5N7>kxIc6vwzwgOFs*eUCeacd{aG)zFZ3PG($4^(~whdEK9R-Eo>)>w9cW z>*iQl9qW76M+M>&3ag!3$D5#8x%GI#atgf-ThOd7*8M649Z~1-Y@_zsB zNKai=*Ssq$X=slAkwspq=-0>r%4VL=Xq7u?+O4b+QE7wtNo0QcaT;N64}&pgi4-MM-;kV+2gwamvV$rUyOiCd?6(pr zL4&9=ja_u11&i3(4|gQ-)X`Q{!(UoqxtwnuYL<`pW{=$=fdffCbuANo9kfYQE`V** zH_k`Iv|h{~Db_6o*haYthhk;`c)A&I!w~ZJk-Rja@EaE;sF>kp*%R*lOTM zyhtldByFGOf#`Yg#OKG;Z+L>{vrSjWVkP)2JRJ&q#8Y^B}PMlZ; z9;wXRu?2{hpko((9}-&d)fAZ@IFL{p^Zet3#PG6acYIN|Pme+aju8c>{54CTgdYvH z#*RZYc1`cGNoQEYbqNnH$NO1vEt7qj%RepPZ0OKp=ul$l(4pk8HkU{C7cg`KcwX~w zs|6!{7&eK7s~~KNi@rX^!y7FFAUHV%AI(!C*uV)zC7g&0qN0CKqEPd{s-vzCgI>c^ z$TQa5h{9T}QA|bfdPK^=Vc2zzgj97^DH42Z8wzRCP(YH`+o8J=o)^`eOYmd|l(}P+m*^}-EkJ{Vs zX7f`j1EaAlS*ugmD?zEfYD!ek%Ww9eJm2h>V=h057NjjEcTr<=^|hhx?czd0v9=G; zNxu3~fe}_68?v;DGcC5B^KWkw#)nkNMr)WK^q*(Y~#~-4iz&Vha z+Ut&w$sCO+A7G)XC;2|xxofg*wCj=9@P3M)8Qv4pgh5d420Lfga~Q)`xVNXX#dt=Z zNg_yceUDLl52_X10|Mp)2wHSt0u>#s?C|*TJ!<&J>NUzYx*1vgpdY8j9&k+G+4Xg0ySMx`*jS^kVm zWm)Glulv|tt@|3WR!$EqI*TFWLN2U0jBt03&$CRxf}sS|h!wvn3InuAJpUZvZUI0B zLxyf^WF*^QB>T3?aWD7O`#9VRnriGs-FOLPk}1=^#$a)R$;9FD*sSr{b>{x~UUe3}JqS4j{$g&?Js&;Z<8e2Qo( zP$dkA()vfKzmXA)=Y;%)jP@v)t|MMcm-nmtfDa?4#)bX~B_r5FU|}=VX|bVUYZ%-4 z(8}|A2v#VSu=;z3$t>RxeBgCn8D4T!jc5h)fKlk6sYliGHJGX-=kq&Uizf_5#|nI< zN&%j5+&1)ath=CiO*E5WHR59r;}hMZULRjEe^~9eaaN(Fg%RTrOvL2AONPQlVzBuZ zV7(Tl60!@A=1OP6!O=quz4VF1qI(a<>aT({DSVS@D{dzE6T7GG`s391X@rkssXc2e z9P^w3vWn3wv<#P(oKh`Pf4I*=e+E^QD&Ptqru#{?;(0<8I_auS1$i!HC`-0rZ0F>&c18F#GJQxe&9Y|(Ta zG&w(PFdlN=>znOTflx3%!HT|nH>QM^&>_ic?bm9Z(&!)3=nhaKn>ahdTxkiNKko}E zCjywlJwTWOlvM;i#HYg*HslH0<5jQf8fvN_@Cf-SYlm=@af&Bz`cv$6kQhE^t(%|o z{h)7_e@WEd?~)#{^;IkqOO@nHRSKg5Au4|csiX!M^|K+$L(##@v%*RTYl(0SvMQS4 zQfd-VYT^M3nz$94m?fdW3saj&!iNFh=ccWG1#D@%+rIx(17WWAf_rlT2T%cHd!Ib+>h?(ZVXKKv_=P!fED!-%e_-)a8 z_Qs~pDsF0j4ySfX*u9s%bhUdJzM(-t1sux=v&8dgR9nA8=COSUV|$OH-^lzy^v7ry z-!#PO_Y#U09{xl@ZXCOqky_Oi)046lc}+C?@v#M#L{*`JrCRx@C-V~MzI*F$efd08 zBf^KE47y7-!vaR84q9cpAnt$PXo6ayg_06ZqIbpsO7|_P?@sF&qw9*NHFq6}C{~%$ z`C_vRxT2wwZ&z+xOGEJ&V*`BjC*MM|S#a_*k(kV%>qhz(byCub4=|9sRH#ddo8nFlvB#@%MOBiO5uw@z{$$yN~?G{N+?y@-r5R$JL ztRWub4uFdkw5A^;hGCVb-UD)a9CJD{YXz=}5JV8;plle?K}|v`@zT9NN_!qQ#X^J( z7FY+j{;Kd$dose!=5r#Sk&DTy6oGccWgx(}8uk$1L2R`mK9?Sfxs+|eD?lhCkHY+j z#PvrwdNw6yMn;BMso%^+<`z(awh&X!yxsh76g;TMGgw@v6U{}j;UtE7xTwsjb50<%&R-4M|dJO!%SAT1J*|PiF(KRNv-Dh?(pmH`Z%9^ zj|#05L>^-HH)u6OqwTrq@B7Kb5tWaowD3kC+(%U6Drsi%8G&rU3b2x0B$Bh%B;-S= zDHf`eK8Vl`;x1LBcRqfeOD1v9a993~OAk)iphWkzcOnJ{{6eTMMh%`3kwQm&g+u zG{PqlY5R@xUR0I|C|F}f#Fa-Dg(h@}(jeIhBIp^bk?`Z#SDdK6X0_Lw&|J=61%ES4 zQ;~#_H9o>?7l~RqBI=nHaMKk8gM(j$;u><6{!JIp2-B~RM&`98U{?5-=~9N;QGV>a z;G`uqQzM>aTNG`1vEsD(omOfqkOsO0EL|ZtQ^jvUP5$2 zYMqewI*h+`je!i3XR&A)BfGKdW%%;&otk}n(CzEPTJg=w;+6}J{5{uhnP460jXdN` zum1KF{jw_P0sUNNZB=D`I@%3P(p3IzKFvwy0q5}2(LJZoz{s*eP3UH(giS#(z!fKe z7}6*jjWTitAuqP{Px##eQ7Kp{EEt(wrj*aD(!{y-g!H3O;DIxi>${qg%35|p|4qf( z3-{TN@rzV>S81e=e2UpO%hYFbY19ndufHZqWcPym4eh60&|^Du2nx%=)(?eL)SaTb zpY8&)v@<()d+1bPoRk8+Fq4(gVHxY)qp{1!3RTeYZ_^}fX(lY2q!J$TlN4IytYUIX z32aVBwn)InGp{!Ya1iXt@i4hmpTMGk1<81ImdPSbf#}3dH_~QYcr6FF0Vbh`o^{_> zN`RM$zlDg$_(`3~e4T2WwQ%B67&Uw7sNiY83C$y=;FS$rN*58Cj{wXxM&;K|l2_E! zOJD|JQuVj!XG(z41|kvsgy`2|74K0=cAnTQEWW4Ijf*c3H@x)vTt$cdu)}4;EFE!V8dMfYVi&$k#iSLbq!Z!q0dX2VVbM;n3+?)tBy7s4Bsk;y-4HHC zy@2!}x2Yc(kTVsE+~>VBd+IYq+YF;|_09eIP`&cg7SjPhqL&b|Azycu_t#OzR)nh~ zgYz7>G(A^=>NC#$V<0XV>49a&|jqa^%sl!5*{ptfHJ4b}+~ zOO5<@?O%*h>cBR^T#6OwOC=R;Z_)$9=_qBnZuci%PTUy;Jp0Lfu*ABbY=#wb#G^`Y z(0z`XBB)DY(n_}Kq4SucxF~CqSRph^!DE0dBrqd^>n zw@<|OgqQT!5I?A^W$17YqEQ`;l(q~{Yo9c12H_lwgm5$`k<%a$4#-Crxh}}dFse^` z`|$(h=L2N&b<@tY=Rc1=Mi^J#Nn})fk7jn8g~PbAdQEDn4V9y1!SSZd$1=2}Gep~= z>>MY|M*01oYk{X3j3Y5Su~Q9^b77|YYUfsVD`R5XRUbRPzKQy8p)-T7-pos(#d)y) z=a2n+ry@!(aN+}kV`c1+?z3wkcaY((aNhQ&aTa2XFqjQ6) z4Hp~qHNC^8MWKuvp5quUa8V0Yp`uu*(nz@2R&i<(e7uS|y_{_@L2-(I{qrxRZ&E)* z1VjQvq6^KVM-8C>#5z~oCw;?yKJZg0c*85lj64ng=;igGTy@KS*=U1;Tc&)Y%b)zp zK~g%~=^d=_S3%CB(8_`99}7e1TB%|Zr?8P2SODzeDk{AU${Y*npCtD( z^mpzt3-s**^2dBvck{|HHnBGU66im&Fub)sK`6ZhK_i`7(P)pYMnjb3!y0$*3ZT+}-EGsz&^J!AgfRjSe4~QQ{&ij^$tPW(QR=)IYN^G4Xu_(T!n(yWO z3$nv3+vY8^>?O_a5zg)bqwalcDgO;zEb6^@*cWxZ<{@Hz+s8C}+SEh+X^8$ozV|kH z^ZImy#9>J}`0U`^o7|*_Dr@skFbftT=)?st<%FMxyPVf8p54)neO9#Z72BGlL-{-T z-S?$S8GUEKh>Jd^0X*`sBC1R6ccvLA?}#*6khW6v9O<09DP5GDDP&lr${<`q2N%J{RN!Jycz+W zOFUjdKr$E%%aB+LO+k{-Zn^jUi8gbNG{{%N0f~hKp7vv;i~Z##RRdX!@;v*Xbk!uP zx1xr)20zIAuyQL_LZ~XXxC|03PE@pF!=Z-1?*af zkr>CV7VFE&1zvUDM!!%xK_UXI@ol)O1O}r@x|OVbYN~I$p=R@?5?YQ)bUNIo<;0`dT06jEy2r-un0rlhtk6IS80qhJuK&Kt@DdX53o|3cvwirR zX>kPi10yhYLEQ^}c6=#6^*pErD%B$ni+7L=#iEcXR3{iaTLVuLx`8nz8Kh{q171b{ z`n9{B=z8i&FX@%ACo4@wabsrvXIDB=eBl?Q@L&)VC^M~~I@*qrlVA%*2)7R`qB26r zoH%1IcgN1zFV@h{wPIX6EBqt>G*Dzl@HqT5AtwgIMer0aiiSXiy$bo5zGuCeGA8hnYZxx zXV5I>&V?Tg7WL11;1l2g(kP$dUytc$Ypphq-Nk0m2y}?Q*9h$P98~RpJqGIYEuGzY zTvFKmWaZ#_6tcARR59i|D4i|HH=y!&JI|2B#mGP>XLt6Snx{htVG@xQ5oH&xwWoHSMUAP2WgJ8c)JxEGfU?-k3{!3sAWl&Fcz7~f%~2v`nSyk^Us0O;BqFZ z)~ANwNlk&??lKPJsPe>B<#b{SXx{xxExWA6C$0jVHES2GHs(i8mEaS!k9e6O3@q@v zW|#=^A+3N6#49$zKgh4^2U1 zoX0At80bA6YV*4>yL1+aIv#0f(0oe-^)27?D^uBC7RqXp6tgW}IN_nxj?EmKZv$?J zx43X@kys9LhNt%6KlHuLKlIe%53WB=a-J=7d=HM(57S31v9L|Q!2+mbc}7VB0RS1W z@ZGk67LqjpC`O&_IgYo=pLk5+WZ-ZD0mc^;Se_h=zM4E1@ge`}Z9X91GQ5F7D%GpTs3U zW}giSN1CrO!4Hw;-KoA}Y~C&1-j06t>LW=^`+Mz+$L0(+15c)He#fc@~51T|Ge;#_$`H)JcA)cBx-(vJmvQrzV8eQwK) zLNX}TvrvI%SpuO^P7^DftRv}7MTRj!UoH3(5P%6>LQ_g!47>!PQ-U8Ec0A@Ca)cye zYWZ;#HQt||myem7$xGf&i^((c>&8^O7|qVv8(5|&G&5Q~`^R~#>VXkjEv#QNhY^XW ztu}v~hE54HT8+lvFm9JSKRz~V6Xf@nS+AO(?ZjypqKD!18}$PgFQ4OYH-I0xg?IWg zizqU6Rw+I~%WL%d6JMZx^lXRiPpvsRufrnKHKLPgA=mZrwD!m3(sJ7PvANxpn{)1R zXZ?#Q`UBJHGWvbf8cB?{o8#>aResJRId_TA8$LlN+7uPB%4m>hhO-m%>I8hLS{+f; zPe0t|XV)8IyZN8)UfjR)wj1rvS5nk^c#j__5PAKrw7mTAT#D(LUUfa19W-`+AQR}M z*pHuXF!RgdbKWXXe|6q{$W3nZK5~r75PUm`U+x*7zWYPza zQC#$nwY{%8zA_VT<}!KP-~8SPGo$!mHNV_h&3)svebq1R_5_&SLnmU|bbdx8*UPZi zc)CxUZxQk*Wv8lXD66XLYN{>c0VR1k18A1GzII}csP?p4JiWYl<~|nP9O^hIQNL%W zbPu)@Ktk60qGoS!L*c86D>+~)nu}f?8I46w)_SE}aM!e0X)Clo^zD$KhRC3sRdp(zo=&kf-WB=Mq zwqzeXqf;Clx5aK1{4%$zokI>;A2+q%ovDYk8=`NsSR53cJ)cMdC0`+^lyp^~E38ri z7d`H;!aEog<>u)fC%%CXrkcH@$?6DSxEWHE6lr&Lu@PQMyneKieM}xJ&_`vrp3IWN zHey!Acs~?NW=7#2qQF$>^KPIJ*}SCi?1E0X)}L0JkOgRAokZCU|Zy&R|+#$#D{1cztcDgkOk&4eL+(S^+$t z0BT-reNAb+-!05cQ=6WSP>s#ZPKu6B`$ZG9xC{C?5%}@&!^9!A)h)g1L8|%zdJ1{& z=rh;(Ui=-})Rm;w!%h>exd-Py#B;1^7Qfq@s`OHNRiju)FYs^^ zN$_rhOu7a_qorIb)=-+%46U#8-!jxzd7bl+#akaqO|Bz3hfB84ts}sgPGr`FS1t$`=&8|hCYBJe~q zzq7K__*t09?cAN#YYH8CVt>DF^raKMb6Sr)s%(95yZs?D?|O7S(|#pdf4c5r@OjV8 z)p%EMgwOTzoEV?fZawF{>hb&JdUsJ0lDco7gX0ffSt-K2)CdK#PRb}-iO@B_hcml+ zF11?M9T`oQ|7cFvcvyv(U{UBOJmk%AtN>7*-sSIA1xX!mdv-U(SPya(cIlq|+^F^5 z&NE&J|0B{yG3VRy8kQCms636S|C?7g&6hitT`)Tvx4o2%Xu5cx%=BO;(jv^%RSw~> zB4dqr6Ew$Rn{W@2J4c1gv#oT!m@Ag#xim?3u01uvd0JUo%ocpwyD^X|h-ksRw9(;O z2`uEUT9bBH(d}}-?;+-*<)Nm)ncVVN6DNIjq*1=O$n1NmNfE*Hfn{*sdxQ$9@|Vkz zw(@dwdzdYhP*GNfgM(vcVNuB91eF+22R$FuWs@a-A(s!{*yhAfyGj&AT%9H-%vP5W zQpUvSB^g%2vBFqzgpnX*mM{|#cW|7fDhvc!jym8*m5|{cVBB$Za>}Pl9T`iDKiEfB z0NNW{19fG1Dl4DK_kSFJ2%E|s?X=HP-{@CaR+ZUT)YuEjSGG=jd&Wud-5sf}5$}{8 z;RPVW4F@0Ls%}x7bU97V&rbMmB)d*}4w>d#S2$w=7gK;7NsCLQ`4zLyRA&RkM64kl=Tl0mKRt?%Ab{CFPAxE$Ke}vDvgw#JB6fFlT|clhL&;-{;>Q z=S)$0-rEt)pVuoVuQ?kYpKm}4+8@@tx0mu-Ej}mXvBr9vY__($3r}4ts1Mu&W2dMT z)d~nO&s@d>=JQLJIh|&Qe$`J7{S9049y{mIm_1yM*D0?D_HUE(rx%_-?)jYcGddgw z5;(p>*QF*AHAH>7JUzuqQN$1mWV*I+_B3@gbQeb-x~^cC>bnwjURg&Ann0>Bu}vq| z*J66i`3mNB*5p4K*+O{aFjQjl%2b?I(0gWZ|B4?QGEz_MmefDhUhyacKM$*zaq4)j z^@0x7;$|phU>lKNtR@-!71{_lLEWa0yVf;ocJ>q}S6gh}$D&ED ztuQ^qB{8xPJxG|lIXO9Tn$V1uV_RNiTAUA7p39d~QA%XYzh^NaZItmH%hNVUB2Bv3 zEzrSHSuXhBm_MTbHO4F!1g4s&(5g|M4qc{PWlH)av-m?)2>5#f8m_djVL0 z{}qmX!Fw&sP{!L`MVsRJ8CAkZ1@F2>uf=eW1-M?joZZxM+Ea+9;uFqXsj1sG{A=;Y zM+Ai)_peuL+>C$BEALDBpfd^>+FY+{=6cnV)F$S~_wHDl*_y*s^z`cRR4+dmDGSVp zK}JHYF7P`QmmF%^hCsuD=Yo(1sv-&=zy1fF-dW2U?P%$IZZJs&5MYsu-g zUi%Umy6;ElmW}mSn0+jf1@@mO-bfun;m11eu z$yZvJB$BEWxK~#v|fNV+&@Fo)XyDW)QTrCUxyz%xbEQe@~QV{yhuKY>K zor)jYIuzn`B zpgr?3SdKzvQuAv8K(uBso>6N#KWm82k{Zs%OYH?YW3-T=-UbP|pz?_Tj2R>HfxuR7 zFat%Iz#Wk^p~JEGGgs$H68;f~CmklMQNC!B<7O(yxQG0wA{QE=+Eg????FseoBo?~ zYo}N~l{PuD9-(R`u9PI5$g-*v)KOG<$P$cdrSA-D&Lv5GcKLm~t@1Ikp_MocLTr*Q zyGwPmci!v(kM8+q=tIqLOw3D53hs1qL&r_Q_^oHLn7Q=rbkg>%ll1gn(q0bz7?;|Q z8<*?pbkDFD=&cAm8rh7&B(+U%#GV+sr87?;~^=CyzXk%lm>v5ILCA<3EBcbjp1M=M(}ZEiq8l3`%}dvsKE zAd9d|CT|~Vg<>&q>=uUn9e;4OK2q?eEX$}ilaHUeKRQl35M+Xtxt&fyx{akd2Q<}8~7O`htT^8{v?;bFUcc~D6Jwhnk&PFI!oFYCZFi_Pz zz~}rN3iR%uFM)pZ5TTzJpqR$w8Do5>$%sofbcyrR3vn3=rj^!4VC#QaX688{V5zsJ zfr8rJcz9j+*!5>A%Cm~<>e|X$K3~4hP{~us(9zC!c5Izxq*0;R)Qr5igh)nSVS4YL zyi`GM!r`T<>1UI1`SBQ4dbuS9GqZC;1H6;d)FDO^IwmR=cee9~th}b7uiEvq4Aw*j zHO)!oirfWr3Q)ybf`uk(!{xSu1Idl8I$09&`Yz^Po|hO%gl{46KjtKq@E~%$T^kmOH&^$exNDjRp$gZSV86(2uC(Cxm!*Z>OflW z2sSH7D}fJ9baGd;ytMub2XWwu7`L9L3zb0W1dHSe;ht%}`*wu}qK3pG?6;tic7!5N-W*3M)PKD9GTF_-O=VR!p#RjjhlSKKZJ33cKK#mQ^)eXkw+yl zEEQ}UV+%RySA=0v2I^mL%oJ7>9Lv%3Lbm~IY{BpDiK+~F>8q91r$pH><4)GEY5wl^ zGZ|CCUg8xDhjY0VM|Un>+MT*q^zrn%U4aoK7S8t-cVSLr zKd7}LsjJ^&tgC4WyiD-ZNf6KJ6nE7L+N|2NS8QmLRRJw{FLRNML27f8M?7yjA+9gx{%sqyWWWmV<=AR@5yv~(7(K2yMFsTAbEJNR&<7O zY%n_DX=yQd@-}bK$?@eV@}+BQo$%W7a*UAiC|G)S^3f)=?(%r8b*A!kymoB_=|1J? zcf8g-Fmcpw3aib71*C@1l+kb9n-$!Ne_P}UjXi1suJX0%Rgt`|_8tTg(?k|Up|_D^72`mS)r z3{1)X(gu?(jP_k(FONAh?^q2+kOT!fj5bBxM?Jo~&srCWbh}+#0>{4l0R2sF=K;u= zU>#j3hQiuu8O?ZD8JHzzNf!b@v~g^)eq~Cy^byI)_@Oxpo-79}KCJf`n+|ef0lMi@ zZqKb`ifSBLoyRk1H`Bb_+Vjw(G2UKiji;y0v#17z$+n5WeTTy|#XwcWkr zi#!v$+Gk^xKTribn^ZdoMD~DC?a$09hCxgOs2BtF*VR=l;-P~@la7tbKHpI`lEy1~ zmAAE9NxV(HGBew8wK>;KL-J>IWZRlkQ5%hxxUWSe&2FcW$sQ#j<2cyJx47=e;K~n= z%AWFAA%H5xw)N_*=n4)uqVznORbeI-L9UDUG!N#rVsf~8cm2#PJ&P(>ATnKY`k$uU zn!iFkjDLQ&|IYmtRsn%>lvD!WKrKjMvp7>_7mX5Xxz{Gk&Lt#!ktuLOd4)-_-YMRy z-k&ybXk%4FwNt=!aL)mW4KWM{s{Vs9anW6~swcG}>8lB^wHmNW+i$tKmA*?KNL8Ev)KU&Y)gh ze}C+S&J;+MQ@*Z<*e3aJD*AqjYyIXL)3$}-v(iNNScXk^xKc6t`VxK^qmCLSMyD@1 zhej-nJ-}M)>p9F1tj(=vPj+(xyMV22iWH7g3s@_AU@lNhL!Yb!@g;znbmXfOL zwC?5BEz^UV(Z+-cl@_J+^%|eylT_U#D~t1iQ)`+X!5eOlTuhCE)?~Q*qXZ(T_Y366 zmG;u4Z;CS<`_N9MQWu?;!pv2pRSF_qLjN!`5jz0RFnhN)JE$CEYxN*HJ=7=Z&nX$CU4C$oPz;ec~=Q{*M zLi0_Yey_B71TZMjAb+7=fWs>QM3?!H_ScT(!va2TUYKHw*&qMH{7=!Cso$g~4)n1O zv7++{HD&|V&ko(YaE=3KYZ*%gvV#BvWJVZlh%ap-1Y2pmsbbTCHSS+?!~He`HB*PE%T)Q7{kEGZNMee4b-l79BcQ4}cecaR zwdtM!8D-2!ZlDMK8>GsMq#2v113oz(F%%nVWM*wn{Qt6r3b>91ae=+=^A}D8IT&tSf;`SA0)XaHOyjY0fHzW48#j*}$K>E=+*v&zY9<|8_KAbZ`* z%Kzu-{nMGBA`l)la0BWJJn+VF0m3nF!3|^n-zJhc5i5rJ60k?zT+bdF_-a6{!f=mN&I&Z-VIlbrmd_(#m~W%oF;V4L?$9LIiNF;*-sWL{|xr(3>| z%uf9Ko-PO>&YXw15$oZ=h2wYkN)ssyQwpFF79_BwtMgokk>a{*c$cTH?ly>rXWw8MMCOByCeQ*3>r0q^N3;2iaHtmMed*CZPr~Bs z9Dym6wo2U$Nl7JVHsO9a`?=|F!Q=i}1nRQ7jl8AEwD5mPu^}$VAetP%J+7Lkv5^`N z?A}dNN)%aGWLP>3BP=LlmRuIe7`QO~N5TH-4LlgAtSv`z#K45nqIi0qtE2GDTFqey ztvGteQ~{QNS)I?+VmhAO26He&^_USWg%4|CE0kHisl0o zt-!>uIr9IA6QCp{*vLKyu#>eZ$=kRrIV?Qu}=D;%L`yo^>i==Fenqs+yiKy{nxIfCa!HV`<_H&;~Gnl_~?6{~`KH*#Al3bOHSQ|7GwG z!9Q&OKL-&*7egC+^Z#YV@}H{zr^Y`S|64=W)Xv<+0>HxhA0meTxn=sg|B?Z~AZ}^n zV(Rpj+8DZ+ikceRo0$H?`d`64Ko`2)f9MRYvhyBhop%AHepM#Bkym>$v^2FW?tdR^ zAphfZ+2+3f{{V47j=#ZF1EG_c&>=JvkYyXom;{qJAtW&+p`=0Jc~S_838@f3(s#|w zjx1B2_x=68f1X$P-s_r~bIzW*r`>bU%(8X!w&lb~4iJSDFI~5IBVm8#uK)&?Zr>W_ z;p}CEs0}MNu3X2%dALp=Sh@Dn6+B#-MM!7bs^yDu9sBzXpOvc+!GlscFl*Jitvh+R z?0Q0^#=R_KAbSMaEyylGE)`^_AUg!vF32`PwhFRE zkWGSY6l8-S>jhaS$XY=z5oC=Zs|8sl$Vx$02(ny|Wr8dfWQib)1z9A>LO~V?(l5w- zLFNfESCBqIdIgyy$ZSD+1eqmBw;)}DbP6(4kQstZ7i5|sQw8Y|q+O6UL0ScA5u{m= zCP5knnIgz!K_&^36r@3rdO;=%GC`0!L23o55u{p>DnTj*sSu=GkTO9^1t}4vSdbz? z3I!<;Bwvt(AbEo13X&s8T#%R`*@9#V5)~vwZ$j=0MRghN%d0CK`1UV>%8a#oP<3-Ucd zo)_edAkPW%T|vGh$g_f+7UUU0P6;w3$Vow-7UYB=#|1ei$e>K^_(45kVdna5)cMHkeV1&;cIW&tczSh6#~-d1w!Z-5hptxO6am5-!;}m_7xtgTrND!6A=BE{7ZrasKEShiv}L zEDli)nf%ca4q<*@h(iX4bPj18f*b;af$30|pM!5OFasek2M>>Qb8zuUCkF=yJ5RH5 zu<}R?2Qvo~Pcw2baM1HK9S1E3&7glKzFj@&?*yngC_GZ;A&CQFAdPYuVV6k5JoFid zPdR+T)BeLlA9MJK!@oKFYtT0YYxBSm;924e!=0* zLGK)7<&8n_Y{2UrUgMEJ=kPNQuX1>WU-B}Cmw4nk4nO7a6AnM-m%PZ~M?CTc4nO4Z z0}f|7e4k(WJsx_V!x;|G@wD%9_zsVJmcwZd&u}=!VTfOOl82t=aDu~e4#x&P4aoH1 zpl2T7D2D+KPjPsX!?!s+!Qlvp#|J&=^`*!7Qy%5;2v2*M!?!p*#Nj~>4{*4j!+jj? z_3y*9bbnQc0)1d2WK;ximKVZtB>i}T#praWui9?b@1Bd!S2kZiAA`eX% zwD%!Y$Dwx6PTNrphw4Fl3qnpC>ylrBeIlVSu$v+87m&N(+;VK zLm|JtfPX_ihXj9E9*121upAC?4lxedgLbN=EDllr%uN2w2!B|ZKPAK=gWs3VA&om)jzajh~hWrZhOUN(GmxSIlmxSH`zHVL{dd(aQ{T%W$@K?==&?}IaAul2Q9O8az zUKjca_>aL~1pkqFP3Q&l>d+6(t3p38uMC~Vz2C?4z6W_8k{msQ&*vcDg?z`fDfFyq zbLg~bOXwNX*3c=)5acA{pN5=3+Hs^EL);+bC}aTgl=0Hglg3@4ZyWc7o-pnW9Wm|; zJq~#c@+jmH$it9t84E%W0Uv}sfP3x--e7g49GeTc8tPI^?_*Uq8!y}<9mF&tTX>sd+S;?ZXUmbzJ!JFD%?CCQY*y6`Y<_36 zOg2k~q0uwPHU~4Bfyq6a&9>%EJsWy99@)^de#N?;HF&Mn)hl~e9a-74qIy}+@*~T7 zmR2w6SzNuSXJK`J&w?ZUJ@c#Q_RKpnx2LbVw`UHnpItqxr{~D5p6=?-o~|REJu|AO z_e@9pwCawYsYg0`+N)c8+K#mLv{X0uG$G3*&6XBUQ*87Frl;XeNKl$w983n^34Rz< zk>Eh^Oi*!H1EGMNYxPT0X85HI{{8+N{fgE1vQJL>a`T(5-j}_<_5RhXawfgGh0Vlc z^MpN$o94|kZ5GYjF;7Dy$C3(`*J++;tl8?8tnQFoZVI_2Vt>c}pws(3g*!X3lE18be08r@=VGC?|~# zQ<{^;g5qYPNMQ-1VQY?ttc+0n#&fUhh#!`dZ&nNuDxmz}3+?mxr&s;RcdExnm%`yLV8z@4ocOeH{Y_ zC{HFCAElh&lD@=(E!(yv5?dGGW5JfK3HA>mX&VjU4+;3UWh=t;KLEmnrhN4uzYNzc z+=4&$7z8+e^6dp@Av<}>m4PiroEF!gAafyokY30f$ZSXtWEP|w(go>+%!JHLOy_;hx`TdXUO}IKSADu{1Ng8$nPP)gZww-zaZ~I-huoU@;2lx$ZsIO zhWrZhOUN%EZ$jRHybgH{@^i?~Ag@ARfxHZP333kdQ^-#sKZd*r`4Qv=$PXbufSiSV zAM!oO^N=%;=OEvOdSkY$jikR_1C zkVTM%kOh!_$b85=$XrMtq!%&=G8@tZnFZ;FbU|i9W|V3{Gd%4d((vdf7+^KTJX%S^^3~v0_Dz4&-ZS#l z$RihJU?z5F%_Z~5e9})Ak;TaWGO~)ShGs4yYsosYo`u#UZ6){$gcjl|bS8{nxM~C0 zNH&noWGmT5w&TBz;9F85nzo6Bw~-zAZzs8w>>|6#9*LCP)`yAvt<$bOW} zW#n?k1oD`JT(yp3)=L-a%YRwR0#{4)iH| zQ!zplHz8-7U&trb5zWJm7v)pj@qdb?Ii`BL3;Gh8p*p(*ad&Cd&aK4kEK0G9wOgDSv*206Ubv8M%*LhQMB#H$r0>Hd}18G5c_B< z^-1hpq$M{%j*>xgj2uTvK21)NAr}8XrG42w$5PK49DB+s@(ekR8uDFo20hL9@SlkJ z4&t6m#hztX@$mP^_sLmy6;1sf>edVBp?*w$LVikKCO<&vCHDCvgkB*(BR?l^N@lQE z$)E5!3?a#uWeXSd&!0E9ueWDbcUR}k8Plgt?PzanZE0?5oHBV*vY~$Bgu2?A>Z;0$ zqQZjwoLF{NG&AIL*=<&{(V*99HENXtQ#QXT+Po+{5L+~$ibY#n3urjH7!ixdMJyT! zBdYo0YX-vfzQsto=*lFnT=BUpll;o$*p-qkJb_Fo$PYI~!vp6Uqv0WGZf7s}4UN&h z@W6S-r!lUIv49zYNCbC;n|!Mp!voTyaMM8Z_Em?P7Bv>+OGk}{DbXp*4F&n+sKE$o z1RKbSZagaG)Ju%WIZd@kWui0FuN_dbn-(t{nAzFe)EJCJ`dA#9!k#stnKGbd&kC;| zz&n%c!bkJZ9J+qUMwTo}n3hGCEuP;ype)8shm@v6hpry5CkAq(jRU#6e&>S%mk;De z8=D3aQM_13*Vq?G1L|yBG<@h^1TP;w{};UVxR}MM7)`eAUxX&oERLyZKw2y~!MouN zk-tcUzRPt(NwNfifdierJRBxVf`cSkl;|6f7txe6BE{W9Qx1rfvD+6#q1mQr)1uVB z?W=qP2bP2j@=>zvU-p118|mQzCAMhE(p3}}FFzD*L=K@#GOKqW*$9$coKj}f(c&Up zzjzTcv6`x(vv;5k+RWuj+Tdm$I3`K>7(y4;F*F#i8USSUAAH%v?#a?^>anIHy9a6_CbAp z(ca~Kw3MQ@f!ufSb@)R8vb&JC&s{ApMz#mE*}8DA98~&fX(1xqjF0H#2}rOFXn2s8 z=;R6EUMWb#W%!oV6_j1{90Zi?DXq8}h+C($1|z84?C*bgr6A7$USmKv_D(9ig!;le z@$dP{SL0XH7s?GcEpHt6f)_m$0rrBar+xW*%2XFAW#AQbv^ZO79t!eh@Gz2f12Xc- zqG&1l!UJSxxHq~y+80F~O3v)1g+q1C%D1CCO1*)sv{SWY)eBz(S3-1c{KGv5=IL`;b>xQi?6G8l%ugWqoa&A zFOG(7;pRh&hei)9Idn9cJhZWC(W+WBgG14_Wrw2Oy%SKDtljSo?xJ7qARSW2tjPuW z=zAs~jY`*a9!*NubkFTQWg{ef&8*%*8J^HZllzWlA+7gR7@a$dm1!)Eq?d$gfIg`U z0Uf(Ocq&QA0hX#_5iGoPNFpqbUxYY`EFF@0oK0LOBTmKRk}R$de`sO8RVV`V!%g93 zw0QRPtva-*k2WsiK~dtLG$2Lm$$%WKhyPY%8ZbncPaZHvC)4-_8sEU~>t& zLS+%6TLum+T}It}_ncYLHBW_xXvOxi|`wt*6 zaG-CXFG0VwcQt*ZaM(6LTBEfncK%FtjDAs3-yuh|lvZq9I$+4Ynt~qhM!I`>Ob|hQ z89H2=BdrN3Z!N05V^7PW@>0>&FNLO?x zx<>la?5ng$9x!LOEk@_h?>8bQS}ktIvvk=siaz5kkJZwgo1k|kd)CnCBhgD~46W2l+O6LTw`RRG*P2WEIkK5Z6zh(7cKGJjhhCRF#SNUUqGZ z@&{s7XOhQNhe)P2gG^M#NipIwl-J38RXI7VEFp7&ihve}r_(Pm&12w<&j%O!W|{PO2{s_n4g2p)yA0)E`c7pAgz!mA)6s9A;pm8 z5SqReLa*tP?KDkl?24XGs)NhztoQ6nR1A}yqm z)ZrVakT!gi1t*MVk`8=VE2@i)_=uX!AP$_X@(>-#CGEt8nXsL>agNAKsz^1dCk=Qz zg89Y$Qjzp~d5Qe8(xDtz%~O49_+3-Xbceag z{I+Ec7RVm3W!oM0I~-QW9nNCs7S}A-@7-HG2G4`uH1B`;7Wh8!e=D#zXbf%)zMMwV zW~begb|&4JJ|X?q^gm}D{RVABG1_BMylNFj96noo{RB*gOdjovY4a08_zf?5*_IXE5(Rr!pt#{vk*Y>xU z>@`JY@4ohKNwH*)*qOL2vR3QTL^BKJig>KDtgN(Nt|*U1Gc7WUE3d4oSISB=WCd69 zn0lFpCFN(I%~fU$Yvg^=hS_E6jDXc;)~Mw)pQB(xwyk?!_JqQ8t)kT^YMnNxYI0`B z+NR83Y3=E5Pr5^=bEJFR>2~e#uho`M{;sxsIz_ei)7unH-Ta0utJ9`3I&F53PV2CnavJ9kU*%4t&q#B-`Ll+nK`qhIPgMKVF4VLbx%(8!8h!7$ z$tF#W4y8zJX!OJ5M#LBe!OHN5$pDSYw$V>B`!uo7WR8?glk<(zw5(_>`=2JG$(NZP zHJBxj%0x^yll)Zlx#-JLC2ESA9O+$-9(50CXlQWM)D#u<_uIWSc2Ikn?R=@d3>r`L zb7vY>8?!wg4O4ksi6|B&ni-2#R!LmXUTsu~sJ7`OTXrav?bNF_4F6$`VsJ*&(zC6S zP8w91{qc-&UcjQ-E&W#d-b7E(qEfUby;L{yqTZ}msVzZ|YS3uWDT>Z&ykU4ZL7jR6 z?OsCd%0OGJCO=9BLOz=`Eo8IO4>LY|CVYgESL{wKOy&gKNu;}zNO!x9`Sjv^dT~Cz zIGC6dm5-WqIkKsz-hsSU+LtGF1_c7eU(s5Nn~ z-1fn3r#vy51=I}5vCCAc8T_U9wAkzx)FUO!2;0IJIEFD@& zd{-_*ALo;b&}+t|{6S~8>a>)H&ahZ2JgT3KCjHuZDpC>8zU_^(CB@k;3vayTtXXQP z0%$X(4cP6>HL< zRV=+}-n1>9p~(9iEkrZ+?+C#^Y7T63H(TxN_2I)K zAF$%je)PS&J5Q8vc>JoTj_!GUbB%oGqo01Oix>2q2j4rq`otCOpV{jVJWt0vW)*9=KH$1*$pw1Z5INJVGusb-Aa z@j@G)88O<3hONv(#9kSZYV$V9$kc(EWE$DUz?fT*0Yt34< z8Xu}B;~@+=G)MDBKTz#dhhZ5!kW5cYv-)Ta_0byYqkWstfEwzvAs0ScdS>!mTnfjN z@kMbZZcXJM$npYw4&J=|t5iExI+NB^ zz2M;7OCI0e(6sBZ;+ue(1X!_MEw*F+E+nG&2io)ah(#juB@dmY(S|^*{09ZFhb$us9IS4P?@G zfiZU`#@r$@biAQNikea?0x}gbgj#{DX|Qyt$V8Q!=FKuv?Hj4~ja2(as(mBvAB=R2 z@RFn(1546LKWuhsDoG-pclu^uib*nEJQ^4EZ#v%~Vbpky zjwGoDb)jMPqX*@N4NRgj%C#xG5hti>rp^`d1;Q@f@G&qyt$8|Erq3U7>EvmwE`kN1 zeN;J29A zr;H-EOQV$}k4O1f>&gs9^F7*;ERh#c2GWl;Hg6;l2s^cA$4IyIl3kldJ3x)iAYVOv z=~!2Ap)8)48}ufvN{s?B2fV|h!*>RpslL7gxet)mQ^d_Pi+y%1vkZ}0Aj>R}4Nz`m z_Bhd7yWB%kBGs8oMdw6eusm`*g%8K5Sk$KOK#!~+KI_dL%fu_xgzInxoqF`mPl~GY z>HT_pTB>9;3G~Mk$P-E1qWX>Xvbng}TU2By^!eCeiRQ!xQ4|bAyep8sD@#Yg1Zcrz zWR;jq2HN@zwDlQi>od^SXP_l*pmhs&UDA&L$*Sx$`n={MUrC`Rl+zjN5vFc~14eEc z%2QZpuyjSsvX|LwCKi>IQQLQ18;eTR-Yt~lQgmE#(|JdR?3K!Bc~k1vBy_Hj-y3o2 za(qtY0FZxVROs`el0a@ zUKlA;b>?`-@fgZ*RN}AzwPbYZhY;ArW5gb-`KeE8w+z|bHBcM)13=) zEK6Bl)SvNjQEnL_`FQEOU!QZg+ zXqG0G5g^M5Lu4GtnjA|&3tH*NL0sktZW=Je;^ z`_1Vqo3oT#7vHsh!bss*yFgKEy$$m(oik%ixn=l2IW0?R3DXhYh#XhK7jttm!&Ydo z(&4SEXfCQ)E~;p*s%R-!p_EVN(wSp!gPp1bj3KUN2-N_YYJjZgv_mz6X@xde$4_re zO39>mA~bL!(&7d7(p`<2+UZ=++ zmB-?-SZZ3RGHP5|8G(q)sM_H!sGn80MJNk1LubjPK*yHp@#y6FHR1At9M@KhZe+M| zroW-==0_WsP7a}y(V-2XiIAh0(1yE$wBrfV;s`#2EtTlSj|G|aaORjlg)WXyTd7H9 zDm*R4;Vv^sv82%+u9B*fMw2uZ<#Q%!psdPXW%o>gC4XX4P@UWD8Ip2S?GQz9-cH>e ziA2BcybaBAoQ=gMFv8#(YoIF8K)Iu-P?HLOe&VW8mQLAmfB&QnbLzZCn6x@e+00Gt z)%{blO1oCCU)5DsxBBK;i8<3II5jF+(HOPHqQ?H(%9-VX((X0u*L0Ujm(2SbruX4Y zUv>x{Cv9d`nde2xzT%xn5 zIi1`+MlFZO(NkXvt0qAXC({=dNMYJ)!?YELY1IkSu|G^}4Sq|>mb8zzyiwDLC)Lvd zSx?6h_W@akSvv0aJcBK?uu7?Y4omP%QV#>&5bLsaVcIV04Kv4ibEXxBGnff%8c1_J zHlW#4E{qE?s!N*=3~jq)U|%Dj{yBB|-P_tawspc_fKeWC>ZP~0pE@wP{?ey+C{dw~ z&;CC5Dy(AlUOq?hia4s3O!RK6pp`7LKAE0HJGPuGDL^q6kaFN7GE4b>Dc>jgk$=`m z8KIrGPsC7?bkHcj&+m(6hq`=f2e-!^H4S!$#9K%LMNInprT+eYxB|188KjEC4^UY- z&iE;XYfvknR9XD-bWg-*H))lTKAq&q$xMql^eSnKB&}9-=(<8#W<{4l-Fy-(Sffrg z$Q*%~+JE|-s)5E+M~?8c=fhqYlp0e>`*4#$(=1YVCbK zn`71<%dq;O%9fU!5lW<4R3m?rKT#}!+;Aj6&8mz%u957qa45^Em8Ga8xfH!CJ0mUP z(koJ~ETtHmg?ib!!XJ-0~8EtFzDDdv^p9w~=Nxm{7CJ-y35ZVH3eO7q;`f5DY2 zG0T>Da>wPCO<-u5O3LrdYDaEnILmERjl47RmfGab%810QYO}O>QWn=ndzapU1b^>sP_b{YDH(%%gXRD%q~T34S3{kxxo{(!to1_PMY*Pof+{c@8KWN z{A4gI#f9~kJ}j;A84R07qO~(b!v(U23uJ=}n@*b0aJ_7{ekO?uJcTQ_oxQEiP!GO|5J^)Y{GK=zjSk1IxJ zW*{rqrZ!3+jf^!`=`HzJwAfT|>Wo}pv9+#dQ-NXvzu2;n!2$)ySaR3MKC>@uCw{A{`5dJ-I?FBZ`N6FK|^kH z_vA)s_b{~kx_T3859UHA8X6=+q%u`mfXqSxvPwh4Okb5l(#Of5J3$TpL>L-PQ2i(9 z7?YqHPYlV1q@K79l@$?{x_C%ZKOJiiHruAwfF4y(qs}nu8uY@>OU;Ka=xl6Uhzsxb zh2g-?S51VuueE!it$JB`y=>`C{fV~b<~Y2YZcK1AT4&hj$80C3qqQ|>$#rvbo^+Sb zPKN7~P4UJ(Q|f!G{L&w{oxY;k9;?k=k1+z(&!kgVGfNL2!@tk1j@qUl9N5-$`LcMr#HZDY)qPqERx0l$57H>ZVkb^B_DUTD}OGb_J`iwT9Q8`X^!flw&B+j)Qy<9 z;6gl$5tTcPKesTzg3(M^S{Y-@0!mm`YyA^CdW#m{vAkl^ro(-S&c+I#UL!lq*7$^; z+8z5N$^Hp7vl|j7I+=dJ?zfx$+3Akt?ql1od~R2rEs*K6IDL+ID3TL7`Q)5~y@{+u zROf`RRVIs|m%FeZI)=57>yn{{I>{KUp{=uqS{pUgTCJhAqlQ+Nn$tKQLr4+VS`n>b zNCz@|gCTBW@wmE(Rw#or(rm1W2UQj{OZA|y9Zg+z%rXs2^{7m&I-$=>85$gD8@%9- z7~cdjT^KVv6wDLGO&+V1yR`N+7hQC0IXrLa^>cDcm)yK?#=)f46{2-Y|L~N(jSZ+l zs8N$56O+wxzo|&fnj#y;yn46^b!W+*WaH(_QJ1E`OqWSNv~?K0 zS^{g~PbTwL!(ZMkT$Xl2od+qTj^YeeW-_Y_!N0{rhRGg7x#& zIKD2yv{?F9f=|5B*-^6w4OA12jH^~?r{gQ1?2cD5g=&?>ccjll`$ydQv(`elpxxwu6u;oRJ>S~AeMIE{(xU_WpZ8kd9*&l6P z*B+gmWr7W7b$Tsoy;1Kg>#SX(wFjJ8;m`g|%{{tor?|se&VXIpzu@ZGxn`@$i8ULA zRE*rJT&w&DyC0@wH~%Y1x1*qiwz3u-Do;z;=9H$klr_K#q$41ZwJ+d1Pt&9Z?F`VQ z+3Jv{&Iqck#Y&l0OKTGvBlLA9X$C1M(*}duvH}&=ak3m0i}cd3=ndO&TW?-=(g@79 z7HgI2_FtL0-*dYcRV#m*(3%&X{LAY0dA|(LNGWH#O52D@REF6q$FHYRGJ;iDxZJZ z)ZCVkWV72xMwa&%w-kAo&nsyy@^&xm{8KpBr@vx*$MX81vNamYno~4=XLo+O$5EIO zEtCy%WMW@k{l=b>>||egq`tb$@1L4KaZxP0fAX|lvkLUO$jIO3uMAhW<@BuxRkaQ; zsBMsS{({^b_oON5#r3p)ABJ6bA4cX6#QQv827K=tZ&gqi!LfZL^ z#;x3^bMP_OSJ+luzo!vF=DHO_am!6@b9YaT_(gq|t0Y>3W?Zip%#+L)0=;Ds3}CZ7ni$_o@TSJvn~r?D$54Gw;$ zsV_S8Q!0f+|Kq0(A-WR+Kbuj1+;3}R`g!AgA~m$6>=oJ%esRskN%z*!%7|Jh)qh?A z&iuOC1eGxrC|AJhK;t%PrQ+JW+!_dSJo@^`tkx#ZO1^~ zv4ea_m&~*2FRLX?XrSympfLA&ABYHU_oMGi8vK4zT1fL)h&&$43AJI7Qgu|#S}AgB zFDpxB_AJjW@~Y;}wv=m#C}D zvo6~`E1@%(?G7_tgI2o=THBN(UsMNg2Yb*C%E|3XQ$wYcTOySt9nv(IN3XCB9)#Im z!1t+kSQttvIgP`^nZ%ST+pk`oMAHa(3JM5S32!2vOrtudEv?xung{$_QW1q0r}_@59y)WABwK0Rz*ZVr-5*ysQdJ_QAA-7n z++b^F6+Tq~zOY8w;a#ay=gMy^tl82;TMt&pw4VGag*98pdRC1i z&Fe|GX{X-UR^8WFY%A#OXvvzhy)86W9&)tibA9X=W8hLWq6+Dax*a_;0!5Q@N*eQ= z=zQrePc{aj1WUcwT8ydT=<}tN8ilypQEI8uq?5%ABennevOl#Q#;^TLAD>JO zOmtXE8VcI;{8?>6_3%VM?Ly6|b&-^||0i8vtlF<0p2n2;^=bcy;prkpK|zb?=tO6O zZ$m?LP3+NRT0^dspy8F(>9`*u(wDWw6zc-}^!xRvuIiY)@Azh5J8)0i zRX6Ze#!m;K0;mCNI;DkH+L&A2LoI2 z;2wrA^((a5W_+bz;mh0#Uo>IdU+q@7WkF8kq-2)ps!>^7?w~`PJ9S!T!IDGNtx(3? z3eEAxT~q4&sshrVwm*BY#gI7uHBv9nt0(ZY3TvCWuSLaie{t@t zr&eIdrOj<`ZHrSCl`g$`VNP>XOCH_A>q@h0zc7CuIW9CMoy)C>TE!gNo?Vx_PN;6= zUwjhH9Wt0iv))O51R5(NOOJ1?kYd(Uj}K&72lC2A3AGlj)CzW_wiwZc4%)0p0Ha2B zQlDs#S>53_H+3hl?w$?!yb;mW_tZjNN7n^cOVEb(O6^?JR|RXDY3ct8yB7do1Qm5p($qB9uu7PdpLbM(CY5^~%| zUP_vZIvP4=bnNeVszW_)F_DdVER1dzc;*<)Vircp@lu0%fzEx%Tvwfz0k$t0G;R}bqrmKeS zp7*$u4{GE~hN%TZY>FPYpj(u3)^MMKh3?Dxzg{quUn*O0`SjvBO~oFAiY^Ey8fI7L zHI@eB$(cQ!$#`zp?yjuX+FZ9*fpuii=rb$Zit>`V?wn*-Pj@mdS(?_OyuE%`R>%qa zGZ+p!qLtaP@|;j+qJH*-ip6dDCWqT*vU+TGzfJ4$dz{hYw0K2MI5Tg;ENb0EM*k|W zQ+*q!80H_(CH81Rsv$CjPJyf}fUH3>gc1vAB{X@>1?Qu!>E`p^))H!cYnfN{{5d+< zm8HB_=gxB19^dn4|Ga}ic8_;MFq@naqN^|MddbMg^dZx{y*JNV}T()oz!y97L#~a)SF=FUns5j`<79Y*`ZPd@FJPVuP z7I^u}C1ae{pg65Tak`ckXPs1>+6ma~`k$u>HOELO)dYb|E5MJL^-c+$!q5vu1e?=f z0`?y)C>FHEjcR`z3^VlwXCG~!!WJ8=QWs5Fg|lzW%f}ZNv7=IKpMjgtk?!`U+cnef zU_-yw#T_%=qSoU2-A!=!VgBmSj~P=tdZtfUdF>K8Q`k$x|D3UKN_KCLyiLSV{a}?* z*$w^Vlm9-2V+t6}=+at1*^g? z#cfiKTFT5p#KcS~D^rS4irv>)5h=`K!%|jQid&`a5h+5QTzb2^H4;XvMd-bx9^F7B zj3!M(bh-rmFloXwA~|glW1!8*J3zMngGmla^fSvLL02;S6Ko}n&3)MVUxN0E+Och3 zV_Q>YuhYvHhOqH%w^Q{O8HcVcQ@$Guxpij zReFO-``Kf3QB$R}7?e3ChhD)HS;mKcIAAi#f6&8OChLq;+ZCgqsIP#wo5AHr%5>~DOZtd>!i9`sjfhpkT2Q7Sj5JU z_A&PXML6RT5ylg27(ZAvMYdFCrP0<&ZR|R#%m&*G+XmZyo644Scv@{`ZP{(LH|0zD zG%cU@nl`7Wb!GmJe7Om+-l=-3F1%@(4xRE# zS$;v*J5cShgG_!?mfn!DPbT2Q(H-Spt;>3$P~;o*`r$1Xipc8H>WwHN%v6U1dOb=A zOO!aLq8s*!kgS8rDv?~Yjt-Pp5xFdB50}t2Y4{;%XHi!uVR8M#r$Nho61MxYZh^KE z7Uhxjw4&xAnb3PC5UDyURT?E@n9eL{ff$V?#kp;C`L<0=+-XNa7v-7fnk~pf z$o8<+Il7_f!oi$z>ziW>o02j`=ZuFkqFBxS#hWUlI}_(~?2=ycjeMk&obhma)MZee zdqriihl1(Z4p~3)pL~ncq{hTtD=i=SCO}b}oEGV%^oYf2Rw){TcI2ou1E8pkF6#(> z)doEWEWka`O%~}oMS{p|1@c)HlyZZTk1hkyWok>MMULyG03D8N1CqZQSm&2QZGMBZ z&CsEmfirXPVABO$G+ShoZ$ao!L=?UPS>>d=Z)4?S8xfq$Y3gxl<+7cclF~rfE^GGa zZOX`VI$KsoMy5-zmL%n4jXg7*mSxwBoUqx|CYMF3Q8^6Ce7Dbn^=hkmxKMt>X;fp3 za3CjrFlgVz@8Tp#-6>*2PCRtSM2zhqD?)m?zELmhv+bC$9P_tYF-~COf)}TbckEN> zKZiaiwON>Mq@^{yO1fw(JlpCe(akdQn;M-(H~fY>NV^N^hLQa?C*5f)tBlxCLE}cY zNe^S&jHVeI+_h&xo8+P zdeeyQwR3#)nO4giV3kv}IcbZ=;%s2d^zDzj$f}ad+pb#%?`hVz1l&OH_PwCt101de$Z$P z=7%#2C>9J)V=wztok5H36GpvcAA4DuoF4rs^{#OeJW8;+bN5L@MildND;7)6HQ+VN z-WA6>#4aY3%h)_CHQ-8Lc)!oT?-$=IC&FJ8XRgul2XLrYB45Y*tVih>iT5bonsw%B zG<}U;L63@8Njy)BYMdK(eNp{{LMrQ8iVB+`bk*dJ(T`LglDFwIaDp}OIpUM|;JBO# zzuf3RG3+_1iMaJaD}82J*|}0w$#?007e87(?rX+#X?4+r+CnPQ_X{bj!w7R$#I0>E zDs21`q4iGLCT+orR*>jX?^=)_UiM#7)?Zoe)Ui-mQGxFzE%uJEgM!Zefv`iPaj<%K zjj}^2WZzIl%*QpEo>F`ZGKlXPTWzOpEp-f3`z5g++EYAi^hSNYOpg&&%yzZfgeqq9 z7$o(G_e&DcX{uWGrQRZtQHEx5j@2|Yi;?qRkw9BXLfIj|I`+24xVLQVZO2+bELMJ@ zHBvA27nLQyO5gGtmD%BQ*xW|t3WGQ5_eMR&kvqpF;Pq83g=R|~58*X^=X6HeAaIn% z4lUX>8hbeKRS77+Ch53bC{M(>WXo})HJ-;-k@GkgKnoEorhH+5^;m@t`^W+Z{-g)c zFR7*f#4|#%Scb+Pz*DXqc|`h$`a0Ch%%oePBcnp6V+!j$6?e#ZC21%^n`4H8q`|>I zhj;9VX`#aUO775*{<^S#;XJiuN%uPfPLopERh<^9=_-?O^2_5*v&rfuFOKxR@#e_f zpP1}MH4dw&SG@X*w>EA1%`bnp5@&KTO5wLDB(e){^hdl=gp{2k4os!-POwgy7mMNv z+POR6SUy8XYRsqk8zxHmE7C%t{U+TlRq3cGm*X++ob!4d(jU{RJ1Z3v&KU;M&60Zl zf&~jyvMtT)#^Ek`8)S9x&rH{vKrm_kEKW6d_#KVMZFCt7Bw2xxse%ozvo8I z$U*fEoI|vn@c+mfc!4Uu=)BOo*kVXkkFzC&ods~+yt=NNrb)wTn3}2S=<$Td(LD0Dlmev6OTY9?x zaHD#yqIRgRR&Hl_!@*KP0IwCcZW1*G^D|V*u#IkXWe79f`il)YnNrOq=<6E1$;8=I zDjcfKh{CGilWlh&{DRK(^7SH^TW|1URbNQHN?A=}k98z$+ua-Z$>FW3`Q2@U>Sou) zhATnYtiGd6SxN!vzEwnAV>lM9hOnS%T5_3UNW*>(52+W^PgKp{^Haw~spl1P`3pLw z#N#raWj+^C=FQ`PWeuxI^KfF)B;#k8L_6olgW~O$k(poG093~(8jI#h6>bt&2lIkK zxw_}(v<7(X&N7P0T$YwPJOz=et>=UU=Xnvw82=&i7R;+?P{r z#gNR%aq0k3{F7-_<|m0#EQ3s+0V;mgPFF{rW5zTC|dvg1%20 z&+{Rd?*sFrmZocWHz`Jj7kL%S8QBjh4`$L@#{zgRkS3#>-H?3_GZJu_gy+dnZsj+1 z!obIC&49Wb{?r+K0GpUPtU_-LH_0($etwFJvX~`hUKCVugMfsR7>bx1rp*R@31>!V z7E{)#JJ~h5!fzxy!Q9L)Q6gEU`6yJhQp2b1Bz{xf-IzVz5}jlXx59V19K2QA*Vj#B zMX0m=D*NCLJQ2c`qo%kHGv9^>$BpT^3HW`keM`KJxn|RkKC84`yMd^XMN?Vn1H;un z)cPzV=%wi@3%<&-6^O~q)-J;*X)gw{9#n@i6E?OM5JH%!%*1GOg_7_OYo6wsGOsIw z@H9t0Z+}izWTrH6L~7^FyW_GZ3>u|)u9mzkgC{j=-&Ta{p~*~B+6e}YWh-dOFSKM< zMbVsIVIJmZVb5u1_6x;GoC)+qMM*gGck2{OvH}O_1q?@oVThQ6Ipnr;^dQz7rhR^+ z%BLw&|LKKT*J0;9z*&Ju-Sy>2xNCJ#yG-xZ!lRIh_S}OR?l8jd#T@@hOW$vbhfx6| z$kN)8Dl@r$oLp6dr5JlRaALYgVfI;xlN;ofJvE6fd43>!&cPMG;^-1=?Va*_Q5w_i z4=LJiHuDfSXhSz&EL7D7QS2AH zO3u%``jB$Z>9A6}*cygVcww(x7?EEv!rPt@M^VhS#w0u?bPq;Kl#^0RcUL5%7wWoc zv(+8uJ#R*NM#tMIk~U|Pg;+BhtWJHtu{!J8)h>cnCKG}CmbZ*)Dy*#3>F6yt;h^91 zi)-N~XvR)gIIMTVmvK_E3nrcckz5|5;hc+X2{g&`s8J1%)Cp(@EU2$ZcYTFYMUa3? zET60@!+B)!>QEfW2UH|ShyvtBSpI-Z#3?q8SkuPC@!R{eBhC$M)*N^#^)*~G?3OD;RfxkE;jourv8%ozAr+uJmZcmGC)c&rx0n)| zVBch~etJ7yrw{VBTsB0b^Hx7iobxDuq%88aJ{)9X7mcUZ=-mR2I{paNwyU1^+jhP2 zrT_p0#`%)!<_gT@#$b8Wz7}{cw3UW{}0yQ*B|q6xm;!774=W7vZ|Dh3HD#@1TqJR-38P zE|Av0m6@9N(vxCp6^1!3b@w%fk@$2mOEyLPE={75(_vo$(G=)yq);}#)tQgXEdLd9 zrUN_C3O~7+`Wq8A>Rd8W_DF_4-Dz6Vof7Fxg`JS)@|4=cndn}{(i$Xvt??9~yJjPo z!qn!HIiBY(Bd@QD$GYt8k&7ElT-T1V(gE$PAy@X+(NsEltWE03`C3H zp%pcQX#d9jdFKi{m68R@A!-ey0-_$$4JV?NhkZi*w$@-~!dvCuk%$xCELq-o5<*37 zQ>wzCCY?E3!35p%o`Cm^U#wFgn4;uxWatxhN~DH2A0}cv)xTt$&7X4|oPq$&qaWdpQNn z6;=VCTv9|VceILyz5@Vqxov^R<$)*VMq(9Wm<6tb1+tIbi%=+?Nx!$_(49d@5wIjF z6Y<;QD=VtF0`6q2>I{`xA;vTHI%t?(&o2328}dr1W9D79Qu2`c^@=5Ts-5RBIO>aJ z43setke?ysOe3p zrx@WZvdT<|bQHj)I7l?0r7-Eu$xX;ltWi=R6dMm>690Z#4#my;1OB{ktH&lx|9qsZFV|XMSAuH!`?X)g`7!t~5X%*lRW##Q?VIvP@m{QqZ zo;!423%QCCp?Vo6mKKz+*-u5)rK65{|3NBGB_5If@pwU^MH^d?)zZ%Z866AeXfHI) zpFNS}h348&xUTYMOHD@Txp~w+f<1-jtz+0^U~M`J;8WmYvS%tJ!D!XEv`+LmN_3ki znimhYj9Ng&BDQL6mbN5`H0p*n5o$|2_sr<5YNDja1javVJKo-c8ngxBK@P8NAA zj0G!IN4EYpbw(VXc-l`%;EPyiz#ofH6qf6S`AhS zSXW`jWixyZOItYqW!a{6V(pGois((CXW)MR<^_vS6Ntl1$rxn5~e zDs~GF8n6}(;ZFs6oBVK`Rm@9il|Kq|9^+!!D<|VnMgv=4k~Z)<=8u)Is6C!9Q5)rR zIZwslUuZHrjA~9$A~9&+9@44F22jo*{8$y45X>AI>nLikdeJ$;5k6#Q!iY@VEhv)8 zIrg^~f59jaIRw{Aq03-0r2j1TA{O6NCY(>G1C-IqBQ70?MSnRB>qiWR{O&j+?fwnG_B*Q1XEP}y=C+SKZ@92;>% z)-kITrRWc79oo(A2Yq8w9NIYjs%Mf<#fA6mB4lp~Zw`~5v@7_JsKqV955(4_NR6GQ z-)-Er&v6S4%JG7+1ClEyT5&L1wh>AuqN7Btrgel&h15og8U^R4R5a zF7?Wj#nQ5+7Zo<1NmOmq7teXdhXxRIK&;vUnvr2$y3W;R6L67~KU((f-7?=LBj zk)DB#<-dq~EdPU__b;ZOh^>v2kg=nogSnlPEs&ST?`UWYr1){LFam*o`gUT*=B8#& z_^iy#_;i2G{^rpzvU2LT-#Ao`yP=SAWgMTjokV6P$4>Gf};j=KZ z;4`yv{AU6Uo(&2Z@U{P| zxv>3@=JFrhB0Dfm0eI>EKYT^)gi)JS`X9oNFHp3z!g?CS=iooS0oT`coBn?C0BRH_ z0XA2IPX+zyJ&Dt5p4N|I$AaxJaaHZH=Dil#yQ89esMtCgaT-#ccKdwC*tm>yb4!nU zI^!(Zx|aTK89lC4CbpqFA<26&@Ud4?VrO$7nQ+UfyS5&3;WTu4cR9MY?~b0iz8*c; z{=VEPHCyR5w!7mczgRKKGwW?pFgec93drBM3Clr6IQM`9dW@pMbgH zRB?Cu8A9eub27DALNVGB*CtzSGX6_=!**j-gu17~7ztIs_6$6t>iaScs(Yt*jCZuK zkmvGuYQj__ENa4*SROruX@!PoRj*OyWuM`2_=0D2oBNZEiAfS?BmE&2VWG_c-TA69ikMP7{r^`@puLM;trL9cDv z0hp+>{aua3KJGB_AN&FGIR2eL@V?*r&%r*-gU$fExg}2`f@>YW7$ve`)a3 z%n^&|8DCbcK;2PF9h#5abx01iAh<|@EETcul7?C6-fBq;O$`E+4svY!BLyk%EQKbW z+89)&w)rXdIM9EX*Zg7U>93SEePx_%OMTE;4JZk5K)*eW=glCM)_Z}qLGp6^e>l~@ zZU3)NVWVgNPak3U4?Fe0A*O#l9?+dR8#w(#O;vJmHvX5d70`Dy{#WMzc7=aa|Jw^g z0Ugjko$MdS=ZMer4?Fd5pL1|@5;W6y`0MWIr1bxNz(5c5i%Pc2Hs=3OPMQApT800~ zS>^b*?7tHK-Hn<5MP>bOYAPesUl;%X>(zN}kX}mj>wI1l>n54aO!3Q%!($m^QVrsa z@kTX_aac7~-=vVgLZU;aZK=dn%|#-XqJjXLF8!6~C}{-MV9YE}avN3@s_&~;3Q<>b z>Mb;ICCgFc+BO}@vUo3VeK#jx-474WMtMeU`3_CqyMmSbq`)C%=TKDXPKj3N>`?r5 z%a@vThVzW`oGY~#8edMNR?>)t+Dz}27j+WFzlT6HGy9I07*jEsJD}>{V;ULFAm57{ zjnAJ}4(B=gMqLe;E>t8_!WYEo*xlDy7Hr7+MAzMv8>?21%zes0_QZA6pDvirq>22f zxWrOpQOl3_fENeCxZ$FkZ0f zSaP`1q6y(^gd|lI8|E`#OlPnC8{X4y9{sF^ufBSJu?RFH`6rG+Zo;==+7Iuz;N8%X zPa9w2PJ=_qH#+$b@J~+lVir&DC46g-@i(z+agAF~yXLmT`e578tiiGSQEz1me*ne~ zGq)@8-OW6)eBtd0)+RQ~gJcQEL|$Hp;PJh%%~3DXCHQ{F0Qi^zpZGI2d3ecCm!chb z$FDIa+wF?Sk#FGT>o3K2Xq`6fKN7G&$yK)y?YIpd@m=5(FL3i9yhb+rbn_$i@Oq%` z+?+}KDy%W#g6erz>Na;vmx4&v1M@cn0jt1G=-XWLwpIofqqD>_mfRuuTr-HXO;-u= zle602*4wn8@thd5f~ce?s2Pw1D8%o&5(-6f z$Xcm6EbYO(y;*)qu;B#yaHM5N zVgP4L={2ekM}hd(sGYZ+pxxI6H;NmS4~3@urO14>2FY02Eu=i7Cd1IopX7wbf;?C! z%Q2RM6|l|Uc&Uzmod%r-80ODB$2nT7y(^Y|tN4{ZdVc$I!$frXEv+Z_HnA zxTgMFF1WJGx$9bE1G4W6%he=+q+rAoK_U>4>Azd&QYIC&+gy86<3CN9N}JOfek6yW ztOy&4Vu8yY(p$~k#@te8cWk3??Pl#{y}hz7;Mv5pqO;VYX$HY2gaw7=0)1`AjY;?W z64ifOk68_Ujpi)5)%8NsaWkEYI-}L);-J|Jw!!Apj#@rD$Xy;47yH3jb#4i>(B6|F zBmc^^2Pb4#{D%*A1&9qzde?an-kwkB8Xn*1$EZlE4 z3|Qaa@U=kK6q<{#MOld97Eqn7-mIa&FnX6AKMgX9B0P0W0L-oB3&X5v(_tcGrby#R?DzE14Q z$k^MVs8hq+N``iUGBAZEgy?uOJi%L=y~V8obTf3t12ad5y|MA#B4|9)rqFu!cX*21 zzO&1F9C@+?T9H>2aXIpVvT%hqM)#RNUqfO(c!y_eU83XR%HL%;HAj7&O4f;bNk*?1 zLP8`f`Ze(gNfPEee4F-&9WHTcm&3Ozw&O~FoS{e6faox!Q^K*X99tl6tF5CDk5tEw zWq9mT-+7_TFfm1H21}}ynmqU;tT1EKipq6~JQKpk!<{>KZ&$GnYauRxCkghfWW5uY z1gTieg4+_fYZT$ZZHDUPflkMF`{wKDA(4INHEa+1`}!cSlyBQ8gSfTG(jJXknw@Ma#KP>nI-5?@L9zKt(Q-B$8zwM`oQ)4N5 zboM?8HcCWfMGkp)y_T)Vu#t?n5Im#q7+6Zk*#ZPtlrPdO(#&b+r4^LU0Zx#$D`-WN z@?DRN+m&q>uz-We@__U6{~XndkjfS@kj5H|GeQ%`SWA4Pp$%YGz{kIZ6url`BRk() zZEARCGFzDzSwS5WTkKmAaf(MPv^2Cf_a2O^@J`s6j#Nr*bqh3uESU-L#!I!q0QK1(*ymrxWHwGLor5)1jV`D9Ot6vcfwyqs=?5yQG z+7Fz&ySV1vfjPYUA{Uvb)>U#&=3a(5ocmgD;aI=%rNEtL{Pkw5T7qtNxeT%E(71fY zq8w4LE%Sc9`>WFKSK^#|l?JD`=5B-XvEotq=1; z^7^`UB2+#Xr8`wBUdb*5j|2kKf9H1WTH7Y)doI0!<3mm`0jo_ z(!IWqpwN`|(6nzSD%-UmpJOe$%?6C37;lbj)_x@!KYXOstqu+vRmu0o)0t1#!LU(z zpqX8HkKREkb5n0}$5WrK$+Fypa#p^*VsuuQbW?YH{3v8)tM}g3)|~7tHNXA5sTeP- zC4HzUtaJI?)wV8sqIjra{bwtjE39*^*X9mraCSPMjmKD*Uiyi8aVRCSC0NNf$J0ym zD7_eCs4?`4^NHa1%R0qi-Q3YlWaaDNRY6^KT`UR+mwGJ9azioUrE5XZo9GdfqA+94 z`8EczNE=NOTjr-`qs_X<0jpJLw{E8&3gOp0*l}CQMxDAQstk!jjTsADM>gZu2K|%8 zx%?5j{0%94OT{!rE(I<{PsN>J*!3ZowuDC$+(u?w>y3jp9CxnUhXe7lt+)z73k%bY z&D$r~U!*O#ov06#ZI}cfY7Xz`rAk@ywM{|lh*&AAL?!>{4cN2m?7 zRK+ATWo_UDF);Qgaag~Ir7bqb4nKa zIG{(3?OFB7dT(L4x5$`SdQWr@qCI>fBr+>(Y)7IBLcYe(A;C>-dvAK!HP$1+>nBnC z>kxGxFR=^6LE3P}R8}RvtrTN~XdpG2>@3!iE`iE@+_`|l6018&iU?fXXP$NFIMHJG zB_^BzeN#L)KaZ2s&C{OlkZhNTYIfmeoF>DLKH~`BT6%{zC&tSGq&bFK@c4d@=Ok~x zjZ>YT!|;ZGk5`&^*I>=E4Q@9ycG-xcIfFZD-Yq0O5Lqur`A+@?`%mN1W}hoV18a?+ zmMA#GP2rRaJcrb%Ime-&*^qv)a2}E|*N{z{FCT}$jKHt7;L|9nxaGChxo-Qew zIKy!dglk;p4o;!@SLZ8m-e_IAZ-Ms){ZEm}+Y&br93mS%>>t0JKgpi`QFot-9&v1L z_i~0!N%^|e?tWld3=11Es7tcO*~VWQs_K$f#(Wl-vV&T5P_$9%ko`$*gSJeQHPJge zFXF-TwjHE}jYr_V)Jt?J(L=4j6YyZrmUf+bJ%aF#?idu;g3!7#pe95$@e8cHH?WGZp(H`)S={VbD!YylO>)^X(yX^{L+J7mX zp8RCAGq%T?1DY`2$7zK>X@K$}vyLu^(C%N6>pL(M(gfNDNP4E%?Pt4zezN&c`M~`+ ze5(uu+2+`G-LbMyc}llg?rS97NVQ69!>|O21>2>>Cm|NM_`;V2l3LOC^l}9ggEbUs zgw+gs<$$&fChr>9CZt35DZW9LY49BaR(~vM_goe9#3tKy%RS~In=ij|X7L#B`0#A| z<_g(iUJG=wuil}wS@UYG7iV{4n|H_Y2}Q2``!zQ>)s!dxls`R%%2o=A4O(WRPd3%u z_zcbB=grxY+qK){6CUZ1&_iEb*ej_I=XKI>Q2e67o4kU=2>lEV`hLK#?sd06V8pnD zm9e^Un-+%eza5mm^?913Ps#afTV^p47>^a)9tpc~UQ_2pTvO+c9%FK+9pk^#wufy< z*%m%pOoAq_+Pr{zKuq4=LHzm58$1rVGkn4Lj(_0x(=mZ+Yex&mWTkI>Z>2fny6j+K z=Xe*qDRL>hu=#yW{{m-YSd`x^>H7UG;4S(o>ACTl4orp|VMjnhjl2xi25|#<191ao zB9y;cSc{04w1fINKW~mgn}7%Z9KahlaYC&9op>J0$@Y}=US6&&Q-9-ob)oM2&P%+H1jbi5+b5z+Rx2*T{$9K-f{_ox>>%r7Xe9E}-HkmA=c&Df_Opx2mXk4_gV z8e^R_+#=Pys2-otpaJ=D=UDLsb(9g-d?{soz(2ic6zU^Ewz0Eq& znhx0Hb3m8-^?4`2PdB;~9h(^DJ*P*w*cCR(dw-ldqCc}VN8K=kEO9)h;ctEg zU+YErRZ#yc^(|QC2VFDX-N#*D#BYO$%kWhY)9720J%c!Wo;5l#9=lyoZtXo!`biuR zm<Sauda4G;Q;@hvnPTKGCU3Y~Ybqfe}?7wbFQy;UU; zlgKy$KfoGk-7m&_{|}qN+PFLXdx&O9PV$f7Iz@N_f5vO{thdKKg{ySF-S_1x)=kKf zhbB3Hd8(|jceCrEKI)vEXWVD7{UOrd?wnU`g2`Ybo|}6p$=mx|@{Zj|x@1YR8?vcY zu4u9w%*`3p8D3sDh~$m8WSJoE>+Bp-CBvxIX`18%fy8EKr*|k$ z#YtYj4@J>Govy)Zq@QTaOndjN<3AxmEeU>C!23^(f!w#GzQLZdM&OYEkkA}nNj0B& z?TU7RzN(NcU`}j7N(XG@m2kNniQf}k{O20%63NN$2{4P^J7|U3lT!=JlF~Q;%6^!e zy195+Q&AN@A135sP=X#l+hFGTt;d?WOo(=aI*my@5TYuc(v zhov+jzjrjI`pgoe-5gB4e6uWGMXlAC{6$0>g@x`Fk7Zs;`rb>Ll8PdZl15&mN8-iI zQ4J$Ig6>4%?cu<#F%EZj=eF)C2DK3%7b@FtW=DIrEYG}hCeCKP$wX7q*3let-IS3v zC`|=JQgVnl7g8R{z+AS;7VloFP$TfRZtik7bi<#bptg6M##|R&dKwnbTD^gB-CkZ* zvX&3|gqB8pwg6>&-@GSqH(4c!*}PI*QrbM@0dxO`*+j5`>QzFdah;Vge!rdJcI0Zr zILRsh+4v}z#5#JrecXJ~nXFxxWSXPzibj|2{&p1~g0k$U!CEunt|FqPV_^Z$fXB%- zH<}sE`h0yM9Bnh$+rm&oBegZZl}g&S8#-G|sGh^vBx%|qr(KoYT+mI#ZM=cXqncrP zb!KnJQm}V<`DA+-iMUmGxgm=RTY~MWcYQR~@xeIO8cnx#vyigGHZdXbEdD&jc-^#K zT6iq6QdC8Mn8{c}s&vA@8ZA>-bz}hj59~UAd6^u2Tm}7s(rBAYm5mXfmO6ggi%?)hk)|N5~-WyU9dNF*XI|XMB|aILRRh4QwzgnA5Qu zwYJvS7oo*KoPP8|%j1%nxJV)`&NVVBh%DkbxU%z_ix+lOK4gQ{R&ODa(O5BfojHIw zl~J>Aa*;i`q81$$29N5_i4jS_p~M8+B`jzZ{4ZUk9f{N1$TS8lhPQCl~ZAR|Y3mqb=Fr4Z)hU zmlkGr#a*erOYp=d&{H$hNAX5#(ixXj|Xu&gues#;likiA8-1jAxE33rx}9oS8Y}_vMO8i*KIHboNA&; zm_>gdYA;&#us7;F4tA9T(N#hictR?#xu7|&a5)0W0tdAVHec+sb2F%Xb^p2Y!DlLv z%!xNCMSW8G-jgvIGi$}>st>=(+DyUQl)?QyTSne1muc0w;_z8mMPzGy$ zKhi-T_bDvGE$`>h-6?P_=G!#za~mx8KW`W}kDK_)9h6$+seR8g?=OV!A;D~s?IxZ1 z3m#Js&F^?Jsw%aoA%8@@eeXAuZ(rB0yU4Pms(utl>uA|!UAfu2pB)-kG$FZ2+)?jz zpE(axLXXp zKU?g+OEL4S$qQA-ozMt=IrmBrpTrc!=dO%0j_FsJ{8@J+>7QKqm`p>QgHo_{t;RzX zHruPam#AkqP!dl5s$-nJ7(te_K#w%4BTT333Iq+9-b(A@$lB+&Xzt_4?F^pV0nY)k z-X(ESoO&*9=Y7Z(!PgAs`4}Xqn_hQLiu5F1Kv_kZU29FAZTSV;kyAktQE6L8xyQf> z4$>rG@BGM414cdgW#neTSyJ`VP>v}R&Ov)h*?lI9GMzoSwZ@|s0wWG5a)(&A04J+i z&^&rMcBCiV&4i!~vcX%A}ruzsnM9d?ZUL8==rhcz}=d#KVKegZE<=hDKBAF?WB=+^yWo6aZ#^ZDm zr7*CEQa*irbQRqh0T3LFZBp>^f|#hnWhu;7K;ouc+6lc;ycbKR;;rYc>we}C+RZuj zY74T(wF&ud>ld(&BLvJYp~3~1GlAy9&s%q^A6DqnizSZc#Mr|TKM#Y*$HiOBqWBi^ zu5RO)Hc?sjJ-u=9$b!DTIv^(0B+XJ&8Q3rxAe2xS`tWdvoN35-iMWj^<)*lXBTz)4 zplu#WaavTV;x_U`^iH7cEe_$j8Vfs1*W;|FEX&zUSf8Rj@;dbPHh!2qkFx2!OGs+_ z-oN}*Csa^X+SFp98s>RGuih*&U?O3X*&*zmOzopRm{Csi8OCGC{@t5#Sw=QWV5nTHT)*<^*NY>BC4 z(HY;WnDa0dT);b=_c9GlkNFI%9n3K6ItMYz>r9*1aaD^fI92;me}UXlaFXpwX)|`; zFSJCqn7KFwU)2syT45By+D(%uY5L$izIuiOe#Y=)T~uF9>PLaJh`d)!SeD$nIns)G zD7*0`D}VKqQ2>zi7`!7+8e9Ti?jP=>M5UrN@airZ&Z|3UJ1(A^A9*G{ zH;_h>dXjLHA`YN4~IRw|9xB)9j9y1qQTux}!CAVRyo`i!K265YAX3*_)MkcOAQPk9hQbLFGUtl4|8RTCEHMZnSvX)o8t_Qnz!S0>@W<3)d{E)Tl&YD=@ zW(y9{;ZW}fOSl3Y@`w1Elo~M{@wR#8A}!)BB%(;0iR*TcCrc-i($i;Ehao0J4j_dDQL4#A1~XDrr-Rcp|6Um?rm%Flj(jp_XZ`tN$UwGA3M;k_qmVy^JbLxz z8U0?rERaAqd7EHWeLeNXn~kp;h?J8K@OG8$4b@65ALT|kk$oD=h z!}7$_AsSouxI{URxO6Xjo4P;7$~31PqM43>jXSO`U0JnogvJ6LkhHbYZGWZ^=|#~y z)jz91xaqf@7ibJx5sMJ6zb=VHO)HlC?l0*cKrY{HRr90U3W2y5Obw9B>GVRKAyat> zmSGg!J}W>&HznFNDD6~eflzETB^jrKJZ7>Dmfn3WBul3#4IU6#$o1ULJs3UZTdcE^ zm7Ns%;IETWbN}#00zjdSXp- zmAFrkur(_d`N~iD^JBcMiYgu}c;#t{ZwY)}W{*#!Yr(eXe?q5bU8T5%=&<%WJs(&v zuI-Zr*=NAqHbYRZ1-^2YqT141G5f5(X!m+fcZ!gN6{bC%2A-}px&J&Sa(Z6@o^>$WP3j?FY@s&<>^J?^b)W-p>-rIivi4KQJlggBC z#pAT#O?W4@DF6MHZ?$Dd=w*5JPrDJ{IFFF2v{NLTZOZ2BAjUNrp4-JHRJO57;c0W?{Jda?w%!%xbV~Iv)_JgN5{|u<{T(g38S;nY#Tc@bvl&N?+{)CY zFASkR(!cC|Xk-L`7$wsyBHE^R3-D&dT8v;0W@w10FT;RC##Hw+%UIb72i{)nqF1Zn zFr#mMZT?m&;ShjqnRbu#A=?L97{GMntH9$yOV+h|$8n*BcoqB7n zoqNrmdvmk2w8@))Jtn(Rw+~P?YPt#3y+18yO%rAXhv|-r*{k8$xAJV*%-kIZ2;jH( zPE(?u$vTnL)2kE&^$Mq0k?_T5;0zgg)}84mp%y)kPUQ8Q2pl>$a5Sj6yJYdqS!)uz znmB`1RFx+#eq$X8=s`VYT}5?|FtprS*y?Qv+5dhH{~c}>Zj^6=7yBvb9QOIJ+4kGV z=tIR@*g4U2ZdXzR-5#A|Crkpmm9-Bogg#t^kOQb6cEJ1*TazQVPvf82=X+Yu#7$@E zE>bE7d@{00TGQp%vxJn1GNQH9k_>1gdoBFr*0ip>5mcK%T%~c3<$=~UoA!;Y$?kTH zc|Acan?~jOXuGiYa}Z4QZC>T_aEtS*KQ%WCg#fBX^Q*1V;H-;r@L0VYP9n4)p7@=G zKLr}pMhyr<`x9|3Q`j27v{(*EZqNaupO+t~?z2=B+EBi~FCWa*dbl~KW~Bu=VF~c* z`3=gl0n9`^<|Dttc75qTq9tz%Xn@~d?v!N;FGG%7oq28tKRx8Nw;Ori5;`7aJo)J> zB1Eh=`qq0$OmUm;2^la^Mg&MCi-RJ5@5a%?i^o9V?Fcb^iLj?>6qlwZjR4ggF83=3 zz?<-CRFQegcI(#i(LPD8X-QU4H8tF1hkvJX75!80#rC@H?+P6$@DA~q^xiN(e-C5k za1%$Z^m%qeOf@eD$*qg8o*fLm{p=V&9(!=KaQ1k_6}zeI^J5+o0kd9ds7><5)D&zD z!8MyoUS%3FC0*N6gk+_g(M3!o%Bzur(*(s)m*ek^HV7ENmC_ z&ri?&^4JiWAFxLMOBBz19c^2K+&Ws%j83{L-kOT7mY%fy%jZtCC3z0D zPmwp*Ygxk2sHc|uhOEsWBk=(~uH;%61l&@S%GG*-lT;-%#e1VSP^Bd>7dZmagW~`c zMlp=9BqmJ?y7^#CYV=K=*$l&RuW1_fa^nIYYxx{==wf?z92o-CYMKfYiJ~^e4n;k* zeneL?5N%zIk*J<=5K0I|^a7g-xg>G3!_JAx1mV4nYFmdOiPnsZ=89@F4{F-)5qC6* zgrj=Z17OL}vV-^m(I77PpuoG=^0X_5?u)8cBR~BDtUWXm!c@1=?au(_3aZMy?Vmm*nR)vFFTc*B zIMTiv3B>X7Qer=-juJ$FN}&W~9hZ+O&3L6Q_T#RuFBnIBm5keFSt0&+g2jNI?2-{E z^nsM%FBl}>5#A;4x>Es zxb!~VPv<+ku6u8fimJGjUGhD}2hm+7Z|on!eKXN=7%l0|m_E7s;ydpuKq7Cu_iU^C z&?H@G`E=1{%eTv0yYSh^a_&m=Lr*koO866aYbhm4P&7sVYL9ui6!Y=?jrB42&3oDN3C%4ar4dT&f*RX6+`io^`iX!#{5uClpF@)M!_Qh+Ywh$lFsaeWbLav-s%KQoYT((O?C?D%uwXJ8e2_V?bw#y6YUf$HxzKD#Sh#z=)a$xEJYs{|`oyRELsTyN^j zq}L;1BW&>28E&snLw%-#?~_J2UI&|^6CeJxZu*I<$FfxbI&f#sFDFXkrSstR7S0om zj<_;!U9Du-0y{zgpX^H6lUeHpTUHo}fEJt=9B@J6qe<9(;eZd|OI}rD{0Ls7dT>~u z_9z1N(ETF;Y_x>87VPE8Y5FF88gk1g&da7V-2wfc6xVUWFuoXcsTzSx{y#Rgb?wO)gD*-L?Cw z)7F7cA)KpHy1O$G=DOFj0>4-;E@ex-W_J)TL|EWfLj;ZJKdQ1-Qbw*t;;@SsG`b** zTrmWRCc{iidqsYIoJRT}#8cDaf7!_(ho13t4#1&JMx!VWymEwfVHWc#sem=-LRMIY z3Y_bq)HO@-Hm>JAIuvl<$l630xdnS?MrQr?{vfxce`p7dFv3pso0kU|{8;YyF<$Nh zUXVO|6l9TJ;JhpU=$7EkudOOR}n@i(QWS5=pm$Xuu}8SRAMngT+)7r z#owJVYB87f=m8{Q-xd{k`8G`%D655-F=7B#*xyN zM`_u;+`s$^P(LnAv)*0g>?a1q16vr7(V5k1|gU-Ta6<==bmiz%DJSL?P8 zxG<_AjMe&yNBpREQQE|2K2!u_L2fe&o%fYyoOVaTZsFTDbem1)CYAfW@bibiIT*H~ zz;2}lZoK9z2K8e9prTK`OwG}o0{+os@XZdtuRb~5yqg~%36#I?w?W`i8{Ju*_{e_} z%N}I|68@Oh8>yEkihS+=bav(^OaX`yL)H^x^(THamx8)SMK`buEtyq+Eu&NCu>aeJ z!!%Sik#)c{ffbTxorfX)d+~rpCw=hXzv22KlV4VNVrjI zmKJyr!LN~mPD}@1Ht0z*8KDJzKr#dZMm|APzsQzYLU4UqY-$@FVW^#v@OXK_qrvR# z=$KJwk#f$Uf0z^$jbzbX)rB%$8fRew{~C&m3Ezu%g(To zt#tIz>S_E*(#Is983{9gAn4i^cC7#st($Eq?*F%ZR;u zR2y{&5uI(Ik8VB6ncw!nPY&OP4gD<+@Jy3IuU73?q#DXwM%2e&>l4m|4liGb)TkXo zV_Bc82?rYYf+_1mDbGCPk%YBknIfFGp@IioRM+?`<`i|3?^;rp?hZFygVGPr0-8jc1>hpG29pqzN+WQR`6TAWBjsb#2PzC8bxLwyC8~;w zki$2fD)_~o5dDOHgn$e~mzb!VpwQ9N)KSNwq0;>Bj{C9q2I!{rz5jaob<_XsB3zP^ zPFzR9S^RznlggG6g+uxyr%JpyQzfAY&klyYQ3Q92=Z7!-wUk%gRbhW+zsRZVys36k z<^Ap`;it|Esng+jj2O$aa=j9dQWR5sJ-;u$9WfeWdFmZcLJ(+7!g8uHtESDTZaoAungW3Z-8; zK@vyiA4nK5CiOw>?MPVEqN0f6Y)j-sO9GImhC*EjMu(<<ge8W$X7&9m^=hgQ#{xwV860=75 zoD$DJJ^(%HH8)**7{}5$Q1E$Awz~T9u~TPs#aH9qOb=n?iqmE>o56Aqh9tYe^VkPp z+0w8OkHaW{8*RPpe0&g5pxR*Fa(3cL>v7b?Z}qF?c0t?qVWX{SrzWn;x2)5;Tf4LP z25eVK!Tu-R3qt%p`yfcJG?W7d*8&I|?2w$!$6XuCP_r}sX{vJxKQ5n(Rl-0D!pK<+ zkkrOD|K25?l48D;#z3d6Vmu~EVo#%FtI+d*D0>Uw%6UaWGaY7TW@cul4l^@%n3?gU z!$~I{W@ct)W@ct)>`eN9`|iDOX12DrRJM*JTUObs<0?z~z7appNl^KaXOhgmO^n*P z90r$N1aGfeeN=?+VJ?I#^3np+d}p4kbo}KwwQyYcjtC+BW4bhaXCYQmK|~HUUU5Yv z^-`@m6!bGLXTLES8eH2%+2#Xceqii;p|FL&=PWKrnQ0FctK`$nW3)nV5JOSrfP(fK z6FErz8X;PYHF7p@i`Zz_HaAqh*CtC&_+qLg7-4%74z<5h8&9Uf?y1)SBtQBO<3HHT z@DqbF{RKFgTf`dLT;g+=PHwXogzM1A!sG6!o5Jv-!E6{ckgA3Iun->J$#&E>L@t$W zdp;C<3tG8#ek@V_E^hYJ_2Cpj*CAP_2>UhdLu8it^V_b^G=?YOH&iL?VEBht_4M#0Rl@2C(dxbS(*pm_%ntO`}kp!+d}9H-*FKOCWH2A!>6&; zNsFKV{3M4S>O4J^N|_hBRG2=zhoK4fDP@F;j>99!W@jgB)2L_*WnJ!MCT?F?o0o&#HL&mF zFErI3)A!-viQ%vGU6r(@94XC{#pKCi;aCI%nM$(o5KEdTW~#A&`o0yy5;|(RFp+DO zEL4=w{m7}TkGwG$@F!=q0}alN7o9D~o-Waxm@w_c6FZC>XFYju|sA|}bz*H(!U)O4MMQw!Z zP+d6;xg5vZeb9b*n8zqu)Y1nn{k(z30r}8%rI1Z@Dq>e-7d~W^zM1?v|f#w?MO#LxJmxY~p8%`g1$c~N@oM;|Z)#=V{MsvZinPv9btv)YdpITK zPb?tp>wb97H8D$ket>{5VTueI-Es!!d@D4xf&?agX@~f^adMNucdOyohndi8{K&0F zfgWKV>zB+SQhQ<+%G{`nEuXB(Mn^%*ZDmlvpB1^r&MF@4#sz zBn>|SBad?CC|SW@GF_TK5=U~RV1?iANtM_K$-9U23-53T;Wv14cqIIGsJ*~4u)FY* zeGrHenj9Wv-vG!#G8N%1D5wKEZtda%Wik&+@i;AKPO6NH9$46(Js0e1oou&~vMyYD z%{1UE_)pvG1scT;`66bu=5^~_*n&rbuwgl+?cXw1Iz@MN%N1!NC)@N4+`^n&^jR+? zqOFgwkt|@)cJM3QN62GL*Z~fmZr&|;JMLOxiVip<@zbnb3ts7Is*0X|*K;tGXL#K$ zxNf;sSy0<`ni-m$nRTm3jO}Anbs^NTpcB-185t8t$`q}4kFp4Tnsal#8IoE z`qiv%Dafu6POh46A+rEmfo@FfT``Di9u9o)GJ>_8U7r|L-OgSJ)Kr`ML&U5llgSwp zG*n^ehm?2Dt@w9NeDH3jZgYErz7Yd~pc{N{pg)Qgy7sf%)!msUz0s9GOA_a)aPH9L zC-vI+tshHUTYq$hE<@M{(v+&XRavk4H;Og)i^=K0g*uydcibUV>uAN0a(| z_Cof$s*2xVq)!Om>Il2)fkO}dy@J2+W)Hx8Ljuj#-<69=W!=mvW_618qgP>DHx={& z#he08dodkM zwe3Jc%;w)ikoLg#GdS3=4y2?alZK&Hozn^y>Xdj!k5wo+%0$w~wd;EdCccN!*v`qD zZGD<9v9jcIPlTuwTJVW89}0}vb{q_W};NL$^^oVVw#=V`Sq(blaj zX}g2yavJjApYM!=~->WZo2e-ZuG|vejN6Bjg9E~j6JVF)kK6Vk%Gu8+D8x@LH5L>w_JH(lzSd| zU{T-tUrRt|Ltqd|ol@jbN(~2%(Rsy(1=pUrX58#N_erD>tX~v8M(X`HP~qkEJ$l4q z>~wt%W#jc6uLX*o-*qiFm>2{yuU0W($2I>vCzz*>Rt}t}QOFB3w1Xr~DplG*H{R~0 z4%A8BS_&4dFc$eoQMTAd8MMe^p8SAB@TV9U2a=t!Bzb~S1^GTOCYcoP1RB=c5~)a% zh~vySOU9!blz8TBh9oJ|8jlPfjWvn}@h}U7%zEfEjFE?JFFeR8(Mj)`jixBWJC%BP zf1t$H#PNF!E_FI;q+*7#sT&eqJb6GEY*6(XH_z-RG6T)*sYODc8^2P!OrE8LG1e|R z4j*(tJX~SXkp&2kouzx0;#40g{8{&S$_S@O92TejWz-hoI-xBJ_@38ZoN)j=B)61bRoi?fwC5en3)$jUahaVht#L)T1YF`!}wHJ*u(Xd@w_WgX#){59<5p2F^}%} zCM}CnG@3vE(_MWm{$5pDtx3=Ra6$cK+(W=!h2)p{rk}T2G~fCsw@*_`Ri)3w)YdZ{ zp(p+Ef%kgOFmcO!Ar*jrzOCnK{9GemqoKPLNv4b@2f5Ur)gJUW-u1Vc{bF$%P0R};qWd||0Tf7P|VmsccY9UIF6d=LK_Q1|sX=+FZ=H71X zb5399dm6L!Gi=f}!Dx4O(8TK$A(PEyE|{N;h)FkBNVD8JXqO?|%`lJKZNXPCeVp+F zWzNaief{3xTbi0ZK!+o_$#mVB6X*d86SemJsL$juF+0@YgR6JYk%(U_znGN3FRPL0 z9v+`PzuPVHv>z)w5*8lJw|uRyvIQ7#7jk{~iLHT5>gQ|BPvYxprak%X9ZG*xa9Pki z(@d%zmZlsJ&%r9TWc`E2EvLv$*Pzh)8}oJj zW|YIZLD~-{yh~<+IfoBg6Dy8jF=>&hHBytf;I#p>?cfXB6016^qBG8W<=>wi=b|{F zZM3p(xRaC-r?kcK8hg_3zk2*He|x&+bWI)>T5Y6l@MIfiO^#xlgmH;@(&udD2vi=K zcKi&=;P=6X;EVsGStd=Wjis}*)y0Xd<|+_Gp|(=0@uI9|X-dLmKvy9fP)IcbM%~@+ zps`G}%_72cxz{5e%?BI^yaayUEC8bERRL4WJ`dum1iuJ^4iX`2Lsw_Z;erWe|F}dmZFRc1smTdDa z26y*VkK8c0CZwb1srnzSZEYD!gM&d%&{07F=*_w_h{_Fy6t8%?EskTm+EPK49Qey0 zBYp&)#|<}h_gIRL6~&o;C>$5R&z7p1$*s-^sC=$aO5XlYU!B8sR{eol>M2z~D);|a#wmCa1+ z;3;jC?J6;q_=3}2J*=PkRQrf>(&As^UUz1Cci1?O)R0jmrEBd@sp%v-s;arzhdO>eOL-JH*`MU){m!uh=AT>Kfz|1rdnJS1|eI%ql9kP*W0(t)*3s_=5x;SBmSPdvF4v$F zP>6p=RIH`tS8%O|uG!Chyy1bDoDip}=Q>cStziPU-jvZRYqNRNIAIAof z4akAmgvCSnl9?{M^dR04;KR3L@!^Y20?m;okAf3Yz8@Ps>%q0Zy9^w{?xpQy zVcwIA+iI_9+d;7KF*m$^%LQ$drmR}wC=2cU^F)|BOb@e*GHjfoRg#Dy&irB!b}n;y02Z=#flZ4hm5JC2d@s;@xNAJ0H&M9NvS&B1&Gz(*`!etw zw4LtpVpZLhV~Q3k6q(DXt2NvF0xc%}<%G_L+$+)c2eX=lu9F%&1gab~gp z%O1#-DmlR`Nk{eZ<)ya1qS(mx2>Z|3^3EO+%@-F2`9W}KysQ{TRUYZkE7{caeKAC4f!T8EUSDEj4Ee+Hn zIx7|&rzxa1_u?9>Wf^t7qz@skKSPJ1)`uZfJS$|P9}i<>d|~TF#eFF?RTZQ}ngwCS z7T?GvDTN9lZcMG5ak>qXn% zdi(g^p!$P7xYSa~V2TbY8H@h-shFd-%$#E$=UZMafy0g-AINwtQT?zmwV5n zrJV+i2Iwln+0H2IzV`nVQk&atud@` z*m`(rcqHbf75#jpkH-Q61hjvri8wTn8y8GRIyUzVnmAZiRZeCT@tnDuPhtevG`AKy z7-g7|IfaxKUarV|KXcw(y<*o}K62BFf^soxm9AjC?Ku>EL37e^sX%$a2(D{yG-#x; zEr7p?zByQGpluiRaorsdt9B42279>;sekE|-Wz!gPnRAGj04PRw8eH2lC-dtxkG2d zKN}Hytp8GdXAJj8+Go~r&|tN13TCBa-Zu@cj-4CZ>x=06QI8vkg1t?08yzYMct1r9 z@(KduOw4%(yninns6NMS?Ql})V-G3G&3v3*oi?l9X>aJ>(F>QN_DU>dVzT~qOG*JB zy7^5}V3njR3u*7$A8d47Fsbc(T5!?qBc`5Q3r@sY@5QNrMs~_n+S%pg@Z!!?>=I>D zvrt{+Aw8+=)q|6CYtO7QF4zQnXz-bw>L!clZnLBw2vPo}>wp7`=j{jaUgc*X zJodaP{DI{yfmM6d?fjmoQ0UGa$cw0Zu~6bR;v(W)1qnxch># z7?UGZtshD55Hyl#81iY5Q8X}TK*K8~a;@i^$OGmP_dU67M!AWXh;BfZ5yv#j&YLR7 z^RVQTglk=M5SRgr#IUhQBS84XSEZA%-ev}C!-NyS6F-El0*8yR%ZYEj;M9;j)Y+=Z zg^1D67~R=0h(UIh*NVGRU@*_VC8U*pEe_EJYU+9mJKSXFFEd2HI3VCPT?x z%rK)*?Or}TFei{%2iJ?H|52xnU>rbD-js~UZ*QZy@V?VNx9kI{y)6$1hee~U#eFJ} z-LtkV$k9f``v4Y6!u}wXB~E&f?!SA4~Xe=>oKsf%Yp-?Dl%EWULtCQ!jo_~|2 z8mqWZCc$l_r<{j7f`Ox-h*f-urO!q^=>x2`nwpz?@#)F+z2_^hNTzOaF$)Hmv(v4G zq98S777urKtaE(aGyv>svDGjqRhNy9%cSsY*_qWP3qp!pihPRLUG(fjKa=lwe+9m#8_%+o@_Z&U#QZUV5#z@>vd8ATWJZKrV-$ zWiWqL_^C-C`6av?r-{E9)bST&9l*3xL zjzh<^1JD{zciHJ9GAoM0OB|9|xk|71%!K!iBDL&~3*f#5x*F%kNYI~i=g4*(b<7fe zI^M`fae?8+IBh>*xxnsULz~Di?`NH1Ej$>o{F-l-mt>h9;o(z$V<>jg%k7i%y+SKE z2b?(TM*$m~?s8DqkLN&1@F2t&VVVq{rZy{R2ZNIy#1saQFxD^+q1pvb?s_>7*l`A% z9)WFls4!82IP@>XiP3Fd(28Ex(wV86=6mahrJRym`P-GPFCyXQgo(kjMp!G+DYe+Q zD@eCTK|NW;Y+R&;UmQ)8j81Zy9hBPv^yCu$8mJaxq8a#?w8=}&gwreK z45cYWi)d)4;q=^2JH(AlGstx_`3azk9CZ!6I}ey`Jt)^gLXD-jj6e{ z8u{#sB5#(nY&vjbPE*?Rm?=CQoK?p79GrF*_!5UBcg-H%XCj)H`|X>Rmq@lZe-QWg zky>xjqZDOspd=w=v92! z+HH)qM8p~geW0ybX$E~-XOr~X9Z%S7Y%(4=WUO_Hn~7Y#_NzOBY|m(v%gj=YP;63Z z@xzxH#PwQIwUt znUUs19)viNh3u96Rwu>eCA{_>bp`s#gJwOWVtPAgEXOHS`};Ac6nsXNP57jegK02v z{v!*|^w32?=O0EiD(dCcnjV-&5V4l!E0$8Z&Gw?Owsz>L%+JiNh*-YwKl22#xy&Se zV$Zz3+pNzfka`V$Be58PGf;7n+BRnH(cO4Lax&zZcMW9=TiI(5r#t*ajyhNjxEnj_c{-eny(#{JQ4WxQ@-HcLpSE}FtgI2paQRmOpd6N#KFZ!vbe_A!xKRyLC$aS6^V0LO zW?eL}V#CxS5X|eunr}m7h0W`qb7X348y9HOtvrc_go4+YPJNi*1V3AVsKa8q`F1~N z2tvc`TN2hC--Sw&f=R51{&Xjkgx$a13uRwER&qPACI@H zcLXUu_AYuynbqy_HaJ~RH7n;9%n@;}4>sq67)hAxS^l%&!k~LHuBIUhV`jtMu%u83 zH@wuamgDh6A=`#TAm4x1>AaU14;^O@>ysDy6DmtpzZj74Eb5MZ@Azd4J$-l29kiKF zp2FPE`McR2vfEn2KKZd`Xv7dgK^@g8MRCm!56B6r3-TZwy#xj7(a4b+ig~nK z<}txv{X@q{8aN`p3`M|99y~Kv;QQOHtDngJN$v>mo9V84sKL>S(&zd{ar1ipMhNAu z6d-pvde&DI7lk9Dt=}hComb3ss?XH|Is82$1zA{1u^IHd8_xg&zr}XrkAm&VpY~?d zbmcH89B~?_X(dWlFkiQctyWn3y`LJJxt}lx5%;DDOg!Z_K7=YL@U`X8dLTK!sHDm4 zxTuF@)swKurNO7?ypIQZe~!%Bo+J1CI+^8LjtjNdQ9N~Vutqh3QwocW#M_{@e&8qN zL-mmKA#71yOT7V+KO_7BfcnKqyZ58|w@; zOl4lorpqV9nt=Op^v#p4#k$MFzHt+O>y72prn%d>&+}S1hVLy$%%7n~u)Zn&+sSjg zthcv1`RF*8pO6LD+$I%49gFex(Q?rO_lL@g5oNm4V|7V!o-MKv67w_5$DFO`84MW! z@65DxkIHlhRCLgl7>~kcMNucnQ8lN;99t5a3fV>1F&mfX`dAz#&tU7Ox$5=oZu%G& z;F{oKDe0j}EHf}}U977O)MfZe{B*&)UAdNH@fI8OfrhToxAP9D48MazG#5@+s;sMW z9i;?L0o-^J32_E+$N>FdL*gfxk6OCrTjSiROOrDmP5i;Q0lJ(a7L~SMa?Ty$WwPKkLsP)Tzk(u@-#-bl)y0+gEtuv#yzGXYCjjG ziz9G)#knIcZw-`(+d1)-={2%wa-c|+y!sa8-b?D2C14|_dOcbX47 zA&%&vSX5Tt-m91Y^*wh|i@FZ|G93pYQc~Aauc4-OQIPh2|ahJ;I4B>Ls zz6>*xr z+<{f{D)&|e{U?$KOTDKmTYYw6BVc0||E{E0c_4cg?XsA@tg^hSNPt0mWmJ-7KjTp=d8FOa8_KqMf>u&IoC zH&#fo(S2{E#?OAillx8KPuSOVK$RsS$A-8Jy&~{n^bFX zj0A1|VQ`xb=6fytm9f+Ofx+^L#oz<>3O(s+-*33$0xVBF9`=;3rQzFg*LS~eI;TS; z-RdBQOF%F%TYm-eL?1D&D0*K%n+_mPHzCu;8gXJGgatVjpjat7iKC%tyW7;v9qA4| zc{P}U_kvVbHt^d1Iw{_l1+$;=Mx_sE+MP0hB)K>|yEZ8{0#3~|@3l8~-NxDCI?%aK zgP)fK+7tsrwzBq#mxWHa9NA{s(GAxfth}!rzkC#+k#P+xj)kk%9EWq)M6^0b^;6nV zURQpIM5gQbGFCpAWrLWCH_oG0eWTLiUG})qZq*JVC%xF#JAuU=1Ly z#FJq`aD(Grm%YB$oDRYv9fD-iUZ=|XoPJ4_Kr^bbKAe4D8ekIWJBo>pmZOn0jGP>p zzNrH~LLY>qg=AZ*dkADq-@x0b=t^;C@lX&bc_XhohXU~*{jvb$JnZ-_85mQrN;^@Y zq}n!PUF@D5CG*UzwQ9RD{LJad0pD=G1rfCIg%Ivp+dFyE=?OajrOU?TvFKU*2DB~G zP(|ta^Ck{64ZxHOyo!+)jThyEeK$DB>=#ALS8E(iA-L!BOF8`8Mv}TNm4QrwnDG=GR%Q-;p z7JLG5IH5-3?;}LeE?xrEwJ!`0q#ukh=4h^zV=u6z6%gW(1% zof2(lf-ekJApd zO7lClMWxxYj>0{>xgmH1weEstR;lBchLA*4^S$`}^_h)0Iu z(t8Ahw}=!?ii6n6;h9Kl6CEkm3KK;hAudhe@4y^#S~tkxj&ksEp$}}UTC?H#e^c-Kki>*$hmHBF2c(e`MG*r8II-aW?%SF zNP?CiJFSj#&LL|ohL68yWmB~u3?HiyZZoSem|Oi6E|jqje5?EDhWgg$eL8QCU)69b@2~)^0rO5$&w|D!>2pdB@L5bO%z4 zCwr5yV#an+$Vx1v77q2B{8|$^wgaCnD)5Dp_Pk0&YDwClLN*m#iEKp<0@m2OGzd(A z*ebD4NzKeB#-ELVF4oNN@{L{Ro+F>a+a4btdj_DpA}&5UaRCUnovzgch~b>uT5`MuwS+K)znyF4!-{=p`*S01v5TEx|7Hx zkZ@~+2z>{c1)5&#x|eJ6v3~v|=_$OH({@xM%}P`_;KZc9I^Lo}mD)$?zFr9qyD{(F z!9h3x@{P&{bHJZ~Pc9)EtCO@YRoU9U{fpwExY3KCL79I1RL zaMTEgrzY6WjEF?9ZWJxWMh;_DWCA?tmmtc;3v2)eb6ps9ogFF9?Tqi!TtThoamEAm z4oz*GKQ3sG3TxBz8pB3r4?fxUkVOwS+vOCKR;9h)!t8NQZ9d$u0b6x){R<(=n}y3{ zVgr}VsY0ENmg3*}KA4Ik)EEam_ zU%m;=6HG(25U8#+-1?J;S7Q5w>d>XxELw_yik<~nl5dYQ`XCG99S7a;o$MctVQZKr ze77>lCL;1u4s*PIxxWQM2e(gnJhib12r>Socs z6dPbNw)gwEWM;~L2Q6wgxg@-J=4|qy7TKK#FQML*2|I?jX8@ zkSHOSb96^@*JF#Vco;LaeKGou^%;o}MIf>B3&?qBELy=Hf@2469zH!l9WlRO5op`` z8R$5R6d$BNPHr_o#+lQ)DA5r1tCwznYjCAS!+KPpohUNoknAAxrZ5P_u5=!DZe&q* ztTP#9#TDQuMA?5*X8o`z>~$v|k3qZ>!r~Xf8s0)?Z;wevuz(~`$RIz3J$7y`*@gia zN%zbspte9&@^CUj@N8RsWckCHOr=$LKQ5iDN|2VHe*PAJ91bzn% zbc0r}La@Etgmsbx)hYF&q8=@91Z?bg{qGe6{hF)7n>`NtACu9}Ac8l~$}nwh<^t4( zV`qhao#(Arf^eovT3xfgM;SPgqKzt!Ru|fO>3q)yS#27T5=tdADJf}rsbr`TneMJ@ zA$C`pVKu2@D(y8sfV`qCiIjBeB?Ng)7=;Mn0leD+-|5tV$7eO<~rf>G;^cBu2sjzCatY@NcyRYWdxkkH5nesR5%PmV)8X2S9l;Kd_i1 z>UlkGqM3(3-{BtjDzL#z5VW)033-gVIXwZi3+N9E@%C7>BJ@iau6sZzfF3ajxZ+?W zE`SEZ+c0?WJ>m06*6xdwt%+Ihr<6wumywDthm?yUmm^DWgD_lWbFc-a6`uB0fOS*c z7|JM*lps>H#=5lzR%4++v2NNMK|!FHLWGHs z4jbwO(V1scCs0fH(Td*s1@KNStMMIYE^lywQybR|e^{t=(v4B=Q8Vl)XVd6AGDBRC z^UE{J6JQ8zs*F?Rpw+HxJ{ydBTKC;*XtHbbo#SizW3V5J#?h+t38fcr$OHXC#K_40KSUV{YRXa?;xsBhY)qZxOx=|1Yz%D`lx0=^hce@@DdQhy z#uwcE-^vVD#;*p+m>Qb=ur>dZPyB~IgPD=>>%f2MGuXcpf2s5T=rg`_6#pAD{_E6# z=`+665dZh^k2K;7MgKSctFZV#xBtrd=WJ+Zj=%W)e+LfczdDL94aL{?C93!br2n^+ z<*PHmiQ|EKSL`8EC@^#4E4 z;Vbzc=>M;W`fv3A*Ii-|v;E@!|9#$Ht`y^cI?I3OK=bqet55&Esee27e@X!UN@Bh$ z|1T#16Co29Gs{@=fQRQRAG@S+{sa@V_!N`I-zl^SZWx`FV_w+q*Q1~A4vU~~R}zoFhm>mLJb5l0j23AY2D;da6L z?*K>D$P$QC#F;|x*bzS1#($u1PERjy8qpe|n1Zxo_av`~ z(ufgA9RM*v2mlO_DQQVHUyj2>-~dh>d@Srt%#C;fU>Bt^!p{X`!kCG)5N0LDMsz}a z0C0=a<$^0lB}YLLmm($tGy%~4GX1ck9;5}htLmYYV!sG~B8dTnMS&Fkhb5ko_(k!F zF?PiE32Tuw0W!f5JJHGJ!n(|e!u{iB%``@t-|TaXKnx|85l;ZD!Dxm;`NT?yX2DQ~ z{mAh(!KC*xqL_%D!SFd^7KoO?&^e-%j8mY&xO}FNRKkJVNVtK-07&leWWh+1PEqdw z&hTg48-#vyqndl=8nJtn`*+M6q+OBzEhGv=0>VF`m?G^l?g%&ZyPUgt{rWZSU7|99 zd{Up0?mR|;R3e|j&&K^K;FV2?cH%N@+pi-1Dlq@mlaQ40-0>rlPrp?W`G&cp)%k+m zFq=JUkDpWSlJ!RKX>Ri21p>q5W*9~6XFk+KN&A7j=vI(zY6t(0DLs2^+Z9Leh!2pc_Dt4 zJP}=ror}NYI>`4!9%lZbHA;tT#<`gT)PU)@iACN4xrs+s_-Bbm;`#Fs4-#$IA;s!o&^<;VWkt#`s4D1`9pCG( z$rPX@3YCkg7)&V&N}N4KNhi2Zf{X+n{Dq#fKuU$Y7y4C-L>-KrBS=cPj|6w7scBDi zZAWNKcoozRaZ5k!aNHr_|Bk;87rP`B9ncPb%X1u}E~NL(19cxMHi!^H5Ffk+jrEfx zmU1IBbrY4Tx}_Q^vF=+9ehoZRWU-J+9=;h#Ab?tw%m|%*1t2L-N<`mn#8YF=Q+@9$ zij#}RgfJ7B9AP2ON`#FB2jBvDisI#>?+A0&1i}a78H(hS%p$4|swvD%_@H zL?0CD1bqSCCmlYTp85oOf!$Y*l^5g(e}VM86p8H$dPm!5AoK(Gz}c54^aJ&P@w|o{ zt|OfCf5+bc5vw1-3+9Nq|C=yOFcUO9kQcP$m2en@@J;YBaGm(^8h!r8tbY{H1A)f} z;6!<-0j|NVfo1a7_<1aGPn1N6PU49afe3>HgUAQ4?f34-0wCtX>_|K-40!-_f-&NP zhQ&>Yn33>GNKddm=E~B?vJT*>-z-bF>yV*gNG>)&&wuh+O)Bw{j*LscB z(A7@Br3qu4Z=%LqOKtX3aj=&o*erMO=WEF?oMDHG==Rwm`0hos`H{G#iGXEHS6RP z)yK?DHwJ)*t%h;}8r&#J$}$HsahWwwM`DdB{Qv@8hN>11m#R5;*pqO4e)N1esgCHZ zKMJnKr?)RzL}zP2r*}6xa>P2pazffLf<3)Aa$XQWVfEE1 z>)UANPplAJ&TYRw#2khk2KYr(ak09&ITepAAzH3)AX-{wJ9$6kaCi30o&Q?iwrj9S zy9k!eJ(bqan5>ZVWBCx}?&7`>#dga{Jf+3Zs%*UGe%`(&S;+KsIjx-MD^bdL?k-cO zu$A6d!)e57_7<7G4&0Fq3dXeMux~AMX>;~+_AavxzXaLHm#dYKc(NdvCJ8=P!Ohn?GZ9jneN^e`ZrnRfF?u2nA>B6!cL@h||J+O$M^>G)rN!r4E5k-jP`)}x*c?wA$@@i9 zk@^#BSX0fBfr59Y$rNbry*ow~mR_A%gv%&+nCJnk#cG|fod7P4%dPl(zYvZO{h85E0-Tgu6Q(wb5HD5c8mHBP6R~~b zTawx|UO{~FF2XKyhPaqwMZ zfRxyggoGiA%M@OCx6Rcb{5(CTN$zqlGURg6J_~k6N21QVTq!?~2kJd9v4$@|@zQul zRE4BIOrV^ce%G1TkQMNDl>Ol~^06Jpf82@SZA&2lzLh1+i+-lptiA=(WymZ= zY{IYt;S+k2+h9RKIRMG3y4R;JCgXu zn?8&mno&Er!zN(B6UOKx1vf0&I2PqF$U!fRca!)Ez=a#qzC~&`2YL&2FpOb>oT+iO zLHIZ=Ya~#+*@pFcA*VQ1F7W7|_JC-a@i5_&efO5_r#V%9lxE!FAkdEo)-lL7@ue=< z;KewjnST-j^f~w3hp&2nV~z9~y!CLF+M5D+{si#7_N(ZppMn*N6n3dg>hM&_&+TN5 z=!;G;UUX8QUOxO-HP-UQVIB4iIB;mS{e=8ce?zAbI>|knPNGhA+frK@ZaCPxM;N*+o3_3oA35 zi`-SFwob~%ed({QtEs0eJ*A_XXe{QxekUfOzWI2xXyUttZr2u(;@opbNtH;(j^!g~ z=8-nZ6<;|8^Z6KtOITP88{6g(@V*v#+=t+8tNMASR|gfGg=NnfffF76tm=m~8sAot zDRonc{n@S~k+BU)P=bc5*qYselj$}O%@=*0{Jc)gFU^}P0s>!zqQrTs1a5_AxO!9! zvs8tHTXI%5F;G_rPqZ`I&pkxP=fd z{@fZDH`WJk$EjTmXKv@o1BTknn@%&o7}5c(Qr==*3WS~1`VeTmj{=;CF}N9~C4YAk z^D?~tDh~-`BAc$HocuVH1vL+633=hft*KiH03T7Z4{mC3%Ucsl(jp-}etHaU;YYu9 z=k3QdB3j!eQXY8&owm+USi*SI=14}~Y@Cn#4Z}zCr=<^>BbcYRy~ysQo6z|47AXf^ z3$m3|cVowZju-UJc(fd6;z{KF55GmfRAK1jWwpKro*a6q;@bANl;$%vSJ#N|(@pg0 zIw<5mAT=t6et7vIL`odJ+@Y$m2W0hbR}>)$cG2iuNSqn23_D1V`&R6P9j-y}C<_A{eaKvSnOS*g-6%L)xoEcf zJYjfoAFhd1)W60nXhkT_W=^3cI2z*JSt-fTgZMI%5IEi4WI;&5g=bU2%TU0Zp6}#K zO$NXP*?OUrUE&4F@{3M`54^1w7}?7d8uM&DF6yB(lc+fRp$8q`4m}-ZFqljQ(U3LV z*sIz14;-)0{kMY|AudomG#Cmwd-Eq|=x8xKK`}*o8f_Q3WR{FR+1;See^ESsaUq;D z4tuYeVPR0roz&gdznS-6+IOg*t1njMdPN^+I08MDXhb>UpV&J@wevSKcyx&+rlGn36eA?RCgT)9Z9z1ADB5dvkc3;4G z)uh2ulZ*15#pbefatv%unU8w<;v!GzYf`+>lkaj9ccYt&1SjXtqv}(nnV`m#F9ea$ z%x~k)@dPmkMu@Qz5L_rD@3TLIL~H#D;m1U+5V^kqzL-$&lvn`A9tHU!j>Q z2w#KH0$5=Tf4oX3TH}qn7IXXjsxVo4qrl2w0qjCyGAJiuvh*?2(`qFRz5i9&cK}7T zG;OO02nZ@cR6thAna#UIQG&bVoFwPCug!7aN%EVLLgV9L<3rGzr|a@W9pW8 z0V!Flngz7nF_m=Tw#c0)gew}is6w=;E@tSO=k7f? zB|+p%wRoEB>f*z+@G7;QeM+C$Kn&g^HZ;AW^9-5I<*yo6c%z^TkcZ;ig&Pu&{^Iz0 zI;*5J^kuKfrBqvAEn@hFoT?e`X-m?8Yub7rzB=WKgzi(s%6sEo&M~yW%CMnQJvUH= zj>zr6^{!3szb?K06nvxjEb^PNC*y4cv`y``&4K#*^k{bqh6Lg#M|1P!wvL8G(ONsN zTG&Nd47Sb*Y%a{R`;2I^ctt#AwQNG4{=y>xmFf<*9w?x6ckS?-_KCNZ9`iYk{Fuh%NU1Sxt*kq_iJ`z!3mJfk(f zktcbF@Z@w`KWl;|MyP%063@rGH^G-kOD_qx%RksDRQoF%Pdme*O2dW;P<^S~7g;jQ zVVB12K<|9v8~Ndbc8LX-Ikhyuz3WUR^<_TZG{H%yO|vsr2e*f^TIdndgQ~YtJQ8 zUlMD{rJ`0=vYb+#f``TvF+TNarC2|H%st0Q83!x$o8sKeiYS5e56P!(|GZ1 zGadtEN~@jAzzXj(mEtK|MeN-VtBA1rp)?!&OV~1A6->a>IQDL+Y<|$tKKq#SYkXhD zW*;q^peQBk@S&Rb#+|(F(7mWh0V=1jcy~?nZiKa3l3JvLO>BR>@-sw%cE<4CN{wdNNeV`Pm%rp0&Oxvc}m@HW|R3o*mqvlbn!p;~XNZQ}V24 zhzPim1i8jDzC{z-cvNfPhC;ghGgL1>nec; zPgREQ4?a4XF6{s@YugjKv z!`re<<0eWk#rTdgCXJ@EATrE_K{3=P33O##P*G@$lWYC$=F29BnfAdXPfrD%>cf}c zcvO7gGlZGC!eDRJ4F(Iny7C6Zpqk0^($tSK5wVE4$t5<|g2CKA?CZXm^9$zYmAJJH z_tDEsG5(|Fi_8$7a(Nn~f@bR<-x|<+vB5Tdp76fI3WX*PWm)3*3C+~Qn^x`LId^E| zlV~R|uy@i7$8uo5-^3(SqXIcK8b)pDsQ8bTbJ2&O~1BTjqol zuXQVr8s(9T!{VBANV0bLLt24hLU>Q~rdNEIbQBG<*~9uZ|5TOt{xr|_jfQSz>~xBj zT(W#|UP?=wrBUC6!qki0?pm1Who1A}u&dZc752ajJs)?YwXWarp~qX?=wIJ>I_+vm zN?S*jk?U=O-w-y1)}h|z|X4vr-U{1siKRfDPjw!b)^nuy3TmTKQNpm zPjiht@)w!)GR)wL_7X`5=rM)0$5A7Y6FSBUW$O#KFFY>DT78e!92@Fg7Ke6teVcp38>e0CqI%->!}Y`_P-+e` z8RWh#Fon>$?9%x)cWNY|BbQcJYaFnTdfdUy29Fu0 z7os(v*0#zSkO!t8wRdcDt;c=nE2tM@GKqOT$nw~#jd^yKd>`4)pB{%@QhEK3y5}WC z679h}niDZ)Cpx~`*qZ98F>P`=evLG6z|GkQZc37*jVrcniU>F}?s10gsbBTIPbQBj zug-J@R)#N=+ST^h&YFx)+aeMyBRPg=gC|@tvH^C|AdY7*V+-NtbZ4D~j1jje%^NFA zCWUalJ};m(H8&dt1$dV3B|Cj;x;oMmA^kp6=0hBDJxx|wFtZkgbpl&nqR4;&*=%kkWC5icV9fof!&b#??JcP5KBHuzcYa*H5(IX+fLYP_v-Z1X6 z)#kJHeapnFpTbO2_fh~4B373#Nw*M$-q zuQZWtzDyD6X{KPAlDeI{qkJ>eX>3&<+)X|EMgA!v=zGA@sVE)u&3`vASdh-m9Y zXNXO^r!}L{gj<4@OvU2Y04Ys5M$_%2A_NU-j82vsIr9&ADrMeW_~we*7QKmTAQvV% zG1qA?XNc1c?{FU^(#*qO+1_@KrIY4<_S90iSWXf?CksZ z?*H{^Qv3N1ZXw6KvnF%?2YYqS`ihP|9S-!}ox|CXy>QmxMiA@W@>2CnLA9K(`KDzc z(4ME9n)GiOJfH{Na{bD#mk!FFTrSlVr?sZEy%6eC?wk%|v-BO7+T(l4#LvHI?Yvd% zk=(oX=`D4fY}EB+A84-nD|3jbl%g&{aX&FWEI^dqE@8_}>D?I_;rl-BJ?CjxM!db_ zHX+M%JKHJZquye^!5hxhGk%4KH@t|nbT;lGUxGCH z<;Co_TNtip{)y+&adw>V96OV?zJ0T>o38e2y5a2RH_|eFyYY2u6xZ+<`r^dejs2$S z!F}^&DqI7x!kasd+WiZ3}Xwa zox`R@V}pG3U5=i3L@UZZ`0HW8_~HBWyz9162 z{1Ntm`(fY%_b(_1PS8tIu1)b?3}e{3vwsZ_QN6%*nzQsG6WLV6L$rA!X41nx?-S|= zxQZqmJ`)OK6OE&9zvft`Oi6##LXeO(k~LCxPLRn^>SZ$ueU=Ut=G*@e>uV$6?F8)5 z=N8Q`bvOCr<23i#O3Kgh+STjz1oEm#mVQH-l%O4Y5eM@+F~p48=mrs^cSqYGC2Sl89z}ot7b}eHVhk|d1dp}X-!}{taXM`a{ zF+u0L8^^GlbJmaY*Ld6KEIjJ!?z8E1!d_+Mar*U{o~l7uMklK;(QHI)#Lf+!?JJWv zWhIP)iK^KI8%Pp`3?(T`jF2|$2dX}WVe}&iS{Ggce&GUWs&h=6INjV`n#EO#l4gAs z$*kP!Mhs?Pnp2Zz{W2z9&RIbW$rV?=AjW0%Xsj@ePcl8u!Fh_+mwL?&qjl!_8cf{M zwK%*=kc8=C*HKjt*Su=_hz**kSUoe>D)c7tO-`{3*&UBFb~vw0f#XL25_(E=&6sdi z4Sk{A2g>oX-Goy0AMg2eVHA*7wB2-o>yu=!jyL^Rp|b6MQQt0@TRd$xOP&y}_tG|L zQb<$yfW`!vcLr3BEbrLIYuB!&lxuv|i97-~J75kO?{mv2?mP8*ThvGOVKyW!@_XzF zR;qoELgX*tw2#KKwnko63%Dg!f=x7XnC+DdX@vKLcjNA|O|S5!F>cG1sK*I>?tPfu zmd)|p!<)v=YuO4;+@JqqEwf4?k$@3C@;lqKfKV}h%YaUPGp^ZrU;oXs+3q4SEz0*s zLtj|TW6tZB zxqelN(Q2yi#QB&*!p1&SkZ*>-AH0f?Gkkp8G2&|v-ro+KU?Tiu*Vlxr@QK5v9x-hL zUyQOYOpQ`jTPgY1YLZDXh9pxjy=SkoR$4 zWfSI;s!NA$-daQCmhAaYH-+lnQx^4+2CO;vAk(7DFi`DN{Z7;W^v}B3q?lF>n4-V0#CYx({(}WYS zy_mz?rV|iisIMyR`{f?Y)bcg8i3R`S>+WXy`*j_VCkzw`Ki+mCfECTP_E6A3cXO@+ zPqzboW?nSpwdkH~=)`UQJfVys_q$730A0L3?h6;^M3CX?7Bt*hvbwNs6x+ zZZFx^%ud`$CVfuAk@sp;oaFnvt`FB{&UuruHF$fs61A%NvQ%xGl}xSouN~sf2{)>j zk|no~@*tcHyNBf0uXQD;P0%HxdETmn)!qGQ#RqIzm-L!`N zQ{DE3uPl94@VaGV<`kU%kyWqds)#6Bcsx9&$aA)1?>Y}}PL0K;B2e{tWn#sJVBA`s z@>!Yg-Sl(h{EuG=*FOnbuQ(F#UD@0&qX--BoEQ@^_BC(!x9AK@RL)k)nXeb!TjCB> zS{cw)JJT4~x@|_HiFt&3^VUI4r))KxvAoR6Lf6V&ujSbYVLEA|JZ}P=r8w|xC&quz zmD$hPXDDT2)O=f`rZFY~LuV0QA=j_57_G9`jlT=XSx2s6kKba$6E*>eozMnQROt-fR^}w1TT@ORA`XuVyVmc7K&+vf} zblT2mzSCB#0n8wF(AjqeX)dpdG`AXdKQu{wjH>~E&*4fvIQr5lcQbFCw$aen!)~Hb z{(@e~jfQMnBrHSNq+`aW!-p$>i)>Zit-Hhc&*J~TBwnrDGMhb*{CW;Cc zPJJu;Toj;TpIoDVJ2hrlQFws5M&Q-(K-SSp#c(d}AVN|2h&#e6zxzksC8Xb!6)7Sq z6lyV;@6c|S27yo62dXNXe``=UQgNF^TXnxA%WPX4)|l2*Q;M_6G+Ab@FO;y@nc%qG zflP^d-}Slob)oh|4_}3(ybNgA*3sd7K6*B%61uFTwI$|`j3J%Shw8W zybSzo$CQK~aS%ltjRep4(ZWx5Zo=cHgmPi(-7~5JU|*E$Q<4LZ4hCObv4>1e=2!vq za!~UyKY3vI(W|UvmG8~I_q%7pXRu- z&^(QA#otVgb82?acb*>_m3CwQeBl+=!_8K@!0>x3)ts9>Mkx+I7M~ZDjcAJl3z~nV z%9!Wr!XYxG$^}wxRU9d}yln#xEzToC%$UXE6+BzW7|tg`g{3B3RJ+po_!LUlOKk4C zykf6vhWQavCK+3t48Xewbkq1Q$=i)Jx*sNIp^O@VWWz8xKKX8V+Nb6NLtB6)) z$zSh+^x^BR)n{)}6b_wnE+oF1Q7bkY028(84h*)+mvc61AQOlH{;edHN~xq>yX)p3 z!6P3MA+&_t-!QM8iDE2H3&)Nw*%BM~b0A9U3|NPsubPL_T&q;D>AIMASn;|b@9;T~ zINyWSjsajFrz}jd{}D^i)|JwsXu-|RO=l0Q$Dc>n;FIccQQYEN5zXfX8gDU}{>A2& zK7nWS)@$o3cWd7dgt{k#o9~#v?#1?&ec6qwG7hcG1kR?)F%^dRa5YqX?+HE}3zt97 zIQo2xjJg&pwoBmY8Zhu(iOJyk*mzn0C0xRHKTRxHiJ7D40W!Y^9x0izc}h)|R3=7X z`x+m%@S-=VOyQ+r=B6@bHJvD}d+lak4r0&cgYTth)l@zl(=I2JeUmF2*t2+;>0_NT zm13s69{AZI_FF{b1_7id8FflsNYb6jJ8aEM#e{I%j5Q9 z(?nH3zwt(oDYwT~&;`K(t}+~o0zu($;2Q~K1HwR17!sh$0u*2f;wJ_H-tzd_&*u;* z2nJLQMWaCoK?Defgn>|CC^;0M(88ebpP%F32qXf8fTIC@fL;Wk3m^o;5nuoV$|Irw z(RZx-KQvsR-hcC1j|s*ApY{JDuyqH4wT8Yi@+lVlC`axWiuSOqb&X@5czip!B^nPTzzmK~ZXC#u4^S-!i zbHO9|v-mn=*T{IGmE052DPOzKxK(tbNTnF_ndMhr-r36r9mP|Olr(RYeV)$cToiC# zo+X6m#E*<3wx)EWJHS7xU2uzDM>G7|dQGs(($Tf8b0XN@j7s*cnS$wzr6yl(7_fJf z6XkO}r&j%H78S9LdsfBm)0G5Da$0%TJO^LZoy_ zIaQbAhcoIoWl%<|((6ng&*n=Wm#Cooc#m8wOTDd@)*+(-KxXhy9QcW+t-C`U0?zGU z45f+Bk2?!iqa?x2^HJ|t|H}|P?(mlGY9>| zfQ%9}kY(}n8OZ)`Oi&PsI&Syz^$UZ7fvEvd|2ua4`#1sOPYj8Io+u0GLj%$Hgd7lL zPt*$*grkus%7O*a2*|(6{;cs2eNZS00z~CMF$4q!0Sxt1`akdX^X?A}umN1~gdA89 zfjaJ*-^(7i5B)C;fdbMIPRJopK$6A@3^4P_I>10tV0`{r2O0s)Dt}^toZtx?fWau( zaSF;GWx*%}Fl+vSL4bZc_MYG6Ab>s~>*oZ9fFV!R0mwms+3tiK3I@!WCo#lvg39sr zyT2Sy(_*Yw?zJKY<~EMaapr0Cv*OP$U!uKKUL@U;_9|C+AadON67!vVsIn>EM2joz|YUN}dDC9}|0Wkt{(k=jYoR{{ieJ)N$ zR<>qNKNELUt-OGc1uP_0a5xtrtL*RCg|RosfdDPX!4D$|(glei%>>bc=B7aJz)g@~ y6C*eZYzBuKn<0%*fG0!IV&wm~2uSaE8R+Z+Oc+0d9TW)%gVE${Y*LESFL From 9654382294dce7bdde7fcbe70e6f2f2613662d3a Mon Sep 17 00:00:00 2001 From: Soonho Kong Date: Tue, 24 Feb 2015 11:02:06 -0500 Subject: [PATCH 173/315] use 'defaultToken' for comment/qqstring/qstring in lean-mode Suggested by @nightwing --- lib/ace/mode/lean_highlight_rules.js | 36 +++++----------------------- 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/lib/ace/mode/lean_highlight_rules.js b/lib/ace/mode/lean_highlight_rules.js index d5f9a67c..44eb8d50 100644 --- a/lib/ace/mode/lean_highlight_rules.js +++ b/lib/ace/mode/lean_highlight_rules.js @@ -151,36 +151,12 @@ var leanHighlightRules = function() { regex : "\\s+" } ], - "comment" : [ - { - token : "comment", // closing comment - regex : ".*?-\\/", - next : "start" - }, { - token : "comment", // comment spanning whole line - regex : ".+" - } - ], - "qqstring" : [ - { - token : "string", - regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"', - next : "start" - }, { - token : "string", - regex : '.+' - } - ], - "qstring" : [ - { - token : "string", - regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'", - next : "start" - }, { - token : "string", - regex : '.+' - } - ], + "comment" : [ {token: "comment", regex: "-/", next: "start"}, + {defaultToken: "comment"} ], + "qqstring" : [ {token : "string", regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"', next : "start" }, + {defaultToken: "qqstring"} ], + "qstring" : [ {token : "string", regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'", next : "start" }, + {defaultToken: "qstring"} ], "directive" : [ { token : "constant.other.multiline", From 8f49d3d89784095089bf0885268b4e87e2fbc69c Mon Sep 17 00:00:00 2001 From: Soonho Kong Date: Tue, 24 Feb 2015 11:03:02 -0500 Subject: [PATCH 174/315] add a small demo for lean mode --- demo/kitchen-sink/docs/lean.lean | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 demo/kitchen-sink/docs/lean.lean diff --git a/demo/kitchen-sink/docs/lean.lean b/demo/kitchen-sink/docs/lean.lean new file mode 100644 index 00000000..40e82753 --- /dev/null +++ b/demo/kitchen-sink/docs/lean.lean @@ -0,0 +1,9 @@ +import logic +section + variables (A : Type) (p q : A → Prop) + + example : (∀x : A, p x ∧ q x) → ∀y : A, p y := + assume H : ∀x : A, p x ∧ q x, + take y : A, + show p y, from and.elim_left (H y) +end From 74800e84ee204d1fd89a82bab1d71c8d8703e1c4 Mon Sep 17 00:00:00 2001 From: Soonho Kong Date: Tue, 24 Feb 2015 12:09:11 -0500 Subject: [PATCH 175/315] remove single quoted string (qstring) from lean-mode --- lib/ace/mode/lean_highlight_rules.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/ace/mode/lean_highlight_rules.js b/lib/ace/mode/lean_highlight_rules.js index 44eb8d50..48241c0e 100644 --- a/lib/ace/mode/lean_highlight_rules.js +++ b/lib/ace/mode/lean_highlight_rules.js @@ -108,13 +108,6 @@ var leanHighlightRules = function() { token : "string", // multi line string start regex : '["].*\\\\$', next : "qqstring" - }, { - token : "string", // single line - regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" - }, { - token : "string", // multi line string start - regex : "['].*\\\\$", - next : "qstring" }, { token : "constant.numeric", // hex regex : "0[xX][0-9a-fA-F]+(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b" @@ -155,8 +148,6 @@ var leanHighlightRules = function() { {defaultToken: "comment"} ], "qqstring" : [ {token : "string", regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"', next : "start" }, {defaultToken: "qqstring"} ], - "qstring" : [ {token : "string", regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'", next : "start" }, - {defaultToken: "qstring"} ], "directive" : [ { token : "constant.other.multiline", From 906b6c9d8d8c6443256365d676a6e0139046c099 Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Tue, 24 Feb 2015 09:30:43 -0800 Subject: [PATCH 176/315] Adding cursive and fantasy to keywords list --- lib/ace/mode/css_highlight_rules.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/mode/css_highlight_rules.js b/lib/ace/mode/css_highlight_rules.js index b9c20423..d08a3a0b 100644 --- a/lib/ace/mode/css_highlight_rules.js +++ b/lib/ace/mode/css_highlight_rules.js @@ -41,7 +41,7 @@ var supportType = exports.supportType = "animation-fill-mode|alignment-adjust|al var supportFunction = exports.supportFunction = "rgb|rgba|url|attr|counter|counters"; var supportConstant = exports.supportConstant = "absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero"; var supportConstantColor = exports.supportConstantColor = "aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow"; -var supportConstantFonts = exports.supportConstantFonts = "arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace"; +var supportConstantFonts = exports.supportConstantFonts = "arial|century|comic|courier|cursive|fantasy|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace"; var numRe = exports.numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))"; var pseudoElements = exports.pseudoElements = "(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b"; From a0fe09f3bee4197231b18215ab8af02f32146755 Mon Sep 17 00:00:00 2001 From: Soonho Kong Date: Tue, 24 Feb 2015 13:19:56 -0500 Subject: [PATCH 177/315] clean up unused rules for lean-mode --- lib/ace/mode/lean_highlight_rules.js | 47 +--------------------------- 1 file changed, 1 insertion(+), 46 deletions(-) diff --git a/lib/ace/mode/lean_highlight_rules.js b/lib/ace/mode/lean_highlight_rules.js index 48241c0e..f653096b 100644 --- a/lib/ace/mode/lean_highlight_rules.js +++ b/lib/ace/mode/lean_highlight_rules.js @@ -70,16 +70,11 @@ var leanHighlightRules = function() { [].join("|") ); - var builtinConstants = ( - "NULL|true|false|TRUE|FALSE" - ); - var keywordMapper = this.$keywords = this.createKeywordMapper({ "keyword.control" : keywordControls, "storage.type" : storageType, "keyword.operator" : keywordOperators, "variable.language": "sorry", - "constant.language": builtinConstants }, "identifier"); var identifierRe = "[A-Za-z_\u03b1-\u03ba\u03bc-\u03fb\u1f00-\u1ffe\u2100-\u214f][A-Za-z0-9_'\u03b1-\u03ba\u03bc-\u03fb\u1f00-\u1ffe\u2070-\u2079\u207f-\u2089\u2090-\u209c\u2100-\u214f]*"; @@ -117,13 +112,6 @@ var leanHighlightRules = function() { }, { token : "storage.modifier", regex : storageModifiers - }, { - token : "keyword", // pre-compiler directives - regex : "#\\s*(?:include|import|pragma|line|define|undef|if|ifdef|else|elif|ifndef)\\b", - next : "directive" - }, { - token : "keyword", // special case pre-compiler directive - regex : "(?:#\\s*endif)\\b" }, { token : keywordMapper, regex : identifierRe @@ -145,40 +133,7 @@ var leanHighlightRules = function() { } ], "comment" : [ {token: "comment", regex: "-/", next: "start"}, - {defaultToken: "comment"} ], - "qqstring" : [ {token : "string", regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"', next : "start" }, - {defaultToken: "qqstring"} ], - "directive" : [ - { - token : "constant.other.multiline", - regex : /\\/ - }, - { - token : "constant.other.multiline", - regex : /.*\\/ - }, - { - token : "constant.other", - regex : "\\s*<.+?>", - next : "start" - }, - { - token : "constant.other", // single line - regex : '\\s*["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]', - next : "start" - }, - { - token : "constant.other", // single line - regex : "\\s*['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']", - next : "start" - }, - // "\" implies multiline, while "/" implies comment - { - token : "constant.other", - regex : /[^\\\/]+/, - next : "start" - } - ] + {defaultToken: "comment"} ] }; this.embedRules(DocCommentHighlightRules, "doc-", From 3c34a9852f54637106a7888ef99e329e82ecd051 Mon Sep 17 00:00:00 2001 From: Soonho Kong Date: Tue, 24 Feb 2015 13:20:28 -0500 Subject: [PATCH 178/315] add and sort keywords/storage-modifiers for lean-mode --- lib/ace/mode/lean_highlight_rules.js | 37 +++++++++++++++------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/lib/ace/mode/lean_highlight_rules.js b/lib/ace/mode/lean_highlight_rules.js index f653096b..91440169 100644 --- a/lib/ace/mode/lean_highlight_rules.js +++ b/lib/ace/mode/lean_highlight_rules.js @@ -38,20 +38,21 @@ var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; var leanHighlightRules = function() { var keywordControls = ( - ["import", "tactic_hint", "protected", "find_decl", - "private", "opaque", "definition", "renaming", "hiding", "exposing", - "parameter", "parameters", "begin", "proof", "qed", "conjecture", "premise", "premises", - "constant", "constants", "example", "attribute", "local", - "hypothesis", "lemma", "corollary", "variable", "variables", "print", - "theorem", "context", "open", "as", "export", "axiom", "inductive", - "with", "structure", "record", "universe", "universes", "alias", "help", "environment", - "options", "precedence", "postfix", "prefix", "calc_trans", - "calc_subst", "calc_refl", "infix", "infixl", "infixr", "notation", - "eval", "check", "exit", "end", "using", "namespace", - "section", "set_option", "omit", "classes", "instances", "coercions", "raw", - "add_rewrite", "extends", "calc", "have", "obtains", "show", "by", "in", "let", - "forall", "fun", "exists", "if", "then", "else", "assume", "match", - "take", "obtain", "from", "axioms", "fields"].join("|") + [ "add_rewrite", "alias", "as", "assume", "attribute", + "begin", "by", "calc", "calc_refl", "calc_subst", "calc_trans", "check", + "classes", "coercions", "conjecture", "constants", "context", + "corollary", "else", "end", "environment", "eval", "example", + "exists", "exit", "export", "exposing", "extends", "fields", "find_decl", + "forall", "from", "fun", "have", "help", "hiding", "if", + "import", "in", "infix", "infixl", "infixr", "instances", + "let", "local", "match", "namespace", "notation", "obtain", "obtains", + "omit", "opaque", "open", "options", "parameter", "parameters", "postfix", + "precedence", "prefix", "premise", "premises", "print", "private", "proof", + "protected", "qed", "raw", "renaming", "section", "set_option", + "show", "tactic_hint", "take", "then", "universe", + "universes", "using", "variable", "variables", "with"].join("|") + ); + ); var storageType = ( @@ -60,9 +61,11 @@ var leanHighlightRules = function() { var storageModifiers = ( "\\[(" + - ["persistent", "notation", "parsing-only", "visible", "instance", "class", "prefix", "axioms", "fields", - "multiple-instances", "classes", "instances", "coercions", "options", "trust", - "coercion", "reducible", "irreducible", "raw"].join("|") + + ["abbreviations", "all-transparent", "begin-end-hints", "class", "classes", "coercion", + "coercions", "declarations", "decls", "instance", "irreducible", + "multiple-instances", "notation", "notations", "parsing-only", "persistent", + "reduce-hints", "reducible", "tactic-hints", "visible", "wf", "whnf" + ].join("|") + ")\\]" ); From 34d80e81cafe90ea78bdb5fcc05fad8a0076bbba Mon Sep 17 00:00:00 2001 From: Soonho Kong Date: Tue, 24 Feb 2015 13:21:22 -0500 Subject: [PATCH 179/315] clean up string rule for lean-mode --- lib/ace/mode/lean_highlight_rules.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/ace/mode/lean_highlight_rules.js b/lib/ace/mode/lean_highlight_rules.js index 91440169..4ba9d484 100644 --- a/lib/ace/mode/lean_highlight_rules.js +++ b/lib/ace/mode/lean_highlight_rules.js @@ -100,12 +100,15 @@ var leanHighlightRules = function() { regex : "\\/-", next : "comment" }, { - token : "string", // single line - regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + stateName: "qqstring", + token : "string.start", regex : '"', next : [ + {token : "string.end", regex : '"', next : "start"}, + {token : "string", regex : "\\\\$", next : "qqstring"}, + {token : "string", regex : "\\n$", next : "qqstring"}, + {token : "constant.language.escape", regex : /\\./}, + {defaultToken: "string"} + ] }, { - token : "string", // multi line string start - regex : '["].*\\\\$', - next : "qqstring" }, { token : "constant.numeric", // hex regex : "0[xX][0-9a-fA-F]+(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b" @@ -141,6 +144,7 @@ var leanHighlightRules = function() { this.embedRules(DocCommentHighlightRules, "doc-", [ DocCommentHighlightRules.getEndRule("start") ]); + this.normalizeRules(); }; oop.inherits(leanHighlightRules, TextHighlightRules); From 27ad84664101be9fd1a19047268a95f24ba6800c Mon Sep 17 00:00:00 2001 From: Soonho Kong Date: Tue, 24 Feb 2015 13:21:40 -0500 Subject: [PATCH 180/315] highlight names followed nameProviders in lean-mode --- lib/ace/mode/lean_highlight_rules.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/ace/mode/lean_highlight_rules.js b/lib/ace/mode/lean_highlight_rules.js index 4ba9d484..06669de3 100644 --- a/lib/ace/mode/lean_highlight_rules.js +++ b/lib/ace/mode/lean_highlight_rules.js @@ -53,6 +53,9 @@ var leanHighlightRules = function() { "universes", "using", "variable", "variables", "with"].join("|") ); + var nameProviders = ( + ["inductive", "structure", "record", "theorem", "axiom", + "axioms", "lemma", "hypothesis", "definition", "constant"].join("|") ); var storageType = ( @@ -109,6 +112,8 @@ var leanHighlightRules = function() { {defaultToken: "string"} ] }, { + token : "keyword.control", regex : nameProviders, next : [ + {token : "variable.language", regex : identifierRe, next : "start"} ] }, { token : "constant.numeric", // hex regex : "0[xX][0-9a-fA-F]+(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b" From b6910a3094a30d695757a28b7680ce876e2ca6ae Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Tue, 24 Feb 2015 10:59:36 -0800 Subject: [PATCH 181/315] Add ClassName to highlighting So that document.getElementsByClassName gets highlighted. --- lib/ace/mode/javascript_highlight_rules.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/mode/javascript_highlight_rules.js b/lib/ace/mode/javascript_highlight_rules.js index 767b8fa1..5bdcce12 100644 --- a/lib/ace/mode/javascript_highlight_rules.js +++ b/lib/ace/mode/javascript_highlight_rules.js @@ -172,7 +172,7 @@ var JavaScriptHighlightRules = function(options) { regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/ }, { token : ["punctuation.operator", "support.function.dom"], - regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/ + regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName|ClassName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/ }, { token : ["punctuation.operator", "support.constant"], regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/ From 49ff50463939d1a5577088dfeab80bdb91614602 Mon Sep 17 00:00:00 2001 From: Soonho Kong Date: Tue, 24 Feb 2015 14:10:41 -0500 Subject: [PATCH 182/315] fix qqstring rule in lean-mode --- lib/ace/mode/lean_highlight_rules.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/ace/mode/lean_highlight_rules.js b/lib/ace/mode/lean_highlight_rules.js index 06669de3..d4a37d20 100644 --- a/lib/ace/mode/lean_highlight_rules.js +++ b/lib/ace/mode/lean_highlight_rules.js @@ -106,9 +106,7 @@ var leanHighlightRules = function() { stateName: "qqstring", token : "string.start", regex : '"', next : [ {token : "string.end", regex : '"', next : "start"}, - {token : "string", regex : "\\\\$", next : "qqstring"}, - {token : "string", regex : "\\n$", next : "qqstring"}, - {token : "constant.language.escape", regex : /\\./}, + {token : "constant.language.escape", regex : /\\[n"\\]/}, {defaultToken: "string"} ] }, { From 9905267e4deedda4fc4e15458a2f6cbfeb391dfc Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 24 Feb 2015 21:02:52 +0400 Subject: [PATCH 183/315] fix gutter in static highlight when wrapping is enabled --- demo/static-highlighter.html | 26 +++++++++++++++++++++++--- lib/ace/ext/static.css | 10 ++++++---- lib/ace/ext/static_highlight.js | 3 ++- lib/ace/ext/static_highlight_test.js | 8 ++++---- lib/ace/layer/text.js | 14 +++++++------- lib/ace/layer/text_test.js | 2 +- 6 files changed, 43 insertions(+), 20 deletions(-) diff --git a/demo/static-highlighter.html b/demo/static-highlighter.html index 39546541..eaf0dd53 100644 --- a/demo/static-highlighter.html +++ b/demo/static-highlighter.html @@ -2,13 +2,13 @@ - Static Code highlighter using Ace - + Static Code highlighter using Ace + @@ -35,6 +35,26 @@ function wobble (flam) { + +