editor.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /**
  2. * @author oldj
  3. * @blog http://oldj.net
  4. */
  5. 'use strict';
  6. import React from 'react';
  7. import CodeMirror from 'codemirror';
  8. // import '../../../node_modules/codemirror/addon/comment/comment';
  9. import 'codemirror/addon/comment/comment';
  10. import classnames from 'classnames';
  11. import modeHost from './cm_hl';
  12. import m_kw from '../../libs/kw';
  13. import 'codemirror/lib/codemirror.css';
  14. import './editor.less'
  15. export default class Editor extends React.Component {
  16. constructor(props) {
  17. super(props);
  18. this.codemirror = null;
  19. modeHost();
  20. this.marks = [];
  21. this.kw = '';
  22. SH_event.on('search', (kw) => {
  23. this.kw = kw;
  24. this.highlightKeyword();
  25. });
  26. }
  27. highlightKeyword() {
  28. while (this.marks.length > 0) {
  29. this.marks.shift().clear();
  30. }
  31. let code = this.props.code;
  32. let pos = m_kw.findPositions(this.kw, code) || [];
  33. // this.codemirror.markText({line: 6, ch: 16}, {line: 6, ch: 22}, {className: 'cm-hl'});
  34. pos.map((p) => {
  35. this.marks.push(this.codemirror.markText(p[0], p[1], {className: 'cm-hl'}));
  36. });
  37. }
  38. setValue(v) {
  39. this.props.setValue(v);
  40. }
  41. toComment() {
  42. let doc = this.codemirror.getDoc();
  43. let cur = doc.getCursor();
  44. let line = cur.line;
  45. let info = doc.lineInfo(line);
  46. this.codemirror.toggleComment({
  47. line: line,
  48. cur: 0
  49. }, {
  50. line: line,
  51. cur: info.text.length
  52. });
  53. }
  54. componentDidMount() {
  55. // console.log(this.cnt_node, this.cnt_node.value);
  56. this.codemirror = CodeMirror.fromTextArea(this.cnt_node, {
  57. lineNumbers: true,
  58. readOnly: true,
  59. mode: 'host'
  60. });
  61. this.codemirror.setSize('100%', '100%');
  62. this.codemirror.on('change', (a) => {
  63. let v = a.getDoc().getValue();
  64. this.setValue(v);
  65. });
  66. this.codemirror.on('gutterClick', (cm, n) => {
  67. if (this.props.readonly === true) return;
  68. let info = cm.lineInfo(n);
  69. //cm.setGutterMarker(n, "breakpoints", info.gutterMarkers ? null : makeMarker());
  70. let ln = info.text;
  71. if (/^\s*$/.test(ln)) return;
  72. let new_ln;
  73. if (/^#/.test(ln)) {
  74. new_ln = ln.replace(/^#\s*/, '');
  75. } else {
  76. new_ln = '# ' + ln;
  77. }
  78. this.codemirror.getDoc().replaceRange(new_ln, {line: info.line, ch: 0}, {line: info.line, ch: ln.length});
  79. //app.caculateHosts();
  80. });
  81. ipcRenderer.on('to_comment', () => {
  82. this.toComment();
  83. });
  84. }
  85. componentWillReceiveProps(next_props) {
  86. // console.log(next_props);
  87. this.codemirror.getDoc().setValue(next_props.code);
  88. this.codemirror.setOption('readOnly', next_props.readonly);
  89. setTimeout(() => {
  90. this.highlightKeyword();
  91. }, 100);
  92. }
  93. render() {
  94. return (
  95. <div id="sh-editor" className={classnames({
  96. readonly: this.props.readonly
  97. })}>
  98. <textarea
  99. ref={(c) => this.cnt_node = c}
  100. defaultValue={this.props.code || ''}
  101. />
  102. </div>
  103. );
  104. }
  105. }