Editor.jsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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 m_kw from './kw'
  12. import Agent from '../Agent'
  13. import * as func from '../libs/search'
  14. import 'codemirror/lib/codemirror.css'
  15. import styles from './Editor.less'
  16. import modeHosts from './cm_hl'
  17. modeHosts()
  18. export default class Editor extends React.Component {
  19. constructor (props) {
  20. super(props)
  21. this.codemirror = null
  22. this.state = {
  23. marks: [],
  24. pos: [],
  25. search_kw: ''
  26. }
  27. }
  28. //highlightKeyword () {
  29. // while (this.marks.length > 0) {
  30. // this.marks.shift().clear()
  31. // }
  32. //
  33. // let code = this.props.code
  34. // let pos = m_kw.findPositions(this.kw, code) || []
  35. // // this.codemirror.markText({line: 6, ch: 16}, {line: 6, ch: 22}, {className: 'cm-hl'});
  36. //
  37. // pos.map((p) => {
  38. // this.marks.push(this.codemirror.markText(p[0], p[1], {className: 'cm-hl'}))
  39. // })
  40. //}
  41. doSearch () {
  42. let {marks, search_kw} = this.state
  43. while (marks.length > 0) {
  44. marks.shift().clear()
  45. }
  46. let pos = []
  47. let {code} = this.props
  48. if (search_kw && code) {
  49. pos = m_kw.findPositions(search_kw, code)
  50. pos.map(p => {
  51. marks.push(this.codemirror.markText(p[0], p[1], {className: 'cm-hl'}))
  52. })
  53. }
  54. let doc = this.codemirror.getDoc()
  55. let cursor = doc.getCursor()
  56. this.setState({marks, pos}, () => {
  57. Agent.emit('search:state', {
  58. count: marks.length,
  59. pos: pos.slice(0),
  60. has_next: !!this.getNext(),
  61. has_previous: !!this.getPrevious(),
  62. cursor
  63. })
  64. })
  65. }
  66. setValue (v) {
  67. this.props.setValue(v)
  68. }
  69. toComment () {
  70. let doc = this.codemirror.getDoc()
  71. let cur = doc.getCursor()
  72. let line = cur.line
  73. let info = doc.lineInfo(line)
  74. this.codemirror.toggleComment({
  75. line: line,
  76. cur: 0
  77. }, {
  78. line: line,
  79. cur: info.text.length
  80. })
  81. }
  82. getNext () {
  83. let doc = this.codemirror.getDoc()
  84. let cursor = doc.getCursor()
  85. let {pos} = this.state
  86. let next_pos = func.getNextPos(pos, cursor)
  87. //console.log(next_pos)
  88. return next_pos
  89. }
  90. gotoNext () {
  91. this.docSelect(this.getNext())
  92. }
  93. getPrevious () {
  94. let doc = this.codemirror.getDoc()
  95. let cursor = doc.getCursor()
  96. let {pos} = this.state
  97. let prev_pos = func.getPreviousPos(pos, cursor)
  98. //console.log(next_pos)
  99. return prev_pos
  100. }
  101. gotoPrevious () {
  102. this.docSelect(this.getPrevious())
  103. }
  104. docSelect (pos) {
  105. console.log(pos)
  106. if (!pos || !Array.isArray(pos)) return
  107. let doc = this.codemirror.getDoc()
  108. doc.setCursor(pos[1])
  109. doc.setSelection(pos[0], pos[1])
  110. Agent.emit('search:state', {
  111. has_next: !!this.getNext(),
  112. has_previous: !!this.getPrevious()
  113. })
  114. }
  115. componentDidMount () {
  116. // console.log(this.cnt_node, this.cnt_node.value);
  117. this.codemirror = CodeMirror.fromTextArea(this.cnt_node, {
  118. lineNumbers: true,
  119. readOnly: true,
  120. mode: 'hosts'
  121. })
  122. this.codemirror.setSize('100%', '100%')
  123. this.codemirror.on('change', (a) => {
  124. let v = a.getDoc().getValue()
  125. this.setValue(v)
  126. })
  127. this.codemirror.on('gutterClick', (cm, n) => {
  128. if (this.props.readonly === true) return
  129. let info = cm.lineInfo(n)
  130. //cm.setGutterMarker(n, "breakpoints", info.gutterMarkers ? null : makeMarker());
  131. let ln = info.text
  132. if (/^\s*$/.test(ln)) return
  133. let new_ln
  134. if (/^#/.test(ln)) {
  135. new_ln = ln.replace(/^#\s*/, '')
  136. } else {
  137. new_ln = '# ' + ln
  138. }
  139. this.codemirror.getDoc()
  140. .replaceRange(new_ln, {line: info.line, ch: 0}, {
  141. line: info.line,
  142. ch: ln.length
  143. })
  144. //app.caculateHosts();
  145. })
  146. Agent.on('to_comment', () => {
  147. this.toComment()
  148. })
  149. Agent.on('search:goto_previous', () => this.gotoPrevious())
  150. Agent.on('search:goto_next', () => this.gotoNext())
  151. Agent.on('editor:select', pos => this.docSelect(pos))
  152. Agent.on('search:kw', kw => {
  153. //this.highlightKeyword()
  154. this.setState({search_kw: kw}, () => this.doSearch())
  155. })
  156. }
  157. componentWillReceiveProps (next_props) {
  158. //console.log(next_props);
  159. let cm = this.codemirror
  160. let doc = cm.getDoc()
  161. let v = doc.getValue()
  162. if (v !== next_props.code) {
  163. let cursor_pos = doc.getCursor()
  164. doc.setValue(next_props.code)
  165. doc.setCursor(cursor_pos)
  166. }
  167. cm.setOption('readOnly', next_props.readonly)
  168. setTimeout(() => {
  169. //this.highlightKeyword()
  170. this.doSearch()
  171. }, 100)
  172. }
  173. render () {
  174. return (
  175. <div
  176. id="sh-editor"
  177. className={classnames({
  178. [styles.root]: 1,
  179. readonly: this.props.readonly,
  180. [styles.show_search]: this.props.show_search
  181. })}
  182. >
  183. <textarea
  184. ref={(c) => this.cnt_node = c}
  185. defaultValue={this.props.code || ''}
  186. />
  187. </div>
  188. )
  189. }
  190. }