Merge branch 'master' of github.com:github/atom

This commit is contained in:
Nathan Sobo
2012-04-18 11:09:42 -06:00
5 changed files with 215 additions and 59 deletions

View File

@@ -1,51 +1,109 @@
{View, $$} = require 'space-pen'
$ = require 'jquery'
_ = require 'underscore'
Range = require 'range'
module.exports =
class Autocomplete
class Autocomplete extends View
@content: ->
@div id: 'autocomplete', tabindex: -1, =>
@ol outlet: 'matchesList'
editor: null
currentBuffer: null
wordList = null
wordList: null
wordRegex: /\w+/g
matches: null
currentMatchIndex: null
isAutocompleting: false
constructor: (@editor) ->
@setCurrentBuffer(@editor.buffer)
@editor.on 'autocomplete:complete-word', => @completeWordAtEditorCursorPosition()
initialize: (@editor) ->
requireStylesheet 'autocomplete.css'
@on 'autocomplete:toggle', => @toggle()
@on 'move-up', => @previousMatch()
@on 'move-down', => @nextMatch()
@editor.on 'buffer-path-change', => @setCurrentBuffer(@editor.buffer)
@setCurrentBuffer(@editor.buffer)
setCurrentBuffer: (buffer) ->
@currentBuffer.off '.autocomplete' if @currentBuffer
@currentBuffer = buffer
@currentBuffer.on 'change.autocomplete', => @buildWordList()
@buildWordList()
@currentBuffer.on 'change.autocomplete', =>
@buildWordList() unless @isAutocompleting
toggle: ->
if @parent()[0] then @remove() else @show()
show: ->
@buildMatchList()
@selectMatch(0) if @matches.length > 0
cursorScreenPosition = @editor.getCursorScreenPosition()
{left, top} = @editor.pixelOffsetForScreenPosition(cursorScreenPosition)
@css {left: left, top: top + @editor.lineHeight}
$(document.body).append(this)
@focus()
previousMatch: ->
previousIndex = @currentMatchIndex - 1
previousIndex = @matches.length - 1 if previousIndex < 0
@selectMatch(previousIndex)
nextMatch: ->
nextIndex = (@currentMatchIndex + 1) % @matches.length
@selectMatch(nextIndex)
buildMatchList: ->
selection = @editor.getSelection()
{prefix, suffix} = @prefixAndSuffixOfSelection(selection)
currentWord = prefix + @editor.getSelectedText() + suffix
@matches = (match for match in @wordMatches(prefix, suffix) when match[0] != currentWord)
@matchesList.empty()
if @matches.length > 0
@matchesList.append($$ -> @li match[0]) for match in @matches
else
@matchesList.append($$ -> @li "No matches found")
buildWordList: () ->
@wordList = _.unique(@currentBuffer.getText().match(@wordRegex))
completeWordAtEditorCursorPosition: () ->
selectionRange = @editor.getSelection().getBufferRange()
wordMatches: (prefix, suffix) ->
regex = new RegExp("^#{prefix}(.+)#{suffix}$", "i")
regex.exec(word) for word in @wordList when regex.test(word)
selectMatch: (index) ->
@currentMatchIndex = index
@matchesList.find("li").removeClass "selected"
@matchesList.find("li:eq(#{index})").addClass "selected"
@completeUsingMatch(index)
completeUsingMatch: (matchIndex) ->
match = @matches[matchIndex]
selection = @editor.getSelection()
startPosition = selection.getBufferRange().start
@isAutocompleting = true
@editor.insertText(match[1])
@editor.setSelectionBufferRange([startPosition, [startPosition.row, startPosition.column + match[1].length]])
@isAutocompleting = false
prefixAndSuffixOfSelection: (selection) ->
selectionRange = selection.getBufferRange()
lineRange = [[selectionRange.start.row, 0], [selectionRange.end.row, @editor.lineLengthForBufferRow(selectionRange.end.row)]]
[prefix, suffix] = ["", ""]
@currentBuffer.scanInRange @wordRegex, lineRange, (match, range, {stop}) ->
stop() if range.start.isGreaterThan(selectionRange.end)
if range.intersectsWith(selectionRange)
prefixOffset = selectionRange.start.column - range.start.column
suffixOffset = selectionRange.end.column - range.end.column
if range.start.isLessThan(selectionRange.start)
prefix = match[0][0...prefixOffset]
prefix = match[0][0...prefixOffset] if range.start.isLessThan(selectionRange.start)
suffix = match[0][suffixOffset..] if range.end.isGreaterThan(selectionRange.end)
if range.end.isGreaterThan(selectionRange.end)
suffix = match[0][suffixOffset..]
stop()
for match in @matches(prefix, suffix)
continue if match[0] == prefix + @editor.getSelectedText() + suffix
startPosition = @editor.getSelection().getBufferRange().start
@editor.insertText(match[1])
@editor.setSelectionBufferRange([startPosition, [startPosition.row, startPosition.column + match[1].length]])
break
matches: (prefix, suffix) ->
regex = new RegExp("^#{prefix}(.+)#{suffix}$", "i")
regex.exec(word) for word in @wordList when regex.test(word)
{prefix, suffix}

View File

@@ -379,6 +379,11 @@ class Editor extends View
position = Point.fromObject(position)
{ top: position.row * @lineHeight, left: position.column * @charWidth }
pixelOffsetForScreenPosition: (position) ->
{top, left} = @pixelPositionForScreenPosition(position)
offset = @lines.offset()
{top: top + offset.top, left: left + offset.left}
screenPositionFromPixelPosition: ({top, left}) ->
screenPosition = new Point(Math.floor(top / @lineHeight), Math.floor(left / @charWidth))

View File

@@ -1,2 +1,2 @@
window.keymap.bindKeys '.editor',
'escape': 'autocomplete:complete-word'
'escape': 'autocomplete:toggle'