Spaces:
Sleeping
Sleeping
| import { onBlur } from "../display/focus" | |
| import { setGuttersForLineNumbers, updateGutters } from "../display/gutters" | |
| import { alignHorizontally } from "../display/line_numbers" | |
| import { loadMode, resetModeState } from "../display/mode_state" | |
| import { initScrollbars, updateScrollbars } from "../display/scrollbars" | |
| import { updateSelection } from "../display/selection" | |
| import { regChange } from "../display/view_tracking" | |
| import { getKeyMap } from "../input/keymap" | |
| import { defaultSpecialCharPlaceholder } from "../line/line_data" | |
| import { Pos } from "../line/pos" | |
| import { findMaxLine } from "../line/spans" | |
| import { clearCaches, compensateForHScroll, estimateLineHeights } from "../measurement/position_measurement" | |
| import { replaceRange } from "../model/changes" | |
| import { mobile, windows } from "../util/browser" | |
| import { addClass, rmClass } from "../util/dom" | |
| import { off, on } from "../util/event" | |
| import { themeChanged } from "./utils" | |
| export let Init = {toString: function(){return "CodeMirror.Init"}} | |
| export let defaults = {} | |
| export let optionHandlers = {} | |
| export function defineOptions(CodeMirror) { | |
| let optionHandlers = CodeMirror.optionHandlers | |
| function option(name, deflt, handle, notOnInit) { | |
| CodeMirror.defaults[name] = deflt | |
| if (handle) optionHandlers[name] = | |
| notOnInit ? (cm, val, old) => {if (old != Init) handle(cm, val, old)} : handle | |
| } | |
| CodeMirror.defineOption = option | |
| // Passed to option handlers when there is no old value. | |
| CodeMirror.Init = Init | |
| // These two are, on init, called from the constructor because they | |
| // have to be initialized before the editor can start at all. | |
| option("value", "", (cm, val) => cm.setValue(val), true) | |
| option("mode", null, (cm, val) => { | |
| cm.doc.modeOption = val | |
| loadMode(cm) | |
| }, true) | |
| option("indentUnit", 2, loadMode, true) | |
| option("indentWithTabs", false) | |
| option("smartIndent", true) | |
| option("tabSize", 4, cm => { | |
| resetModeState(cm) | |
| clearCaches(cm) | |
| regChange(cm) | |
| }, true) | |
| option("lineSeparator", null, (cm, val) => { | |
| cm.doc.lineSep = val | |
| if (!val) return | |
| let newBreaks = [], lineNo = cm.doc.first | |
| cm.doc.iter(line => { | |
| for (let pos = 0;;) { | |
| let found = line.text.indexOf(val, pos) | |
| if (found == -1) break | |
| pos = found + val.length | |
| newBreaks.push(Pos(lineNo, found)) | |
| } | |
| lineNo++ | |
| }) | |
| for (let i = newBreaks.length - 1; i >= 0; i--) | |
| replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)) | |
| }) | |
| option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/g, (cm, val, old) => { | |
| cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g") | |
| if (old != Init) cm.refresh() | |
| }) | |
| option("specialCharPlaceholder", defaultSpecialCharPlaceholder, cm => cm.refresh(), true) | |
| option("electricChars", true) | |
| option("inputStyle", mobile ? "contenteditable" : "textarea", () => { | |
| throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME | |
| }, true) | |
| option("spellcheck", false, (cm, val) => cm.getInputField().spellcheck = val, true) | |
| option("rtlMoveVisually", !windows) | |
| option("wholeLineUpdateBefore", true) | |
| option("theme", "default", cm => { | |
| themeChanged(cm) | |
| guttersChanged(cm) | |
| }, true) | |
| option("keyMap", "default", (cm, val, old) => { | |
| let next = getKeyMap(val) | |
| let prev = old != Init && getKeyMap(old) | |
| if (prev && prev.detach) prev.detach(cm, next) | |
| if (next.attach) next.attach(cm, prev || null) | |
| }) | |
| option("extraKeys", null) | |
| option("lineWrapping", false, wrappingChanged, true) | |
| option("gutters", [], cm => { | |
| setGuttersForLineNumbers(cm.options) | |
| guttersChanged(cm) | |
| }, true) | |
| option("fixedGutter", true, (cm, val) => { | |
| cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0" | |
| cm.refresh() | |
| }, true) | |
| option("coverGutterNextToScrollbar", false, cm => updateScrollbars(cm), true) | |
| option("scrollbarStyle", "native", cm => { | |
| initScrollbars(cm) | |
| updateScrollbars(cm) | |
| cm.display.scrollbars.setScrollTop(cm.doc.scrollTop) | |
| cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft) | |
| }, true) | |
| option("lineNumbers", false, cm => { | |
| setGuttersForLineNumbers(cm.options) | |
| guttersChanged(cm) | |
| }, true) | |
| option("firstLineNumber", 1, guttersChanged, true) | |
| option("lineNumberFormatter", integer => integer, guttersChanged, true) | |
| option("showCursorWhenSelecting", false, updateSelection, true) | |
| option("resetSelectionOnContextMenu", true) | |
| option("lineWiseCopyCut", true) | |
| option("readOnly", false, (cm, val) => { | |
| if (val == "nocursor") { | |
| onBlur(cm) | |
| cm.display.input.blur() | |
| cm.display.disabled = true | |
| } else { | |
| cm.display.disabled = false | |
| } | |
| cm.display.input.readOnlyChanged(val) | |
| }) | |
| option("disableInput", false, (cm, val) => {if (!val) cm.display.input.reset()}, true) | |
| option("dragDrop", true, dragDropChanged) | |
| option("allowDropFileTypes", null) | |
| option("cursorBlinkRate", 530) | |
| option("cursorScrollMargin", 0) | |
| option("cursorHeight", 1, updateSelection, true) | |
| option("singleCursorHeightPerLine", true, updateSelection, true) | |
| option("workTime", 100) | |
| option("workDelay", 100) | |
| option("flattenSpans", true, resetModeState, true) | |
| option("addModeClass", false, resetModeState, true) | |
| option("pollInterval", 100) | |
| option("undoDepth", 200, (cm, val) => cm.doc.history.undoDepth = val) | |
| option("historyEventDelay", 1250) | |
| option("viewportMargin", 10, cm => cm.refresh(), true) | |
| option("maxHighlightLength", 10000, resetModeState, true) | |
| option("moveInputWithCursor", true, (cm, val) => { | |
| if (!val) cm.display.input.resetPosition() | |
| }) | |
| option("tabindex", null, (cm, val) => cm.display.input.getField().tabIndex = val || "") | |
| option("autofocus", null) | |
| option("direction", "ltr", (cm, val) => cm.doc.setDirection(val), true) | |
| } | |
| function guttersChanged(cm) { | |
| updateGutters(cm) | |
| regChange(cm) | |
| alignHorizontally(cm) | |
| } | |
| function dragDropChanged(cm, value, old) { | |
| let wasOn = old && old != Init | |
| if (!value != !wasOn) { | |
| let funcs = cm.display.dragFunctions | |
| let toggle = value ? on : off | |
| toggle(cm.display.scroller, "dragstart", funcs.start) | |
| toggle(cm.display.scroller, "dragenter", funcs.enter) | |
| toggle(cm.display.scroller, "dragover", funcs.over) | |
| toggle(cm.display.scroller, "dragleave", funcs.leave) | |
| toggle(cm.display.scroller, "drop", funcs.drop) | |
| } | |
| } | |
| function wrappingChanged(cm) { | |
| if (cm.options.lineWrapping) { | |
| addClass(cm.display.wrapper, "CodeMirror-wrap") | |
| cm.display.sizer.style.minWidth = "" | |
| cm.display.sizerWidth = null | |
| } else { | |
| rmClass(cm.display.wrapper, "CodeMirror-wrap") | |
| findMaxLine(cm) | |
| } | |
| estimateLineHeights(cm) | |
| regChange(cm) | |
| clearCaches(cm) | |
| setTimeout(() => updateScrollbars(cm), 100) | |
| } | |