Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions browser/components/CodeEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'
import CodeMirror from 'codemirror'
import 'codemirror/addon/hint/show-hint'
import 'codemirror/addon/hint/show-hint.css'
import 'codemirror/addon/hint/anyword-hint'
import hljs from 'highlight.js'
import 'codemirror-mode-elixir'
import attachmentManagement from 'browser/main/lib/dataApi/attachmentManagement'
Expand Down Expand Up @@ -233,6 +236,17 @@ export default class CodeEditor extends React.Component {
'Cmd-T': function(cm) {
// Do nothing
},
'Ctrl-Space': function(cm) {
const hints = self.getSnippetHints(cm)
if (hints) {
cm.showHint({
hint: function() {
return self.getSnippetHints(cm)
},
completeSingle: false
})
}
},
[translateHotkey(hotkey.insertDate)]: function(cm) {
const dateNow = new Date()
if (self.props.dateFormatISO8601) {
Expand Down Expand Up @@ -569,6 +583,67 @@ export default class CodeEditor extends React.Component {
}
}

getSnippetHints(cm) {
const cursor = cm.getCursor()
const line = cm.getLine(cursor.line)
const end = cursor.ch
let start = end

while (start > 0 && /\w/.test(line.charAt(start - 1))) {
start--
}

const currentWord = line.slice(start, end)
if (currentWord.length === 0) {
return null
}

const lowerWord = currentWord.toLowerCase()
const list = []
const seen = new Set()

const snippets = snippetManager.snippets || []
for (let i = 0; i < snippets.length; i++) {
const snippet = snippets[i]
const prefixes = snippet.prefix || []
for (let j = 0; j < prefixes.length; j++) {
const prefix = prefixes[j]
if (
prefix.toLowerCase().indexOf(lowerWord) === 0 &&
!seen.has(prefix)
) {
seen.add(prefix)
list.push({
text: snippet.content.replace(/:\{\}/g, ''),
displayText: prefix + ' (snippet: ' + snippet.name + ')',
className: 'snippet-hint'
})
}
}
}

const anywordResult = CodeMirror.hint.anyword(cm)
if (anywordResult && anywordResult.list) {
for (let i = 0; i < anywordResult.list.length; i++) {
const word = anywordResult.list[i]
if (!seen.has(word)) {
seen.add(word)
list.push(word)
}
}
}

if (list.length === 0) {
return null
}

return {
list: list,
from: CodeMirror.Pos(cursor.line, start),
to: CodeMirror.Pos(cursor.line, end)
}
}

quitEditor() {
document.querySelector('textarea').blur()
}
Expand Down
31 changes: 31 additions & 0 deletions browser/components/CodeEditor.styl
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,34 @@

.spellcheck-select
border: none

.CodeMirror-hints
position absolute
z-index 100
overflow hidden
list-style none
margin 0
padding 2px
box-shadow 2px 3px 5px rgba(0, 0, 0, 0.2)
border-radius 3px
border 1px solid silver
background white
font-size 90%
font-family monospace
max-height 20em
overflow-y auto

.CodeMirror-hint
margin 0
padding 0 4px
border-radius 2px
white-space pre
color black
cursor pointer

li.CodeMirror-hint-active
background #08f
color white

.snippet-hint
font-style italic