private static _enter(config: CursorConfiguration, model: ITextModel, keepPosition: boolean, range: Range): ICommand {
		if (!model.isCheapToTokenize(range.getStartPosition().lineNumber)) {
			let lineText = model.getLineContent(range.startLineNumber);
			let indentation = strings.getLeadingWhitespace(lineText).substring(0, range.startColumn - 1);
			return TypeOperations._typeCommand(range, '\n' + config.normalizeIndentation(indentation), keepPosition);
		}

		let r = LanguageConfigurationRegistry.getEnterAction(model, range);
		if (r) {
			let enterAction = r.enterAction;
			let indentation = r.indentation;

			if (enterAction.indentAction === IndentAction.None) {
				// Nothing special
				return TypeOperations._typeCommand(range, '\n' + config.normalizeIndentation(indentation + enterAction.appendText), keepPosition);

			} else if (enterAction.indentAction === IndentAction.Indent) {
				// Indent once
				return TypeOperations._typeCommand(range, '\n' + config.normalizeIndentation(indentation + enterAction.appendText), keepPosition);

			} else if (enterAction.indentAction === IndentAction.IndentOutdent) {
				// Ultra special
				let normalIndent = config.normalizeIndentation(indentation);
				let increasedIndent = config.normalizeIndentation(indentation + enterAction.appendText);

				let typeText = '\n' + increasedIndent + '\n' + normalIndent;

				if (keepPosition) {
					return new ReplaceCommandWithoutChangingPosition(range, typeText, true);
				} else {
					return new ReplaceCommandWithOffsetCursorState(range, typeText, -1, increasedIndent.length - normalIndent.length, true);
				}
			} else if (enterAction.indentAction === IndentAction.Outdent) {
				let actualIndentation = TypeOperations.unshiftIndent(config, indentation);
				return TypeOperations._typeCommand(range, '\n' + config.normalizeIndentation(actualIndentation + enterAction.appendText), keepPosition);
			}
		}

		// no enter rules applied, we should check indentation rules then.
		if (!config.autoIndent) {
			// Nothing special
			let lineText = model.getLineContent(range.startLineNumber);
			let indentation = strings.getLeadingWhitespace(lineText).substring(0, range.startColumn - 1);
			return TypeOperations._typeCommand(range, '\n' + config.normalizeIndentation(indentation), keepPosition);
		}

		let ir = LanguageConfigurationRegistry.getIndentForEnter(model, range, {
			unshiftIndent: (indent) => {
				return TypeOperations.unshiftIndent(config, indent);
			},
			shiftIndent: (indent) => {
				return TypeOperations.shiftIndent(config, indent);
			},
			normalizeIndentation: (indent) => {
				return config.normalizeIndentation(indent);
			}
		}, config.autoIndent);

		let lineText = model.getLineContent(range.startLineNumber);
		let indentation = strings.getLeadingWhitespace(lineText).substring(0, range.startColumn - 1);

		if (ir) {
			let oldEndViewColumn = CursorColumns.visibleColumnFromColumn2(config, model, range.getEndPosition());
			let oldEndColumn = range.endColumn;

			let beforeText = '\n';
			if (indentation !== config.normalizeIndentation(ir.beforeEnter)) {
				beforeText = config.normalizeIndentation(ir.beforeEnter) + lineText.substring(indentation.length, range.startColumn - 1) + '\n';
				range = new Range(range.startLineNumber, 1, range.endLineNumber, range.endColumn);
			}

			let newLineContent = model.getLineContent(range.endLineNumber);
			let firstNonWhitespace = strings.firstNonWhitespaceIndex(newLineContent);
			if (firstNonWhitespace >= 0) {
				range = range.setEndPosition(range.endLineNumber, Math.max(range.endColumn, firstNonWhitespace + 1));
			} else {
				range = range.setEndPosition(range.endLineNumber, model.getLineMaxColumn(range.endLineNumber));
			}

			if (keepPosition) {
				return new ReplaceCommandWithoutChangingPosition(range, beforeText + config.normalizeIndentation(ir.afterEnter), true);
			} else {
				let offset = 0;
				if (oldEndColumn <= firstNonWhitespace + 1) {
					if (!config.insertSpaces) {
						oldEndViewColumn = Math.ceil(oldEndViewColumn / config.tabSize);
					}
					offset = Math.min(oldEndViewColumn + 1 - config.normalizeIndentation(ir.afterEnter).length - 1, 0);
				}
				return new ReplaceCommandWithOffsetCursorState(range, beforeText + config.normalizeIndentation(ir.afterEnter), 0, offset, true);
			}

		} else {
			return TypeOperations._typeCommand(range, '\n' + config.normalizeIndentation(indentation), keepPosition);
		}
	}