2022-01-26 12:08:38 +05:30
|
|
|
/**
|
|
|
|
* A WebIDE Extension options for Source Editor
|
|
|
|
* @typedef {Object} WebIDEExtensionOptions
|
|
|
|
* @property {Object} modelManager The root manager for WebIDE models
|
|
|
|
* @property {Object} store The state store for communication
|
|
|
|
* @property {Object} file
|
|
|
|
* @property {Object} options The Monaco editor options
|
|
|
|
*/
|
|
|
|
|
2021-04-17 20:07:23 +05:30
|
|
|
import { debounce } from 'lodash';
|
|
|
|
import { KeyCode, KeyMod, Range } from 'monaco-editor';
|
|
|
|
import { EDITOR_TYPE_DIFF } from '~/editor/constants';
|
|
|
|
import Disposable from '~/ide/lib/common/disposable';
|
|
|
|
import { editorOptions } from '~/ide/lib/editor_options';
|
|
|
|
import keymap from '~/ide/lib/keymap.json';
|
|
|
|
|
|
|
|
const isDiffEditorType = (instance) => {
|
|
|
|
return instance.getEditorType() === EDITOR_TYPE_DIFF;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const UPDATE_DIMENSIONS_DELAY = 200;
|
2022-01-26 12:08:38 +05:30
|
|
|
const defaultOptions = {
|
|
|
|
modelManager: undefined,
|
|
|
|
store: undefined,
|
|
|
|
file: undefined,
|
|
|
|
options: {},
|
|
|
|
};
|
2021-04-17 20:07:23 +05:30
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
const addActions = (instance, store) => {
|
|
|
|
const getKeyCode = (key) => {
|
|
|
|
const monacoKeyMod = key.indexOf('KEY_') === 0;
|
2021-04-17 20:07:23 +05:30
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
return monacoKeyMod ? KeyCode[key] : KeyMod[key];
|
|
|
|
};
|
2021-04-17 20:07:23 +05:30
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
keymap.forEach((command) => {
|
|
|
|
const { bindings, id, label, action } = command;
|
2021-04-17 20:07:23 +05:30
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
const keybindings = bindings.map((binding) => {
|
|
|
|
const keys = binding.split('+');
|
2021-04-17 20:07:23 +05:30
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
// eslint-disable-next-line no-bitwise
|
|
|
|
return keys.length > 1 ? getKeyCode(keys[0]) | getKeyCode(keys[1]) : getKeyCode(keys[0]);
|
2021-04-17 20:07:23 +05:30
|
|
|
});
|
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
instance.addAction({
|
|
|
|
id,
|
|
|
|
label,
|
|
|
|
keybindings,
|
|
|
|
run() {
|
|
|
|
store.dispatch(action.name, action.params);
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
2021-04-17 20:07:23 +05:30
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
const renderSideBySide = (domElement) => {
|
|
|
|
return domElement.offsetWidth >= 700;
|
|
|
|
};
|
2021-04-17 20:07:23 +05:30
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
const updateInstanceDimensions = (instance) => {
|
|
|
|
instance.layout();
|
|
|
|
if (isDiffEditorType(instance)) {
|
|
|
|
instance.updateOptions({
|
|
|
|
renderSideBySide: renderSideBySide(instance.getDomNode()),
|
2021-04-17 20:07:23 +05:30
|
|
|
});
|
|
|
|
}
|
2022-01-26 12:08:38 +05:30
|
|
|
};
|
2021-04-17 20:07:23 +05:30
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
export class EditorWebIdeExtension {
|
|
|
|
static get extensionName() {
|
|
|
|
return 'EditorWebIde';
|
2021-04-17 20:07:23 +05:30
|
|
|
}
|
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
/**
|
|
|
|
* Set up the WebIDE extension for Source Editor
|
|
|
|
* @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
|
|
|
|
* @param {WebIDEExtensionOptions} setupOptions
|
|
|
|
*/
|
|
|
|
onSetup(instance, setupOptions = defaultOptions) {
|
|
|
|
this.modelManager = setupOptions.modelManager;
|
|
|
|
this.store = setupOptions.store;
|
|
|
|
this.file = setupOptions.file;
|
|
|
|
this.options = setupOptions.options;
|
|
|
|
|
|
|
|
this.disposable = new Disposable();
|
|
|
|
this.debouncedUpdate = debounce(() => {
|
|
|
|
updateInstanceDimensions(instance);
|
|
|
|
}, UPDATE_DIMENSIONS_DELAY);
|
|
|
|
|
|
|
|
addActions(instance, setupOptions.store);
|
2021-04-17 20:07:23 +05:30
|
|
|
}
|
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
onUse(instance) {
|
|
|
|
window.addEventListener('resize', this.debouncedUpdate, false);
|
2021-04-17 20:07:23 +05:30
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
instance.onDidDispose(() => {
|
|
|
|
this.onUnuse();
|
|
|
|
});
|
2021-04-17 20:07:23 +05:30
|
|
|
}
|
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
onUnuse() {
|
|
|
|
window.removeEventListener('resize', this.debouncedUpdate);
|
|
|
|
|
|
|
|
// catch any potential errors with disposing the error
|
|
|
|
// this is mainly for tests caused by elements not existing
|
|
|
|
try {
|
|
|
|
this.disposable.dispose();
|
|
|
|
} catch (e) {
|
|
|
|
if (process.env.NODE_ENV !== 'test') {
|
|
|
|
// eslint-disable-next-line no-console
|
|
|
|
console.error(e);
|
|
|
|
}
|
2021-04-17 20:07:23 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
provides() {
|
|
|
|
return {
|
|
|
|
createModel: (instance, file, head = null) => {
|
|
|
|
return this.modelManager.addModel(file, head);
|
|
|
|
},
|
|
|
|
attachModel: (instance, model) => {
|
|
|
|
if (isDiffEditorType(instance)) {
|
|
|
|
instance.setModel({
|
|
|
|
original: model.getOriginalModel(),
|
|
|
|
modified: model.getModel(),
|
|
|
|
});
|
2021-04-17 20:07:23 +05:30
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
return;
|
|
|
|
}
|
2021-04-17 20:07:23 +05:30
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
instance.setModel(model.getModel());
|
|
|
|
|
|
|
|
instance.updateOptions(
|
|
|
|
editorOptions.reduce((acc, obj) => {
|
|
|
|
Object.keys(obj).forEach((key) => {
|
|
|
|
Object.assign(acc, {
|
|
|
|
[key]: obj[key](model),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return acc;
|
|
|
|
}, {}),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
attachMergeRequestModel: (instance, model) => {
|
|
|
|
instance.setModel({
|
|
|
|
original: model.getBaseModel(),
|
|
|
|
modified: model.getModel(),
|
|
|
|
});
|
|
|
|
},
|
|
|
|
updateDimensions: (instance) => updateInstanceDimensions(instance),
|
|
|
|
setPos: (instance, { lineNumber, column }) => {
|
|
|
|
instance.revealPositionInCenter({
|
|
|
|
lineNumber,
|
|
|
|
column,
|
|
|
|
});
|
|
|
|
instance.setPosition({
|
|
|
|
lineNumber,
|
|
|
|
column,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
onPositionChange: (instance, cb) => {
|
|
|
|
if (typeof instance.onDidChangeCursorPosition !== 'function') {
|
|
|
|
return;
|
|
|
|
}
|
2021-04-17 20:07:23 +05:30
|
|
|
|
2022-01-26 12:08:38 +05:30
|
|
|
this.disposable.add(instance.onDidChangeCursorPosition((e) => cb(instance, e)));
|
|
|
|
},
|
|
|
|
replaceSelectedText: (instance, text) => {
|
|
|
|
let selection = instance.getSelection();
|
|
|
|
const range = new Range(
|
|
|
|
selection.startLineNumber,
|
|
|
|
selection.startColumn,
|
|
|
|
selection.endLineNumber,
|
|
|
|
selection.endColumn,
|
|
|
|
);
|
|
|
|
|
|
|
|
instance.executeEdits('', [{ range, text }]);
|
|
|
|
|
|
|
|
selection = instance.getSelection();
|
|
|
|
instance.setPosition({ lineNumber: selection.endLineNumber, column: selection.endColumn });
|
|
|
|
},
|
|
|
|
};
|
2021-04-17 20:07:23 +05:30
|
|
|
}
|
|
|
|
}
|