@@ -5,7 +5,7 @@ import CodeMirror from 'codemirror'
5
5
import 'codemirror-mode-elixir'
6
6
import attachmentManagement from 'browser/main/lib/dataApi/attachmentManagement'
7
7
import convertModeName from 'browser/lib/convertModeName'
8
- import { options , TableEditor } from '@susisu/mte-kernel'
8
+ import { options , TableEditor , Alignment } from '@susisu/mte-kernel'
9
9
import TextEditorInterface from 'browser/lib/TextEditorInterface'
10
10
import eventEmitter from 'browser/main/lib/eventEmitter'
11
11
import iconv from 'iconv-lite'
@@ -59,6 +59,7 @@ export default class CodeEditor extends React.Component {
59
59
this . searchState = null
60
60
61
61
this . formatTable = ( ) => this . handleFormatTable ( )
62
+ this . editorActivityHandler = ( ) => this . handleEditorActivity ( )
62
63
}
63
64
64
65
handleSearch ( msg ) {
@@ -99,6 +100,28 @@ export default class CodeEditor extends React.Component {
99
100
this . tableEditor . formatAll ( options ( { textWidthOptions : { } } ) )
100
101
}
101
102
103
+ handleEditorActivity ( ) {
104
+ if ( ! this . textEditorInterface . transaction ) {
105
+ this . updateTableEditorState ( )
106
+ }
107
+ }
108
+
109
+ updateTableEditorState ( ) {
110
+ const active = this . tableEditor . cursorIsInTable ( this . tableEditorOptions )
111
+ if ( active ) {
112
+ if ( this . extraKeysMode !== 'editor' ) {
113
+ this . extraKeysMode = 'editor'
114
+ this . editor . setOption ( 'extraKeys' , this . editorKeyMap )
115
+ }
116
+ } else {
117
+ if ( this . extraKeysMode !== 'default' ) {
118
+ this . extraKeysMode = 'default'
119
+ this . editor . setOption ( 'extraKeys' , this . defaultKeyMap )
120
+ this . tableEditor . resetSmartCursor ( )
121
+ }
122
+ }
123
+ }
124
+
102
125
componentDidMount ( ) {
103
126
const { rulers, enableRulers } = this . props
104
127
const expandSnippet = this . expandSnippet . bind ( this )
@@ -119,6 +142,59 @@ export default class CodeEditor extends React.Component {
119
142
)
120
143
}
121
144
145
+ this . defaultKeyMap = CodeMirror . normalizeKeyMap ( {
146
+ Tab : function ( cm ) {
147
+ const cursor = cm . getCursor ( )
148
+ const line = cm . getLine ( cursor . line )
149
+ const cursorPosition = cursor . ch
150
+ const charBeforeCursor = line . substr ( cursorPosition - 1 , 1 )
151
+ if ( cm . somethingSelected ( ) ) cm . indentSelection ( 'add' )
152
+ else {
153
+ const tabs = cm . getOption ( 'indentWithTabs' )
154
+ if ( line . trimLeft ( ) . match ( / ^ ( - | \* | \+ ) ( \[ ( | x ) ] ) ? $ / ) ) {
155
+ cm . execCommand ( 'goLineStart' )
156
+ if ( tabs ) {
157
+ cm . execCommand ( 'insertTab' )
158
+ } else {
159
+ cm . execCommand ( 'insertSoftTab' )
160
+ }
161
+ cm . execCommand ( 'goLineEnd' )
162
+ } else if (
163
+ ! charBeforeCursor . match ( / \t | \s | \r | \n / ) &&
164
+ cursor . ch > 1
165
+ ) {
166
+ // text expansion on tab key if the char before is alphabet
167
+ const snippets = JSON . parse (
168
+ fs . readFileSync ( consts . SNIPPET_FILE , 'utf8' )
169
+ )
170
+ if ( expandSnippet ( line , cursor , cm , snippets ) === false ) {
171
+ if ( tabs ) {
172
+ cm . execCommand ( 'insertTab' )
173
+ } else {
174
+ cm . execCommand ( 'insertSoftTab' )
175
+ }
176
+ }
177
+ } else {
178
+ if ( tabs ) {
179
+ cm . execCommand ( 'insertTab' )
180
+ } else {
181
+ cm . execCommand ( 'insertSoftTab' )
182
+ }
183
+ }
184
+ }
185
+ } ,
186
+ 'Cmd-T' : function ( cm ) {
187
+ // Do nothing
188
+ } ,
189
+ Enter : 'boostNewLineAndIndentContinueMarkdownList' ,
190
+ 'Ctrl-C' : cm => {
191
+ if ( cm . getOption ( 'keyMap' ) . substr ( 0 , 3 ) === 'vim' ) {
192
+ document . execCommand ( 'copy' )
193
+ }
194
+ return CodeMirror . Pass
195
+ }
196
+ } )
197
+
122
198
this . value = this . props . value
123
199
this . editor = CodeMirror ( this . refs . root , {
124
200
rulers : buildCMRulers ( rulers , enableRulers ) ,
@@ -141,58 +217,7 @@ export default class CodeEditor extends React.Component {
141
217
explode : '[]{}``$$' ,
142
218
override : true
143
219
} ,
144
- extraKeys : {
145
- Tab : function ( cm ) {
146
- const cursor = cm . getCursor ( )
147
- const line = cm . getLine ( cursor . line )
148
- const cursorPosition = cursor . ch
149
- const charBeforeCursor = line . substr ( cursorPosition - 1 , 1 )
150
- if ( cm . somethingSelected ( ) ) cm . indentSelection ( 'add' )
151
- else {
152
- const tabs = cm . getOption ( 'indentWithTabs' )
153
- if ( line . trimLeft ( ) . match ( / ^ ( - | \* | \+ ) ( \[ ( | x ) ] ) ? $ / ) ) {
154
- cm . execCommand ( 'goLineStart' )
155
- if ( tabs ) {
156
- cm . execCommand ( 'insertTab' )
157
- } else {
158
- cm . execCommand ( 'insertSoftTab' )
159
- }
160
- cm . execCommand ( 'goLineEnd' )
161
- } else if (
162
- ! charBeforeCursor . match ( / \t | \s | \r | \n / ) &&
163
- cursor . ch > 1
164
- ) {
165
- // text expansion on tab key if the char before is alphabet
166
- const snippets = JSON . parse (
167
- fs . readFileSync ( consts . SNIPPET_FILE , 'utf8' )
168
- )
169
- if ( expandSnippet ( line , cursor , cm , snippets ) === false ) {
170
- if ( tabs ) {
171
- cm . execCommand ( 'insertTab' )
172
- } else {
173
- cm . execCommand ( 'insertSoftTab' )
174
- }
175
- }
176
- } else {
177
- if ( tabs ) {
178
- cm . execCommand ( 'insertTab' )
179
- } else {
180
- cm . execCommand ( 'insertSoftTab' )
181
- }
182
- }
183
- }
184
- } ,
185
- 'Cmd-T' : function ( cm ) {
186
- // Do nothing
187
- } ,
188
- Enter : 'boostNewLineAndIndentContinueMarkdownList' ,
189
- 'Ctrl-C' : cm => {
190
- if ( cm . getOption ( 'keyMap' ) . substr ( 0 , 3 ) === 'vim' ) {
191
- document . execCommand ( 'copy' )
192
- }
193
- return CodeMirror . Pass
194
- }
195
- }
220
+ extraKeys : this . defaultKeyMap
196
221
} )
197
222
198
223
this . setMode ( this . props . mode )
@@ -215,8 +240,58 @@ export default class CodeEditor extends React.Component {
215
240
CodeMirror . Vim . defineEx ( 'qw' , 'qw' , this . quitEditor )
216
241
CodeMirror . Vim . map ( 'ZZ' , ':q' , 'normal' )
217
242
218
- this . tableEditor = new TableEditor ( new TextEditorInterface ( this . editor ) )
243
+ this . textEditorInterface = new TextEditorInterface ( this . editor )
244
+ this . tableEditor = new TableEditor ( this . textEditorInterface )
219
245
eventEmitter . on ( 'code:format-table' , this . formatTable )
246
+
247
+ this . tableEditorOptions = options ( {
248
+ smartCursor : true
249
+ } )
250
+
251
+ this . editorKeyMap = CodeMirror . normalizeKeyMap ( {
252
+ 'Tab' : ( ) => { this . tableEditor . nextCell ( this . tableEditorOptions ) } ,
253
+ 'Shift-Tab' : ( ) => { this . tableEditor . previousCell ( this . tableEditorOptions ) } ,
254
+ 'Enter' : ( ) => { this . tableEditor . nextRow ( this . tableEditorOptions ) } ,
255
+ 'Ctrl-Enter' : ( ) => { this . tableEditor . escape ( this . tableEditorOptions ) } ,
256
+ 'Cmd-Enter' : ( ) => { this . tableEditor . escape ( this . tableEditorOptions ) } ,
257
+ 'Shift-Ctrl-Left' : ( ) => { this . tableEditor . alignColumn ( Alignment . LEFT , this . tableEditorOptions ) } ,
258
+ 'Shift-Cmd-Left' : ( ) => { this . tableEditor . alignColumn ( Alignment . LEFT , this . tableEditorOptions ) } ,
259
+ 'Shift-Ctrl-Right' : ( ) => { this . tableEditor . alignColumn ( Alignment . RIGHT , this . tableEditorOptions ) } ,
260
+ 'Shift-Cmd-Right' : ( ) => { this . tableEditor . alignColumn ( Alignment . RIGHT , this . tableEditorOptions ) } ,
261
+ 'Shift-Ctrl-Up' : ( ) => { this . tableEditor . alignColumn ( Alignment . CENTER , this . tableEditorOptions ) } ,
262
+ 'Shift-Cmd-Up' : ( ) => { this . tableEditor . alignColumn ( Alignment . CENTER , this . tableEditorOptions ) } ,
263
+ 'Shift-Ctrl-Down' : ( ) => { this . tableEditor . alignColumn ( Alignment . NONE , this . tableEditorOptions ) } ,
264
+ 'Shift-Cmd-Down' : ( ) => { this . tableEditor . alignColumn ( Alignment . NONE , this . tableEditorOptions ) } ,
265
+ 'Ctrl-Left' : ( ) => { this . tableEditor . moveFocus ( 0 , - 1 , this . tableEditorOptions ) } ,
266
+ 'Cmd-Left' : ( ) => { this . tableEditor . moveFocus ( 0 , - 1 , this . tableEditorOptions ) } ,
267
+ 'Ctrl-Right' : ( ) => { this . tableEditor . moveFocus ( 0 , 1 , this . tableEditorOptions ) } ,
268
+ 'Cmd-Right' : ( ) => { this . tableEditor . moveFocus ( 0 , 1 , this . tableEditorOptions ) } ,
269
+ 'Ctrl-Up' : ( ) => { this . tableEditor . moveFocus ( - 1 , 0 , this . tableEditorOptions ) } ,
270
+ 'Cmd-Up' : ( ) => { this . tableEditor . moveFocus ( - 1 , 0 , this . tableEditorOptions ) } ,
271
+ 'Ctrl-Down' : ( ) => { this . tableEditor . moveFocus ( 1 , 0 , this . tableEditorOptions ) } ,
272
+ 'Cmd-Down' : ( ) => { this . tableEditor . moveFocus ( 1 , 0 , this . tableEditorOptions ) } ,
273
+ 'Ctrl-K Ctrl-I' : ( ) => { this . tableEditor . insertRow ( this . tableEditorOptions ) } ,
274
+ 'Cmd-K Cmd-I' : ( ) => { this . tableEditor . insertRow ( this . tableEditorOptions ) } ,
275
+ 'Ctrl-L Ctrl-I' : ( ) => { this . tableEditor . deleteRow ( this . tableEditorOptions ) } ,
276
+ 'Cmd-L Cmd-I' : ( ) => { this . tableEditor . deleteRow ( this . tableEditorOptions ) } ,
277
+ 'Ctrl-K Ctrl-J' : ( ) => { this . tableEditor . insertColumn ( this . tableEditorOptions ) } ,
278
+ 'Cmd-K Cmd-J' : ( ) => { this . tableEditor . insertColumn ( this . tableEditorOptions ) } ,
279
+ 'Ctrl-L Ctrl-J' : ( ) => { this . tableEditor . deleteColumn ( this . tableEditorOptions ) } ,
280
+ 'Cmd-L Cmd-J' : ( ) => { this . tableEditor . deleteColumn ( this . tableEditorOptions ) } ,
281
+ 'Alt-Shift-Ctrl-Left' : ( ) => { this . tableEditor . moveColumn ( - 1 , this . tableEditorOptions ) } ,
282
+ 'Alt-Shift-Cmd-Left' : ( ) => { this . tableEditor . moveColumn ( - 1 , this . tableEditorOptions ) } ,
283
+ 'Alt-Shift-Ctrl-Right' : ( ) => { this . tableEditor . moveColumn ( 1 , this . tableEditorOptions ) } ,
284
+ 'Alt-Shift-Cmd-Right' : ( ) => { this . tableEditor . moveColumn ( 1 , this . tableEditorOptions ) } ,
285
+ 'Alt-Shift-Ctrl-Up' : ( ) => { this . tableEditor . moveRow ( - 1 , this . tableEditorOptions ) } ,
286
+ 'Alt-Shift-Cmd-Up' : ( ) => { this . tableEditor . moveRow ( - 1 , this . tableEditorOptions ) } ,
287
+ 'Alt-Shift-Ctrl-Down' : ( ) => { this . tableEditor . moveRow ( 1 , this . tableEditorOptions ) } ,
288
+ 'Alt-Shift-Cmd-Down' : ( ) => { this . tableEditor . moveRow ( 1 , this . tableEditorOptions ) }
289
+ } )
290
+
291
+ if ( this . props . enableTableEditor ) {
292
+ this . editor . on ( 'cursorActivity' , this . editorActivityHandler )
293
+ this . editor . on ( 'changes' , this . editorActivityHandler )
294
+ }
220
295
}
221
296
222
297
expandSnippet ( line , cursor , cm , snippets ) {
@@ -353,6 +428,19 @@ export default class CodeEditor extends React.Component {
353
428
this . editor . setOption ( 'scrollPastEnd' , this . props . scrollPastEnd )
354
429
}
355
430
431
+ if ( prevProps . enableTableEditor !== this . props . enableTableEditor ) {
432
+ if ( this . props . enableTableEditor ) {
433
+ this . editor . on ( 'cursorActivity' , this . editorActivityHandler )
434
+ this . editor . on ( 'changes' , this . editorActivityHandler )
435
+ } else {
436
+ this . editor . off ( 'cursorActivity' , this . editorActivityHandler )
437
+ this . editor . off ( 'changes' , this . editorActivityHandler )
438
+ }
439
+
440
+ this . extraKeysMode = 'default'
441
+ this . editor . setOption ( 'extraKeys' , this . defaultKeyMap )
442
+ }
443
+
356
444
if ( needRefresh ) {
357
445
this . editor . refresh ( )
358
446
}
0 commit comments