diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 70b3753d..7f33807f 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -72,6 +72,26 @@
"message": "Checking...",
"description": "Text to display when checking a style for an update"
},
+ "cm_indentWithTabs": {
+ "message": "Use tabs with smart indentation",
+ "description": "Label for the checkbox controlling tabs with smart indentation option for the style editor."
+ },
+ "cm_keyMap": {
+ "message": "Keymap",
+ "description": "Label for the drop-down list controlling the keymap for the style editor."
+ },
+ "cm_lineWrapping": {
+ "message": "Word wrap",
+ "description": "Label for the checkbox controlling word wrap option for the style editor."
+ },
+ "cm_smartIndent": {
+ "message": "Use smart indentation",
+ "description": "Label for the checkbox controlling smart indentation option for the style editor."
+ },
+ "cm_tabSize": {
+ "message": "Tab size",
+ "description": "Label for the text box controlling tab size option for the style editor."
+ },
"dbError": {
"message": "An error has occurred using the Stylish database. Would you like to visit a web page with possible solutions?",
"description": "Prompt when a DB error is encountered"
@@ -169,10 +189,6 @@
"message": "Show number of styles active for the current site on the toolbar button",
"description": "Label for the checkbox controlling toolbar badge text."
},
- "prefSmartIndent": {
- "message": "Use smart indentation",
- "description": "Label for the checkbox controlling smart indentation option for the style editor."
- },
"sectionAdd": {
"message": "Add another section",
"description": "Label for the button to add a section"
diff --git a/edit.html b/edit.html
index 24841df8..6be58b2e 100644
--- a/edit.html
+++ b/edit.html
@@ -173,6 +173,16 @@
}
}
+
+ /* editor options */
+ [type="number"] {
+ max-width: 2.8em;
+ text-align: right;
+ }
+ table, input, select {
+ font-size: inherit;
+ }
+ table td:first-child {min-width: 60px}
@@ -191,7 +201,34 @@
diff --git a/edit.js b/edit.js
index a0570dca..90c55157 100644
--- a/edit.js
+++ b/edit.js
@@ -12,11 +12,13 @@ appliesToEverythingTemplate.innerHTML = t("appliesToEverything") + ' ' + t("appliesLabel") + ' ' + t('sectionRemove') + ' ' + t('sectionAdd') + ' ';
+var editors = []; // array of all CodeMirror instances
+function initCodeMirror() {
+ var CM = CodeMirror;
-var editors = [] // array of all CodeMirror instances
-// replace given textarea with the CodeMirror editor
-function setupCodeMirror(textarea) {
- var cm = CodeMirror.fromTextArea(textarea, {
+ // default option values
+ var userOptions = prefs.getPref("editor.options");
+ var stylishOptions = {
mode: 'css',
lineNumbers: true,
lineWrapping: true,
@@ -24,26 +26,70 @@ function setupCodeMirror(textarea) {
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter", "CodeMirror-lint-markers"],
matchBrackets: true,
lint: CodeMirror.lint.css,
- smartIndent: prefs.getPref("smart-indent"),
keyMap: "sublime",
extraKeys: {"Ctrl-Space": "autocomplete"}
+ };
+ mergeOptions(stylishOptions, CM.defaults);
+ mergeOptions(userOptions, CM.defaults);
+
+ function mergeOptions(source, target) {
+ for (var key in source) target[key] = source[key];
+ return target;
+ }
+
+ // additional commands
+ var cc = CM.commands;
+ cc.jumpToLine = jumpToLine;
+ cc.nextBuffer = nextBuffer;
+ cc.prevBuffer = prevBuffer;
+ // cc.save = save;
+
+ // user option values
+ CM.getOption = function (o) {
+ return CodeMirror.defaults[o];
+ }
+ CM.setOption = function (o, v) {
+ CodeMirror.defaults[o] = v;
+ editors.forEach(function(editor) {
+ editor.setOption(o, v);
+ });
+ }
+
+ // initialize global editor controls
+ document.getElementById("options").addEventListener("change", acmeEventListener, false);
+
+ var keymapControl = document.getElementById("editor.keyMap");
+ Object.keys(CodeMirror.keyMap).sort().forEach(function(map) {
+ keymapControl.appendChild(document.createElement("option")).textContent = map;
});
+
+ var controlPrefs = {},
+ controlOptions = ["smartIndent", "indentWithTabs", "tabSize", "keyMap", "lineWrapping"];
+ controlOptions.forEach(function(option) {
+ controlPrefs["editor." + option] = CM.defaults[option];
+ tE(option + "-label", "cm_" + option);
+ });
+ loadPrefs(controlPrefs);
+
+}
+initCodeMirror();
+
+function acmeEventListener(event) {
+ var option = event.target.dataset.option;
+ console.log("acmeEventListener heard %s on %s", event.type, event.target.id);
+ if (!option) console.error("acmeEventListener: no 'cm_option' %O", event.target);
+ else CodeMirror.setOption(option, event.target[isCheckbox(event.target) ? "checked" : "value"]);
+
+ if ("tabSize" === option) CodeMirror.setOption("indentUnit", CodeMirror.getOption("tabSize"));
+}
+
+// replace given textarea with the CodeMirror editor
+function setupCodeMirror(textarea) {
+ var cm = CodeMirror.fromTextArea(textarea);
cm.addKeyMap({
- "Ctrl-G": function(cm) {
- var cur = cm.getCursor();
- cm.openDialog(t('editGotoLine') + ': ', function(str) {
- var m = str.match(/^\s*(\d+)(?:\s*:\s*(\d+))?\s*$/);
- if (m) {
- cm.setCursor(m[1] - 1, m[2] ? m[2] - 1 : cur.ch);
- }
- }, {value: cur.line+1});
- },
- "Alt-PageDown": function(cm) {
- editors[(editors.indexOf(cm) + 1) % editors.length].focus();
- },
- "Alt-PageUp": function(cm) {
- editors[(editors.indexOf(cm) - 1 + editors.length) % editors.length].focus();
- }
+ "Ctrl-G": "jumpToLine",
+ "Alt-PageDown": "nextBuffer",
+ "Alt-PageUp": "prevBuffer"
});
cm.lastChange = cm.changeGeneration();
cm.on("change", indicateCodeChange);
@@ -325,11 +371,27 @@ function setupGlobalSearch() {
CodeMirror.commands.findPrev = function(cm) { findNext(cm, true) }
}
+function jumpToLine(cm) {
+ var cur = cm.getCursor();
+ cm.openDialog(t('editGotoLine') + ': ', function(str) {
+ var m = str.match(/^\s*(\d+)(?:\s*:\s*(\d+))?\s*$/);
+ if (m) {
+ cm.setCursor(m[1] - 1, m[2] ? m[2] - 1 : cur.ch);
+ }
+ }, {value: cur.line+1});
+}
+
+function nextBuffer(cm) {
+ editors[(editors.indexOf(cm) + 1) % editors.length].focus();
+}
+function prevBuffer(cm) {
+ editors[(editors.indexOf(cm) - 1 + editors.length) % editors.length].focus();
+}
+
window.addEventListener("load", init, false);
function init() {
tE("sections-help", "helpAlt", "alt");
- loadPrefs({"smart-indent": true});
var params = getParams();
if (!params.id) { // match should be 2 - one for the whole thing, one for the parentheses
// This is an add
@@ -554,10 +616,8 @@ chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
}
break;
case "prefChanged":
- if (request.prefName == "smart-indent") {
- editors.forEach(function(editor) {
- editor.setOption("smartIndent", request.value);
- });
+ if (request.prefName == "editor.smartIndent") {
+ CodeMirror.setOption("smartIndent", request.value);
}
}
});
@@ -569,7 +629,6 @@ tE("save-button", "styleSaveLabel");
tE("cancel-button", "styleCancelEditLabel");
tE("sections-heading", "styleSectionsTitle");
tE("options-heading", "optionsHeading");
-tE("smart-indent-label", "prefSmartIndent");
document.getElementById("name").addEventListener("change", makeDirty, false);
document.getElementById("enabled").addEventListener("change", makeDirty, false);
diff --git a/storage.js b/storage.js
index 29651754..cb9b8004 100644
--- a/storage.js
+++ b/storage.js
@@ -162,14 +162,20 @@ var prefs = {
// defaults
"openEditInWindow": false, // new editor opens in a own browser window
"show-badge": true, // display text on popup menu icon
- "smart-indent": true, // CodeMirror smart indent
"popup.breadcrumbs": true, // display "New style" links as URL breadcrumbs
"popup.breadcrumbs.usePath": false, // use URL path for "this URL"
"popup.enabledFirst": true, // display enabled styles before disabled styles
"manage.onlyEnabled": false, // display only enabled styles
- "manage.onlyEdited": false,// display only styles created locally
+ "manage.onlyEdited": false, // display only styles created locally
+
+ "editor.options": null, // CodeMirror.defaults.*
+ "editor.lineWrapping": true, // word wrap
+ "editor.smartIndent": true, // "smart" indent
+ "editor.indentWithTabs": false,// smart indent with tabs
+ "editor.tabSize": 4, // tab width, in spaces
+ "editor.keyMap": "sublime", // keymap
NO_DEFAULT_PREFERENCE: "No default preference for '%s'",
UNHANDLED_DATA_TYPE: "Default '%s' is of type '%s' - what should be done with it?",