Skip to content

Instantly share code, notes, and snippets.

@sailist
Created March 27, 2020 04:57
Show Gist options
  • Save sailist/916e1d28f787664957576f08f9ac66dd to your computer and use it in GitHub Desktop.
Save sailist/916e1d28f787664957576f08f9ac66dd to your computer and use it in GitHub Desktop.
ace-editor.vue
<template>
<div ref="root">
</div>
</template>
<script>
var ace = require("ace-builds")
require("ace-builds/webpack-resolver");
const PROPS = {
value: {},
theme: { v: 'chrome' },
autoScrollEditorIntoView: { f: toBool },
tabSize: { f: toNum, v: 2 },
readOnly: { f: toBool },
minLines: { f: toNum },
maxLines: { f: toNum },
highlightActiveLine: { f: toBool },
highlightSelectedWord: { f: toBool },
cursorStyle: {},
hScrollBarAlwaysVisible: { f: toBool },
vScrollBarAlwaysVisible: { f: toBool },
highlightGutterLine: { f: toBool },
animatedScroll: { f: toBool },
showInvisibles: { f: toBool },
showPrintMargin: { f: toBool },
printMarginColumn: { f: toNum },
fadeFoldWidgets: { f: toBool },
showFoldWidgets: { f: toBool, v: true },
showLineNumbers: { f: toBool, v: true },
showGutter: { f: toBool, v: true },
displayIndentGuides: { f: toBool },
fontSize: {},
fontFamily: {},
scrollPastEnd: {},
fixedWidthGutter: { f: toBool },
firstLineNumber: { f: toNum, v: 1 },
overwrite: { f: toBool },
newLineMode: {},
useSoftTabs: { f: toBool, v: true },
mode: { v: 'python' },
foldStyle: { v: 'markbegin' }
};
const EDITOR_EVENTS = ['blur', 'change', 'changeSelectionStyle', 'changeSession', 'copy', 'focus', 'paste'];
function toBool(value, opt_ignoreNum) {
var result = value;
if (result != null) {
(value + '').replace(
/^(?:|0|false|no|off|(1|true|yes|on))$/,
(m, isTrue) => result = (/01/.test(m) && opt_ignoreNum) ? result : !!isTrue
);
}
return result;
}
function toNum(value) {
return (value == null || Number.isNaN(+value)) ? value : +value;
}
// eslint-disable-next-line no-unused-vars
function toBoolOrNum(value) {
var result = toBool(value, true);
return 'boolean' === typeof result ? result : toNum(value);
}
export default {
name: "AceEditor",
props: Object.keys(PROPS),
data() {
return {
editor: null,
// NOTE: "lastValue" is needed to prevent cursor from always going to
// the end after typing
lastValue: ''
};
},
methods: {
setOption(key, value) {
let { f: func } = PROPS[key];
value = /^(theme|mode)$/.test(key)
? `ace/${key}/${value}`
: func
? func(value)
: value;
this.editor.setOption(key, value);
}
},
watch: (function () {
let watch = {
value(value) {
if (this.lastValue !== value) {
this.editor.setValue(value);
}
}
};
return Object.entries(PROPS).reduce(
// eslint-disable-next-line no-unused-vars
(watch, [propName, prop]) => {
if (propName !== 'value') {
watch[propName] = function(newValue) {
this.setOption(propName, newValue);
};
}
return watch;
},
watch
);
})(),
mounted() {
this.editor = ace.edit(this.$refs.root, { value: this.value });
Object.entries(PROPS).forEach(
([propName, prop]) => {
let value = this.$props[propName];
this.setOption(propName, value === undefined ? prop.v : value);
}
);
// eslint-disable-next-line no-unused-vars
this.editor.on('change', (e) => {
this.$emit('input', this.lastValue = this.editor.getValue());
});
EDITOR_EVENTS.forEach(eName => this.editor.on(eName, e => this.$emit(eName, e)));
}
}
</script>
<style scoped>
</style>
<ace-editor v-model="code" min-lines="3" max-lines="30"></ace-editor>
import AceEditor from "./AceEditor";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment