Skip to content

Commit fe323d5

Browse files
authored
Merge branch 'master' into tags
2 parents 69a032c + 671dff0 commit fe323d5

File tree

9 files changed

+275
-109
lines changed

9 files changed

+275
-109
lines changed

browser/components/CodeEditor.js

Lines changed: 142 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import CodeMirror from 'codemirror'
55
import 'codemirror-mode-elixir'
66
import attachmentManagement from 'browser/main/lib/dataApi/attachmentManagement'
77
import convertModeName from 'browser/lib/convertModeName'
8-
import { options, TableEditor } from '@susisu/mte-kernel'
8+
import { options, TableEditor, Alignment } from '@susisu/mte-kernel'
99
import TextEditorInterface from 'browser/lib/TextEditorInterface'
1010
import eventEmitter from 'browser/main/lib/eventEmitter'
1111
import iconv from 'iconv-lite'
@@ -59,6 +59,7 @@ export default class CodeEditor extends React.Component {
5959
this.searchState = null
6060

6161
this.formatTable = () => this.handleFormatTable()
62+
this.editorActivityHandler = () => this.handleEditorActivity()
6263
}
6364

6465
handleSearch (msg) {
@@ -99,6 +100,28 @@ export default class CodeEditor extends React.Component {
99100
this.tableEditor.formatAll(options({textWidthOptions: {}}))
100101
}
101102

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+
102125
componentDidMount () {
103126
const { rulers, enableRulers } = this.props
104127
const expandSnippet = this.expandSnippet.bind(this)
@@ -119,6 +142,59 @@ export default class CodeEditor extends React.Component {
119142
)
120143
}
121144

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+
122198
this.value = this.props.value
123199
this.editor = CodeMirror(this.refs.root, {
124200
rulers: buildCMRulers(rulers, enableRulers),
@@ -141,58 +217,7 @@ export default class CodeEditor extends React.Component {
141217
explode: '[]{}``$$',
142218
override: true
143219
},
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
196221
})
197222

198223
this.setMode(this.props.mode)
@@ -215,8 +240,58 @@ export default class CodeEditor extends React.Component {
215240
CodeMirror.Vim.defineEx('qw', 'qw', this.quitEditor)
216241
CodeMirror.Vim.map('ZZ', ':q', 'normal')
217242

218-
this.tableEditor = new TableEditor(new TextEditorInterface(this.editor))
243+
this.textEditorInterface = new TextEditorInterface(this.editor)
244+
this.tableEditor = new TableEditor(this.textEditorInterface)
219245
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+
}
220295
}
221296

222297
expandSnippet (line, cursor, cm, snippets) {
@@ -353,6 +428,19 @@ export default class CodeEditor extends React.Component {
353428
this.editor.setOption('scrollPastEnd', this.props.scrollPastEnd)
354429
}
355430

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+
356444
if (needRefresh) {
357445
this.editor.refresh()
358446
}

browser/components/MarkdownEditor.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ class MarkdownEditor extends React.Component {
265265
storageKey={storageKey}
266266
noteKey={noteKey}
267267
fetchUrlTitle={config.editor.fetchUrlTitle}
268+
enableTableEditor={config.editor.enableTableEditor}
268269
onChange={(e) => this.handleChange(e)}
269270
onBlur={(e) => this.handleBlur(e)}
270271
/>

browser/components/MarkdownSplitEditor.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ class MarkdownSplitEditor extends React.Component {
158158
rulers={config.editor.rulers}
159159
scrollPastEnd={config.editor.scrollPastEnd}
160160
fetchUrlTitle={config.editor.fetchUrlTitle}
161+
enableTableEditor={config.editor.enableTableEditor}
161162
storageKey={storageKey}
162163
noteKey={noteKey}
163164
onChange={this.handleOnChange.bind(this)}

0 commit comments

Comments
 (0)