Skip to content

Commit

Permalink
Merge pull request #290 from mjmlio/fix-273
Browse files Browse the repository at this point in the history
Fix 273
  • Loading branch information
iRyusa authored Jul 2, 2019
2 parents 4779451 + 0f17644 commit 0547044
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/components/FileEditor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import 'helpers/codemirror-util-autoformat'

import isOldSyntax from 'helpers/detectOldMJMLSyntax'

import { codeMirrorCtrlD, codeMirrorDuplicate } from 'helpers/codemirror-shortcuts'

import {
completeAfter,
completeIfAfterLt,
Expand Down Expand Up @@ -177,6 +179,14 @@ class FileEditor extends Component {
} catch (e) {} // eslint-disable-line
}

handleCtrlD(cm) {
codeMirrorCtrlD(cm, this._codeMirror)
}

handleCtrlShiftD(cm) {
codeMirrorDuplicate(cm, this._codeMirror)
}

initEditor() {
if (!this._textarea) {
return
Expand Down Expand Up @@ -215,6 +225,10 @@ class FileEditor extends Component {
"' '": cm => completeIfInTag(CodeMirror, cm),
"'='": cm => completeIfInTag(CodeMirror, cm),
'Ctrl-Space': 'autocomplete',
'Ctrl-D': cm => this.handleCtrlD(cm),
'Cmd-D': cm => this.handleCtrlD(cm),
'Shift-Ctrl-D': cm => this.handleCtrlShiftD(cm),
'Shift-Cmd-D': cm => this.handleCtrlShiftD(cm),
/* eslint-enable quotes */
},
lint: this.handleValidate,
Expand Down
121 changes: 121 additions & 0 deletions src/helpers/codemirror-shortcuts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { last, maxBy } from 'lodash'

export const codeMirrorCtrlD = (cm, doc) => {
if (!cm.somethingSelected()) {
// If nothing selected yet, select the word around the cursor
const { ch, line } = cm.getCursor()
const lineContent = cm.getLine(line)
const reg = /([\d\w-_]+)/g
let found = false
let match

// eslint-disable-next-line no-cond-assign
while (!found && (match = reg.exec(lineContent))) {
if (ch >= match.index && ch <= reg.lastIndex) {
found = true

cm.setSelection(
{
line,
ch: match.index,
},
{
line,
ch: reg.lastIndex,
},
)
}
}
} else {
// Search and select next occurence
const selectionValue = cm.getSelections()[0]
const selections = cm.listSelections()
const lastSelection = last(selections)

// don't support if multiline
if (lastSelection.anchor.line !== lastSelection.head.line) return

const lastPos = maxBy([lastSelection.head, lastSelection.anchor], 'ch')
let lineNb = lastPos.line
let found = false

const handleLine = ({ text }) => {
if (!found) {
let index

if (lineNb === lastPos.line) {
index = text.substring(lastPos.ch).indexOf(selectionValue)

if (index !== -1) index += lastPos.ch
} else {
index = text.indexOf(selectionValue)
}

if (index !== -1) {
found = true
cm.setSelections(
[
...selections,
{
anchor: {
line: lineNb,
ch: index,
},
head: {
line: lineNb,
ch: index + selectionValue.length,
},
},
],
selections.length,
)
}
}
lineNb++
}

doc.eachLine(lastPos.line, cm.lastLine(), handleLine)

// Start again from beginning
if (!found) {
lineNb = 0
doc.eachLine(0, lastPos.line, handleLine)
}
}
}

export const codeMirrorDuplicate = (cm, doc) => {
if (!cm.somethingSelected()) {
// If nothing selected, duplicate current line
const { line } = cm.getCursor()
const lineContent = cm.getLine(line)

doc.replaceRange(`${lineContent}\n`, { line, ch: 0 })
return
}

const selections = cm.listSelections()

selections.forEach((selection, i) => {
// Get up-to-date selection because previous loops changed line numbers
const select = i === 0 ? selection : cm.listSelections()[i]

// if single line, duplicate line
if (select.anchor.line === select.head.line) {
const { line } = select.head
const lineContent = cm.getLine(line)

doc.replaceRange(`${lineContent}\n`, { line, ch: 0 })
return
}

// if multiline, duplicate all lines of the selection (full line, regardless of the selection)
const lineNumbers = [select.head.line, select.anchor.line].sort()
let lines = ''
doc.eachLine(lineNumbers[0], lineNumbers[1] + 1, line => {
lines += `${line.text}\n`
})

doc.replaceRange(`${lines}`, { line: lineNumbers[0], ch: 0 })
})
}

0 comments on commit 0547044

Please sign in to comment.