@@ -38,6 +38,7 @@ export default class CodeEditor extends React.Component {
38
38
trailing : true
39
39
} )
40
40
this . changeHandler = ( editor , changeObject ) => this . handleChange ( editor , changeObject )
41
+ this . highlightHandler = ( editor , changeObject ) => this . handleHighlight ( editor , changeObject )
41
42
this . focusHandler = ( ) => {
42
43
ipcRenderer . send ( 'editor:focused' , true )
43
44
}
@@ -177,6 +178,9 @@ export default class CodeEditor extends React.Component {
177
178
}
178
179
}
179
180
} ,
181
+ 'Cmd-Left' : function ( cm ) {
182
+ cm . execCommand ( 'goLineLeft' )
183
+ } ,
180
184
'Cmd-T' : function ( cm ) {
181
185
// Do nothing
182
186
} ,
@@ -235,6 +239,7 @@ export default class CodeEditor extends React.Component {
235
239
this . editor = CodeMirror ( this . refs . root , {
236
240
rulers : buildCMRulers ( rulers , enableRulers ) ,
237
241
value : this . props . value ,
242
+ linesHighlighted : this . props . linesHighlighted ,
238
243
lineNumbers : this . props . displayLineNumbers ,
239
244
lineWrapping : true ,
240
245
theme : this . props . theme ,
@@ -261,6 +266,7 @@ export default class CodeEditor extends React.Component {
261
266
this . editor . on ( 'focus' , this . focusHandler )
262
267
this . editor . on ( 'blur' , this . blurHandler )
263
268
this . editor . on ( 'change' , this . changeHandler )
269
+ this . editor . on ( 'gutterClick' , this . highlightHandler )
264
270
this . editor . on ( 'paste' , this . pasteHandler )
265
271
if ( this . props . switchPreview !== 'RIGHTCLICK' ) {
266
272
this . editor . on ( 'contextmenu' , this . contextMenuHandler )
@@ -339,6 +345,8 @@ export default class CodeEditor extends React.Component {
339
345
this . setState ( {
340
346
clientWidth : this . refs . root . clientWidth
341
347
} )
348
+
349
+ this . initialHighlighting ( )
342
350
}
343
351
344
352
expandSnippet ( line , cursor , cm , snippets ) {
@@ -537,12 +545,96 @@ export default class CodeEditor extends React.Component {
537
545
538
546
handleChange ( editor , changeObject ) {
539
547
spellcheck . handleChange ( editor , changeObject )
548
+
549
+ this . updateHighlight ( editor , changeObject )
550
+
540
551
this . value = editor . getValue ( )
541
552
if ( this . props . onChange ) {
542
553
this . props . onChange ( editor )
543
554
}
544
555
}
545
556
557
+ incrementLines ( start , linesAdded , linesRemoved , editor ) {
558
+ let highlightedLines = editor . options . linesHighlighted
559
+
560
+ const totalHighlightedLines = highlightedLines . length
561
+
562
+ let offset = linesAdded - linesRemoved
563
+
564
+ // Store new items to be added as we're changing the lines
565
+ let newLines = [ ]
566
+
567
+ let i = totalHighlightedLines
568
+
569
+ while ( i -- ) {
570
+ const lineNumber = highlightedLines [ i ]
571
+
572
+ // Interval that will need to be updated
573
+ // Between start and (start + offset) remove highlight
574
+ if ( lineNumber >= start ) {
575
+ highlightedLines . splice ( highlightedLines . indexOf ( lineNumber ) , 1 )
576
+
577
+ // Lines that need to be relocated
578
+ if ( lineNumber >= ( start + linesRemoved ) ) {
579
+ newLines . push ( lineNumber + offset )
580
+ }
581
+ }
582
+ }
583
+
584
+ // Adding relocated lines
585
+ highlightedLines . push ( ...newLines )
586
+
587
+ if ( this . props . onChange ) {
588
+ this . props . onChange ( editor )
589
+ }
590
+ }
591
+
592
+ handleHighlight ( editor , changeObject ) {
593
+ const lines = editor . options . linesHighlighted
594
+
595
+ if ( ! lines . includes ( changeObject ) ) {
596
+ lines . push ( changeObject )
597
+ editor . addLineClass ( changeObject , 'text' , 'CodeMirror-activeline-background' )
598
+ } else {
599
+ lines . splice ( lines . indexOf ( changeObject ) , 1 )
600
+ editor . removeLineClass ( changeObject , 'text' , 'CodeMirror-activeline-background' )
601
+ }
602
+ if ( this . props . onChange ) {
603
+ this . props . onChange ( editor )
604
+ }
605
+ }
606
+
607
+ updateHighlight ( editor , changeObject ) {
608
+ const linesAdded = changeObject . text . length - 1
609
+ const linesRemoved = changeObject . removed . length - 1
610
+
611
+ // If no lines added or removed return
612
+ if ( linesAdded === 0 && linesRemoved === 0 ) {
613
+ return
614
+ }
615
+
616
+ let start = changeObject . from . line
617
+
618
+ switch ( changeObject . origin ) {
619
+ case '+insert", "undo' :
620
+ start += 1
621
+ break
622
+
623
+ case 'paste' :
624
+ case '+delete' :
625
+ case '+input' :
626
+ if ( changeObject . to . ch !== 0 || changeObject . from . ch !== 0 ) {
627
+ start += 1
628
+ }
629
+ break
630
+
631
+ default :
632
+ return
633
+ }
634
+
635
+ this . incrementLines ( start , linesAdded , linesRemoved , editor )
636
+ }
637
+
546
638
moveCursorTo ( row , col ) { }
547
639
548
640
scrollToLine ( event , num ) {
@@ -567,6 +659,7 @@ export default class CodeEditor extends React.Component {
567
659
this . value = this . props . value
568
660
this . editor . setValue ( this . props . value )
569
661
this . editor . clearHistory ( )
662
+ this . restartHighlighting ( )
570
663
this . editor . on ( 'change' , this . changeHandler )
571
664
this . editor . refresh ( )
572
665
}
@@ -758,6 +851,29 @@ export default class CodeEditor extends React.Component {
758
851
} )
759
852
}
760
853
854
+ initialHighlighting ( ) {
855
+ if ( this . editor . options . linesHighlighted == null ) {
856
+ return
857
+ }
858
+
859
+ const totalHighlightedLines = this . editor . options . linesHighlighted . length
860
+ const totalAvailableLines = this . editor . lineCount ( )
861
+
862
+ for ( let i = 0 ; i < totalHighlightedLines ; i ++ ) {
863
+ const lineNumber = this . editor . options . linesHighlighted [ i ]
864
+ if ( lineNumber > totalAvailableLines ) {
865
+ // make sure that we skip the invalid lines althrough this case should not be happened.
866
+ continue
867
+ }
868
+ this . editor . addLineClass ( lineNumber , 'text' , 'CodeMirror-activeline-background' )
869
+ }
870
+ }
871
+
872
+ restartHighlighting ( ) {
873
+ this . editor . options . linesHighlighted = this . props . linesHighlighted
874
+ this . initialHighlighting ( )
875
+ }
876
+
761
877
mapImageResponse ( response , pastedTxt ) {
762
878
return new Promise ( ( resolve , reject ) => {
763
879
try {
0 commit comments