Skip to content

Commit 604f17f

Browse files
authored
Merge pull request #2586 from GuilhermeJSilva/feature/autoBracketMatching
Feature/auto bracket matching
2 parents 7a3cab8 + 21c6112 commit 604f17f

File tree

8 files changed

+259
-73
lines changed

8 files changed

+259
-73
lines changed

browser/components/CodeEditor.js

Lines changed: 195 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ 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, Alignment } from '@susisu/mte-kernel'
8+
import {
9+
options,
10+
TableEditor,
11+
Alignment
12+
} from '@susisu/mte-kernel'
913
import TextEditorInterface from 'browser/lib/TextEditorInterface'
1014
import eventEmitter from 'browser/main/lib/eventEmitter'
1115
import iconv from 'iconv-lite'
@@ -18,12 +22,16 @@ import normalizeEditorFontFamily from 'browser/lib/normalizeEditorFontFamily'
1822
const spellcheck = require('browser/lib/spellcheck')
1923
const buildEditorContextMenu = require('browser/lib/contextMenuBuilder')
2024
import TurndownService from 'turndown'
21-
import { gfm } from 'turndown-plugin-gfm'
25+
import {
26+
gfm
27+
} from 'turndown-plugin-gfm'
2228

2329
CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js'
2430

2531
const buildCMRulers = (rulers, enableRulers) =>
26-
(enableRulers ? rulers.map(ruler => ({ column: ruler })) : [])
32+
(enableRulers ? rulers.map(ruler => ({
33+
column: ruler
34+
})) : [])
2735

2836
function translateHotkey (hotkey) {
2937
return hotkey.replace(/\s*\+\s*/g, '-').replace(/Command/g, 'Cmd').replace(/Control/g, 'Ctrl')
@@ -54,7 +62,10 @@ export default class CodeEditor extends React.Component {
5462
}
5563
this.props.onBlur != null && this.props.onBlur(e)
5664

57-
const { storageKey, noteKey } = this.props
65+
const {
66+
storageKey,
67+
noteKey
68+
} = this.props
5869
attachmentManagement.deleteAttachmentsNotPresentInNote(
5970
this.editor.getValue(),
6071
storageKey,
@@ -124,7 +135,9 @@ export default class CodeEditor extends React.Component {
124135
}
125136

126137
handleFormatTable () {
127-
this.tableEditor.formatAll(options({textWidthOptions: {}}))
138+
this.tableEditor.formatAll(options({
139+
textWidthOptions: {}
140+
}))
128141
}
129142

130143
handleEditorActivity () {
@@ -253,9 +266,9 @@ export default class CodeEditor extends React.Component {
253266
foldGutter: true,
254267
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
255268
autoCloseBrackets: {
256-
pairs: '()[]{}\'\'""$$**``',
257-
triples: '```"""\'\'\'',
258-
explode: '[]{}``$$',
269+
pairs: this.props.matchingPairs,
270+
triples: this.props.matchingTriples,
271+
explode: this.props.explodingPairs,
259272
override: true
260273
},
261274
extraKeys: this.defaultKeyMap
@@ -298,43 +311,117 @@ export default class CodeEditor extends React.Component {
298311
})
299312

300313
this.editorKeyMap = CodeMirror.normalizeKeyMap({
301-
'Tab': () => { this.tableEditor.nextCell(this.tableEditorOptions) },
302-
'Shift-Tab': () => { this.tableEditor.previousCell(this.tableEditorOptions) },
303-
'Enter': () => { this.tableEditor.nextRow(this.tableEditorOptions) },
304-
'Ctrl-Enter': () => { this.tableEditor.escape(this.tableEditorOptions) },
305-
'Cmd-Enter': () => { this.tableEditor.escape(this.tableEditorOptions) },
306-
'Shift-Ctrl-Left': () => { this.tableEditor.alignColumn(Alignment.LEFT, this.tableEditorOptions) },
307-
'Shift-Cmd-Left': () => { this.tableEditor.alignColumn(Alignment.LEFT, this.tableEditorOptions) },
308-
'Shift-Ctrl-Right': () => { this.tableEditor.alignColumn(Alignment.RIGHT, this.tableEditorOptions) },
309-
'Shift-Cmd-Right': () => { this.tableEditor.alignColumn(Alignment.RIGHT, this.tableEditorOptions) },
310-
'Shift-Ctrl-Up': () => { this.tableEditor.alignColumn(Alignment.CENTER, this.tableEditorOptions) },
311-
'Shift-Cmd-Up': () => { this.tableEditor.alignColumn(Alignment.CENTER, this.tableEditorOptions) },
312-
'Shift-Ctrl-Down': () => { this.tableEditor.alignColumn(Alignment.NONE, this.tableEditorOptions) },
313-
'Shift-Cmd-Down': () => { this.tableEditor.alignColumn(Alignment.NONE, this.tableEditorOptions) },
314-
'Ctrl-Left': () => { this.tableEditor.moveFocus(0, -1, this.tableEditorOptions) },
315-
'Cmd-Left': () => { this.tableEditor.moveFocus(0, -1, this.tableEditorOptions) },
316-
'Ctrl-Right': () => { this.tableEditor.moveFocus(0, 1, this.tableEditorOptions) },
317-
'Cmd-Right': () => { this.tableEditor.moveFocus(0, 1, this.tableEditorOptions) },
318-
'Ctrl-Up': () => { this.tableEditor.moveFocus(-1, 0, this.tableEditorOptions) },
319-
'Cmd-Up': () => { this.tableEditor.moveFocus(-1, 0, this.tableEditorOptions) },
320-
'Ctrl-Down': () => { this.tableEditor.moveFocus(1, 0, this.tableEditorOptions) },
321-
'Cmd-Down': () => { this.tableEditor.moveFocus(1, 0, this.tableEditorOptions) },
322-
'Ctrl-K Ctrl-I': () => { this.tableEditor.insertRow(this.tableEditorOptions) },
323-
'Cmd-K Cmd-I': () => { this.tableEditor.insertRow(this.tableEditorOptions) },
324-
'Ctrl-L Ctrl-I': () => { this.tableEditor.deleteRow(this.tableEditorOptions) },
325-
'Cmd-L Cmd-I': () => { this.tableEditor.deleteRow(this.tableEditorOptions) },
326-
'Ctrl-K Ctrl-J': () => { this.tableEditor.insertColumn(this.tableEditorOptions) },
327-
'Cmd-K Cmd-J': () => { this.tableEditor.insertColumn(this.tableEditorOptions) },
328-
'Ctrl-L Ctrl-J': () => { this.tableEditor.deleteColumn(this.tableEditorOptions) },
329-
'Cmd-L Cmd-J': () => { this.tableEditor.deleteColumn(this.tableEditorOptions) },
330-
'Alt-Shift-Ctrl-Left': () => { this.tableEditor.moveColumn(-1, this.tableEditorOptions) },
331-
'Alt-Shift-Cmd-Left': () => { this.tableEditor.moveColumn(-1, this.tableEditorOptions) },
332-
'Alt-Shift-Ctrl-Right': () => { this.tableEditor.moveColumn(1, this.tableEditorOptions) },
333-
'Alt-Shift-Cmd-Right': () => { this.tableEditor.moveColumn(1, this.tableEditorOptions) },
334-
'Alt-Shift-Ctrl-Up': () => { this.tableEditor.moveRow(-1, this.tableEditorOptions) },
335-
'Alt-Shift-Cmd-Up': () => { this.tableEditor.moveRow(-1, this.tableEditorOptions) },
336-
'Alt-Shift-Ctrl-Down': () => { this.tableEditor.moveRow(1, this.tableEditorOptions) },
337-
'Alt-Shift-Cmd-Down': () => { this.tableEditor.moveRow(1, this.tableEditorOptions) }
314+
'Tab': () => {
315+
this.tableEditor.nextCell(this.tableEditorOptions)
316+
},
317+
'Shift-Tab': () => {
318+
this.tableEditor.previousCell(this.tableEditorOptions)
319+
},
320+
'Enter': () => {
321+
this.tableEditor.nextRow(this.tableEditorOptions)
322+
},
323+
'Ctrl-Enter': () => {
324+
this.tableEditor.escape(this.tableEditorOptions)
325+
},
326+
'Cmd-Enter': () => {
327+
this.tableEditor.escape(this.tableEditorOptions)
328+
},
329+
'Shift-Ctrl-Left': () => {
330+
this.tableEditor.alignColumn(Alignment.LEFT, this.tableEditorOptions)
331+
},
332+
'Shift-Cmd-Left': () => {
333+
this.tableEditor.alignColumn(Alignment.LEFT, this.tableEditorOptions)
334+
},
335+
'Shift-Ctrl-Right': () => {
336+
this.tableEditor.alignColumn(Alignment.RIGHT, this.tableEditorOptions)
337+
},
338+
'Shift-Cmd-Right': () => {
339+
this.tableEditor.alignColumn(Alignment.RIGHT, this.tableEditorOptions)
340+
},
341+
'Shift-Ctrl-Up': () => {
342+
this.tableEditor.alignColumn(Alignment.CENTER, this.tableEditorOptions)
343+
},
344+
'Shift-Cmd-Up': () => {
345+
this.tableEditor.alignColumn(Alignment.CENTER, this.tableEditorOptions)
346+
},
347+
'Shift-Ctrl-Down': () => {
348+
this.tableEditor.alignColumn(Alignment.NONE, this.tableEditorOptions)
349+
},
350+
'Shift-Cmd-Down': () => {
351+
this.tableEditor.alignColumn(Alignment.NONE, this.tableEditorOptions)
352+
},
353+
'Ctrl-Left': () => {
354+
this.tableEditor.moveFocus(0, -1, this.tableEditorOptions)
355+
},
356+
'Cmd-Left': () => {
357+
this.tableEditor.moveFocus(0, -1, this.tableEditorOptions)
358+
},
359+
'Ctrl-Right': () => {
360+
this.tableEditor.moveFocus(0, 1, this.tableEditorOptions)
361+
},
362+
'Cmd-Right': () => {
363+
this.tableEditor.moveFocus(0, 1, this.tableEditorOptions)
364+
},
365+
'Ctrl-Up': () => {
366+
this.tableEditor.moveFocus(-1, 0, this.tableEditorOptions)
367+
},
368+
'Cmd-Up': () => {
369+
this.tableEditor.moveFocus(-1, 0, this.tableEditorOptions)
370+
},
371+
'Ctrl-Down': () => {
372+
this.tableEditor.moveFocus(1, 0, this.tableEditorOptions)
373+
},
374+
'Cmd-Down': () => {
375+
this.tableEditor.moveFocus(1, 0, this.tableEditorOptions)
376+
},
377+
'Ctrl-K Ctrl-I': () => {
378+
this.tableEditor.insertRow(this.tableEditorOptions)
379+
},
380+
'Cmd-K Cmd-I': () => {
381+
this.tableEditor.insertRow(this.tableEditorOptions)
382+
},
383+
'Ctrl-L Ctrl-I': () => {
384+
this.tableEditor.deleteRow(this.tableEditorOptions)
385+
},
386+
'Cmd-L Cmd-I': () => {
387+
this.tableEditor.deleteRow(this.tableEditorOptions)
388+
},
389+
'Ctrl-K Ctrl-J': () => {
390+
this.tableEditor.insertColumn(this.tableEditorOptions)
391+
},
392+
'Cmd-K Cmd-J': () => {
393+
this.tableEditor.insertColumn(this.tableEditorOptions)
394+
},
395+
'Ctrl-L Ctrl-J': () => {
396+
this.tableEditor.deleteColumn(this.tableEditorOptions)
397+
},
398+
'Cmd-L Cmd-J': () => {
399+
this.tableEditor.deleteColumn(this.tableEditorOptions)
400+
},
401+
'Alt-Shift-Ctrl-Left': () => {
402+
this.tableEditor.moveColumn(-1, this.tableEditorOptions)
403+
},
404+
'Alt-Shift-Cmd-Left': () => {
405+
this.tableEditor.moveColumn(-1, this.tableEditorOptions)
406+
},
407+
'Alt-Shift-Ctrl-Right': () => {
408+
this.tableEditor.moveColumn(1, this.tableEditorOptions)
409+
},
410+
'Alt-Shift-Cmd-Right': () => {
411+
this.tableEditor.moveColumn(1, this.tableEditorOptions)
412+
},
413+
'Alt-Shift-Ctrl-Up': () => {
414+
this.tableEditor.moveRow(-1, this.tableEditorOptions)
415+
},
416+
'Alt-Shift-Cmd-Up': () => {
417+
this.tableEditor.moveRow(-1, this.tableEditorOptions)
418+
},
419+
'Alt-Shift-Ctrl-Down': () => {
420+
this.tableEditor.moveRow(1, this.tableEditorOptions)
421+
},
422+
'Alt-Shift-Cmd-Down': () => {
423+
this.tableEditor.moveRow(1, this.tableEditorOptions)
424+
}
338425
})
339426

340427
if (this.props.enableTableEditor) {
@@ -423,8 +510,14 @@ export default class CodeEditor extends React.Component {
423510
return {
424511
text: wordBeforeCursor,
425512
range: {
426-
from: { line: lineNumber, ch: originCursorPosition },
427-
to: { line: lineNumber, ch: cursorPosition }
513+
from: {
514+
line: lineNumber,
515+
ch: originCursorPosition
516+
},
517+
to: {
518+
line: lineNumber,
519+
ch: cursorPosition
520+
}
428521
}
429522
}
430523
}
@@ -450,7 +543,10 @@ export default class CodeEditor extends React.Component {
450543

451544
componentDidUpdate (prevProps, prevState) {
452545
let needRefresh = false
453-
const { rulers, enableRulers } = this.props
546+
const {
547+
rulers,
548+
enableRulers
549+
} = this.props
454550
if (prevProps.mode !== this.props.mode) {
455551
this.setMode(this.props.mode)
456552
}
@@ -491,6 +587,18 @@ export default class CodeEditor extends React.Component {
491587
this.editor.setOption('scrollPastEnd', this.props.scrollPastEnd)
492588
}
493589

590+
if (prevProps.matchingPairs !== this.props.matchingPairs ||
591+
prevProps.matchingTriples !== this.props.matchingTriples ||
592+
prevProps.explodingPairs !== this.props.explodingPairs) {
593+
const bracketObject = {
594+
pairs: this.props.matchingPairs,
595+
triples: this.props.matchingTriples,
596+
explode: this.props.explodingPairs,
597+
override: true
598+
}
599+
this.editor.setOption('autoCloseBrackets', bracketObject)
600+
}
601+
494602
if (prevProps.enableTableEditor !== this.props.enableTableEditor) {
495603
if (this.props.enableTableEditor) {
496604
this.editor.on('cursorActivity', this.editorActivityHandler)
@@ -523,7 +631,7 @@ export default class CodeEditor extends React.Component {
523631
if (prevProps.spellCheck !== this.props.spellCheck) {
524632
if (this.props.spellCheck === false) {
525633
spellcheck.setLanguage(this.editor, spellcheck.SPELLCHECK_DISABLED)
526-
let elem = document.getElementById('editor-bottom-panel')
634+
const elem = document.getElementById('editor-bottom-panel')
527635
elem.parentNode.removeChild(elem)
528636
} else {
529637
this.editor.addPanel(this.createSpellCheckPanel(), {position: 'bottom'})
@@ -672,7 +780,10 @@ export default class CodeEditor extends React.Component {
672780

673781
handleDropImage (dropEvent) {
674782
dropEvent.preventDefault()
675-
const { storageKey, noteKey } = this.props
783+
const {
784+
storageKey,
785+
noteKey
786+
} = this.props
676787
attachmentManagement.handleAttachmentDrop(
677788
this,
678789
storageKey,
@@ -695,15 +806,21 @@ export default class CodeEditor extends React.Component {
695806

696807
const isInLinkTag = editor => {
697808
const startCursor = editor.getCursor('start')
698-
const prevChar = editor.getRange(
699-
{ line: startCursor.line, ch: startCursor.ch - 2 },
700-
{ line: startCursor.line, ch: startCursor.ch }
701-
)
809+
const prevChar = editor.getRange({
810+
line: startCursor.line,
811+
ch: startCursor.ch - 2
812+
}, {
813+
line: startCursor.line,
814+
ch: startCursor.ch
815+
})
702816
const endCursor = editor.getCursor('end')
703-
const nextChar = editor.getRange(
704-
{ line: endCursor.line, ch: endCursor.ch },
705-
{ line: endCursor.line, ch: endCursor.ch + 1 }
706-
)
817+
const nextChar = editor.getRange({
818+
line: endCursor.line,
819+
ch: endCursor.ch
820+
}, {
821+
line: endCursor.line,
822+
ch: endCursor.ch + 1
823+
})
707824
return prevChar === '](' && nextChar === ')'
708825
}
709826

@@ -919,20 +1036,28 @@ export default class CodeEditor extends React.Component {
9191036
}
9201037

9211038
render () {
922-
const {className, fontSize} = this.props
1039+
const {
1040+
className,
1041+
fontSize
1042+
} = this.props
9231043
const fontFamily = normalizeEditorFontFamily(this.props.fontFamily)
9241044
const width = this.props.width
925-
return (
926-
<div
927-
className={className == null ? 'CodeEditor' : `CodeEditor ${className}`}
928-
ref='root'
929-
tabIndex='-1'
930-
style={{
931-
fontFamily,
932-
fontSize: fontSize,
933-
width: width
934-
}}
935-
onDrop={e => this.handleDropImage(e)}
1045+
return (<
1046+
div className={
1047+
className == null ? 'CodeEditor' : `CodeEditor ${className}`
1048+
}
1049+
ref='root'
1050+
tabIndex='-1'
1051+
style={
1052+
{
1053+
fontFamily,
1054+
fontSize: fontSize,
1055+
width: width
1056+
}
1057+
}
1058+
onDrop={
1059+
e => this.handleDropImage(e)
1060+
}
9361061
/>
9371062
)
9381063
}

browser/components/MarkdownEditor.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ class MarkdownEditor extends React.Component {
293293
enableRulers={config.editor.enableRulers}
294294
rulers={config.editor.rulers}
295295
displayLineNumbers={config.editor.displayLineNumbers}
296+
matchingPairs={config.editor.matchingPairs}
297+
matchingTriples={config.editor.matchingTriples}
298+
explodingPairs={config.editor.explodingPairs}
296299
scrollPastEnd={config.editor.scrollPastEnd}
297300
storageKey={storageKey}
298301
noteKey={noteKey}

browser/components/MarkdownSplitEditor.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@ class MarkdownSplitEditor extends React.Component {
160160
fontFamily={config.editor.fontFamily}
161161
fontSize={editorFontSize}
162162
displayLineNumbers={config.editor.displayLineNumbers}
163+
matchingPairs={config.editor.matchingPairs}
164+
matchingTriples={config.editor.matchingTriples}
165+
explodingPairs={config.editor.explodingPairs}
163166
indentType={config.editor.indentType}
164167
indentSize={editorIndentSize}
165168
enableRulers={config.editor.enableRulers}

browser/main/Detail/SnippetNoteDetail.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,9 @@ class SnippetNoteDetail extends React.Component {
722722
indentType={config.editor.indentType}
723723
indentSize={editorIndentSize}
724724
displayLineNumbers={config.editor.displayLineNumbers}
725+
matchingPairs={config.editor.matchingPairs}
726+
matchingTriples={config.editor.matchingTriples}
727+
explodingPairs={config.editor.explodingPairs}
725728
keyMap={config.editor.keyMap}
726729
scrollPastEnd={config.editor.scrollPastEnd}
727730
fetchUrlTitle={config.editor.fetchUrlTitle}

0 commit comments

Comments
 (0)