function doFold(cm, pos, options, force) {
        options = options || {};
        force = force || "fold";
        if (typeof pos === "number") {
            pos = CodeMirror.Pos(pos, 0);
        }

        var finder = options.rangeFinder || CodeMirror.fold.auto,
            range,
            widget,
            textRange;

        function getRange(allowFolded) {
            var range = options.range || finder(cm, pos);
            if (!range || range.to.line - range.from.line < prefs.getSetting("minFoldSize")) {
                return null;
            }
            var marks = cm.findMarksAt(range.from),
                i,
                lastMark,
                foldMarks;
            for (i = 0; i < marks.length; ++i) {
                if (marks[i].__isFold && force !== "fold") {
                    if (!allowFolded) {
                        return null;
                    }
                    range.cleared = true;
                    marks[i].clear();
                }
            }
            //check for overlapping folds
            if (marks && marks.length) {
                foldMarks = marks.filter(function (d) {
                    return d.__isFold;
                });
                if (foldMarks && foldMarks.length) {
                    lastMark = foldMarks[foldMarks.length - 1].find();
                    if (lastMark && range.from.line <= lastMark.to.line && lastMark.to.line < range.to.line) {
                        return null;
                    }
                }
            }
            return range;
        }

        function makeWidget() {
            var widget = window.document.createElement("span");
            widget.className = "CodeMirror-foldmarker";
            return widget;
        }

        range = getRange(true);
        if (options.scanUp) {
            while (!range && pos.line > cm.firstLine()) {
                pos = CodeMirror.Pos(pos.line - 1, 0);
                range = getRange(false);
            }
        }
        if (!range || range.cleared || force === "unfold" || range.to.line - range.from.line < prefs.getSetting("minFoldSize")) {
            if (range) { range.cleared = false; }
            return;
        }

        widget = makeWidget();
        textRange = cm.markText(range.from, range.to, {
            replacedWith: widget,
            clearOnEnter: true,
            __isFold: true
        });

        CodeMirror.on(widget, "mousedown", function (e) {
            textRange.clear();
            e.preventDefault();
        });

        textRange.on("clear", function (from, to) {
            delete cm._lineFolds[from.line];
            CodeMirror.signal(cm, "unfold", cm, from, to);
        });

        if (force === "fold") {
            delete range.cleared;
            // In some cases such as in xml style files, the start of  line folds can span multiple lines.
            // For instance the attributes of an element can span multiple lines. In these cases when folding
            // we want to render a gutter marker for both the beginning and end of the opening xml tag.
            if (pos.line < range.from.line) {
                cm._lineFolds[range.from.line] = range;
            } else {
                cm._lineFolds[pos.line] = range;
            }
        } else {
            delete cm._lineFolds[pos.line];
        }

        CodeMirror.signal(cm, force, cm, range.from, range.to);
        return range;
    }
Performs the folding and unfolding of code regions.
@param {CodeMirror} cm the CodeMirror instance
@param {number| Object} pos