Skip to content

Commit b7a269c

Browse files
author
Ives van Hoorne
committed
New way of handling prettifying and operations
1 parent cc120f4 commit b7a269c

File tree

21 files changed

+3536
-168
lines changed

21 files changed

+3536
-168
lines changed

packages/app/src/app/components/CodeEditor/Monaco/index.js

Lines changed: 58 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
ModuleCorrection,
1717
Directory,
1818
} from 'common/types';
19+
import { getTextOperation } from 'common/utils/diff';
1920

2021
import delay from 'common/utils/delay';
2122

@@ -33,33 +34,15 @@ import getSettings from './settings';
3334
import type { Props, Editor } from '../types';
3435
import getMode from './mode';
3536
import { liftOff } from './grammars/configure-tokenizer';
37+
import {
38+
lineAndColumnToIndex,
39+
indexToLineAndColumn,
40+
} from './monaco-index-converter';
3641

3742
type State = {
3843
fuzzySearchEnabled: boolean,
3944
};
4045

41-
function indexToLineAndColumn(lines, index) {
42-
let offset = 0;
43-
for (let i = 0; i < lines.length; i++) {
44-
const line = lines[i];
45-
if (offset + line.length + 1 > index) {
46-
return {
47-
lineNumber: i + 1,
48-
column: index - offset + 1,
49-
};
50-
}
51-
52-
// + 1 is for the linebreak character which is not included
53-
offset += line.length + 1;
54-
}
55-
56-
// +2 for column (length is already a +1), because +1 for Monaco and +1 for linebreak
57-
return {
58-
lineNumber: lines.length,
59-
column: (lines[lines.length - 1] || '').length + 1,
60-
};
61-
}
62-
6346
const fadeIn = css.keyframes('fadeIn', {
6447
// optional name
6548
'0%': { opacity: 0 },
@@ -72,21 +55,6 @@ const fadeOut = css.keyframes('fadeOut', {
7255
'100%': { opacity: 0 },
7356
});
7457

75-
function lineAndColumnToIndex(lines, lineNumber, column) {
76-
let currentLine = 0;
77-
let index = 0;
78-
79-
while (currentLine + 1 < lineNumber) {
80-
index += lines[currentLine].length;
81-
index += 1; // Linebreak character
82-
currentLine += 1;
83-
}
84-
85-
index += column - 1;
86-
87-
return index;
88-
}
89-
9058
function getSelection(lines, selection) {
9159
const startSelection = lineAndColumnToIndex(
9260
lines,
@@ -228,7 +196,7 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
228196
this.monaco = monaco;
229197

230198
// eslint-disable-next-line no-underscore-dangle
231-
window._cs = {
199+
window.CSEditor = {
232200
editor: this.editor,
233201
monaco: this.monaco,
234202
};
@@ -731,6 +699,55 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
731699
}
732700
};
733701

702+
applyOperationToModel = (operation, pushStack) => {
703+
const model = this.editor.getModel();
704+
705+
const results = [];
706+
let index = 0;
707+
for (let i = 0; i < operation.ops.length; i++) {
708+
const op = operation.ops[i];
709+
if (TextOperation.isRetain(op)) {
710+
index += op;
711+
} else if (TextOperation.isInsert(op)) {
712+
const { lineNumber, column } = indexToLineAndColumn(
713+
model.getLinesContent() || [],
714+
index
715+
);
716+
const range = new this.monaco.Range(
717+
lineNumber,
718+
column,
719+
lineNumber,
720+
column
721+
);
722+
results.push({
723+
range,
724+
text: op,
725+
forceMoveMarkers: true,
726+
});
727+
} else if (TextOperation.isDelete(op)) {
728+
const lines = model.getLinesContent() || [];
729+
const from = indexToLineAndColumn(lines, index);
730+
const to = indexToLineAndColumn(lines, index - op);
731+
results.push({
732+
range: new this.monaco.Range(
733+
from.lineNumber,
734+
from.column,
735+
to.lineNumber,
736+
to.column
737+
),
738+
text: '',
739+
});
740+
index -= op;
741+
}
742+
}
743+
744+
if (pushStack) {
745+
model.pushEditOperations([], results);
746+
} else {
747+
model.applyOperations(results);
748+
}
749+
};
750+
734751
applyOperations = (operations: { [moduleShortid: string]: any }) => {
735752
const operationsJSON = operations.toJSON();
736753

@@ -739,7 +756,6 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
739756

740757
if (moduleShortid !== this.currentModule.shortid) {
741758
// Apply the code to the current module code itself
742-
743759
const module = this.sandbox.modules.find(
744760
m => m.shortid === moduleShortid
745761
);
@@ -755,49 +771,8 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
755771
return;
756772
}
757773

758-
const model = this.editor.getModel();
759-
760774
this.liveOperationCode = '';
761-
let index = 0;
762-
for (let i = 0; i < operation.ops.length; i++) {
763-
const op = operation.ops[i];
764-
if (TextOperation.isRetain(op)) {
765-
index += op;
766-
} else if (TextOperation.isInsert(op)) {
767-
const { lineNumber, column } = indexToLineAndColumn(
768-
model.getLinesContent() || [],
769-
index
770-
);
771-
model.applyEdits([
772-
{
773-
range: new this.monaco.Range(
774-
lineNumber,
775-
column,
776-
lineNumber,
777-
column
778-
),
779-
text: op,
780-
forceMoveMarkers: true,
781-
},
782-
]);
783-
index += op.length;
784-
} else if (TextOperation.isDelete(op)) {
785-
const lines = model.getLinesContent() || [];
786-
const from = indexToLineAndColumn(lines, index);
787-
const to = indexToLineAndColumn(lines, index - op);
788-
model.applyEdits([
789-
{
790-
range: new this.monaco.Range(
791-
from.lineNumber,
792-
from.column,
793-
to.lineNumber,
794-
to.column
795-
),
796-
text: '',
797-
},
798-
]);
799-
}
800-
}
775+
this.applyOperationToModel(operation);
801776
});
802777
};
803778

@@ -1223,19 +1198,7 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
12231198
};
12241199

12251200
updateCode(code: string = '') {
1226-
const pos = this.editor.getPosition();
1227-
const lines = this.editor.getModel().getLinesContent() || [];
1228-
const lastLine = lines.length;
1229-
const lastLineColumn = (lines[lines.length - 1] || '').length;
1230-
const editOperation = {
1231-
identifier: {
1232-
major: 1,
1233-
minor: 1,
1234-
},
1235-
text: code,
1236-
range: new this.monaco.Range(0, 0, lastLine + 1, lastLineColumn),
1237-
forceMoveMarkers: false,
1238-
};
1201+
const operation = getTextOperation(this.getCode(), code);
12391202

12401203
if (!this.receivingCode) {
12411204
// For the live operation we need to send the operation based on the old code,
@@ -1244,8 +1207,7 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
12441207
this.liveOperationCode = this.getCode();
12451208
}
12461209

1247-
this.editor.getModel().pushEditOperations([], [editOperation], null);
1248-
this.editor.setPosition(pos);
1210+
this.applyOperationToModel(operation, true);
12491211
}
12501212

12511213
lint = async (code: string, title: string, version: number) => {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
export function lineAndColumnToIndex(lines, lineNumber, column) {
2+
let currentLine = 0;
3+
let index = 0;
4+
5+
while (currentLine + 1 < lineNumber) {
6+
index += lines[currentLine].length;
7+
index += 1; // Linebreak character
8+
currentLine += 1;
9+
}
10+
11+
index += column - 1;
12+
13+
return index;
14+
}
15+
16+
export function indexToLineAndColumn(lines, index) {
17+
let offset = 0;
18+
for (let i = 0; i < lines.length; i++) {
19+
const line = lines[i];
20+
if (offset + line.length + 1 > index) {
21+
return {
22+
lineNumber: i + 1,
23+
column: index - offset + 1,
24+
};
25+
}
26+
27+
// + 1 is for the linebreak character which is not included
28+
offset += line.length + 1;
29+
}
30+
31+
// +2 for column (length is already a +1), because +1 for Monaco and +1 for linebreak
32+
return {
33+
lineNumber: lines.length,
34+
column: (lines[lines.length - 1] || '').length + 1,
35+
};
36+
}

packages/app/src/app/pages/common/Modals/PreferencesModal/Appearance/index.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ function EditorSettings({ store, signals }) {
8989
type="number"
9090
placeholder="1.15"
9191
step="0.05"
92-
style={{ width: '4rem' }}
9392
{...bindValue('lineHeight')}
9493
/>
9594
<Rule />

packages/app/src/app/pages/common/Modals/PreferencesModal/CodeFormatting/Prettier/index.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,27 @@ function Prettier({ store, signals }) {
3535
</SubDescription>
3636
<Rule />
3737
<PaddedPreference
38+
title="Fluid print width"
39+
type="boolean"
40+
{...bindValue('fluid')}
41+
/>
42+
<SubDescription>
43+
Wrap the code based on the editor width.
44+
</SubDescription>
45+
<Rule />
46+
<PaddedPreference
47+
style={{
48+
opacity: store.preferences.settings.prettierConfig.fluid ? 0.5 : 1,
49+
}}
3850
title="Print width"
3951
type="number"
4052
{...bindValue('printWidth')}
4153
/>
42-
<SubDescription>
54+
<SubDescription
55+
style={{
56+
opacity: store.preferences.settings.prettierConfig.fluid ? 0.5 : 1,
57+
}}
58+
>
4359
Specify the line length that the printer will wrap on.
4460
</SubDescription>
4561
<Rule />

packages/app/src/app/store/modules/editor/actions.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,11 @@ export function prettifyCode({ utils, state, props, path }) {
384384
.prettify(
385385
moduleToPrettify.title,
386386
() => (moduleToPrettify ? moduleToPrettify.code : ''),
387-
config
387+
config,
388+
() =>
389+
moduleToPrettify
390+
? moduleToPrettify.id === state.get(`editor.currentModule.id`)
391+
: false
388392
)
389393
.then(newCode => path.success({ code: newCode }))
390394
.catch(error => path.error({ error }));

packages/app/src/app/store/modules/live/actions.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { TextOperation } from 'ot';
22
import { camelizeKeys } from 'humps';
33

44
import VERSION from 'common/version';
5+
import { getTextOperation } from 'common/utils/diff';
56

67
export function createRoom({ api, props }) {
78
const id = props.sandboxId;
@@ -563,10 +564,7 @@ export function getCodeOperation({ props, state }) {
563564

564565
const oldCode = module.code;
565566

566-
const op = new TextOperation();
567-
568-
op.delete(oldCode.length);
569-
op.insert(code);
567+
const op = getTextOperation(oldCode, code);
570568

571569
return {
572570
operation: op.toJSON(),

packages/app/src/app/store/modules/preferences/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export default Module({
2222
keybindings: [],
2323
newPackagerExperiment: false,
2424
prettierConfig: {
25+
fluid: false,
2526
printWidth: 80,
2627
tabWidth: 2,
2728
useTabs: false,

packages/app/src/app/store/modules/preferences/model.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,15 @@ export default {
2121
),
2222
newPackagerExperiment: types.boolean,
2323
prettierConfig: types.model({
24-
printWidth: types.number,
25-
tabWidth: types.number,
26-
useTabs: types.boolean,
27-
semi: types.boolean,
28-
singleQuote: types.boolean,
29-
trailingComma: types.string,
30-
bracketSpacing: types.boolean,
31-
jsxBracketSameLine: types.boolean,
24+
fluid: types.maybe(types.boolean),
25+
printWidth: types.maybe(types.number),
26+
tabWidth: types.maybe(types.number),
27+
useTabs: types.maybe(types.boolean),
28+
semi: types.maybe(types.boolean),
29+
singleQuote: types.maybe(types.boolean),
30+
trailingComma: types.maybe(types.string),
31+
bracketSpacing: types.maybe(types.boolean),
32+
jsxBracketSameLine: types.maybe(types.boolean),
3233
}),
3334
jsxBracketSameLine: types.boolean,
3435
printWidth: types.number,

packages/app/src/app/store/providers/Utils/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ export default Provider({
99
createOptimisticId() {
1010
return 'OPTIMISTIC_' + nextOptimisticId++;
1111
},
12-
prettify(fileName, code, config) {
13-
return prettify(fileName, code, config);
12+
prettify(fileName, code, config, isCurrentModule) {
13+
return prettify(fileName, code, config, isCurrentModule);
1414
},
1515
resolveModule,
1616
isEqual,

0 commit comments

Comments
 (0)