function wrapCMOption(view, name, {doc = cmDoc, eventType = "input", get = ({value}) => value, validate, invalidation, block = true}) {
is.a(block, String) && (block = block.valueOf());
block = is.object(block)
? {valid: Boolean(block.valid), invalid: Boolean(block.invalid), mode: block.mode || "hard"}
: block
? {valid: true, invalid: true, mode: is.string(block) ? block.valueOf() : "hard"}
: {valid: false, invalid: false, mode: "soft"};
block.mode = block.mode == "soft" ? Event.prototype.stopPropagation : Event.prototype.stopImmediatePropagation;
Object.freeze(block);
function handler(e) {
let newVal = get.call(view, view, name);
if (newVal != doc.getEditor().getOption(name)) {
if (validate && !validate.call(view, newVal, name)) {
block.invalid && block.mode.call(e);
} else {
block.valid && block.mode.call(e);
doc.getEditor().setOption(name, newVal);
}
}
}
handler.opts = { passive: true };
for (let type of to.multi(eventType)) {
view.addEventListener(type, handler, handler.opts);
}
invalidation?.then?.(() => {
for (let type of to.multi(eventType)) {
view.removeEventListener(type, handler, handler.opts);
}
doc = view = undefined;
});
}