mirror of
https://github.com/atom/atom.git
synced 2026-02-09 06:05:11 -05:00
Autocomplete extends View
This commit is contained in:
@@ -1,42 +1,84 @@
|
||||
{View, $$} = require 'space-pen'
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
Range = require 'range'
|
||||
|
||||
module.exports =
|
||||
class Autocomplete extends View
|
||||
@content: ->
|
||||
@div class: 'autocomplete', =>
|
||||
@div id: 'autocomplete', =>
|
||||
@ol outlet: 'matchesList'
|
||||
|
||||
editor: null
|
||||
currentBuffer: null
|
||||
wordList = null
|
||||
wordList: null
|
||||
wordRegex: /\w+/g
|
||||
matches: null
|
||||
isAutocompleting: false
|
||||
|
||||
initialize: (@editor) ->
|
||||
@setCurrentBuffer(@editor.buffer)
|
||||
@editor.on 'autocomplete:complete-word', => @completeWordAtEditorCursorPosition()
|
||||
requireStylesheet 'autocomplete.css'
|
||||
@editor.on 'autocomplete:toggle', => @toggle()
|
||||
@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()
|
||||
|
||||
buildWordList: () ->
|
||||
@wordList = _.unique(@currentBuffer.getText().match(@wordRegex))
|
||||
@currentBuffer.on 'change.autocomplete', =>
|
||||
@buildWordList() unless @isAutocompleting
|
||||
|
||||
completeWord: ->
|
||||
|
||||
toggle: ->
|
||||
if @parent()[0] then @hide() 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)
|
||||
|
||||
hide: ->
|
||||
@remove()
|
||||
|
||||
buildMatchList: ->
|
||||
selection = @editor.getSelection()
|
||||
{prefix, suffix} = @prefixAndSuffixOfSelection(selection)
|
||||
currentWord = prefix + @editor.getSelectedText() + suffix
|
||||
|
||||
for match in @wordMatches(prefix, suffix) when match[0] != currentWord
|
||||
startPosition = selection.getBufferRange().start
|
||||
@editor.insertText(match[1])
|
||||
@editor.setSelectionBufferRange([startPosition, [startPosition.row, startPosition.column + match[1].length]])
|
||||
break
|
||||
@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")
|
||||
|
||||
wordMatches: (prefix, suffix) ->
|
||||
regex = new RegExp("^#{prefix}(.+)#{suffix}$", "i")
|
||||
regex.exec(word) for word in @wordList when regex.test(word)
|
||||
|
||||
selectMatch: (index) ->
|
||||
@matchesList.find("li:eq(#{index})").addClass "selected"
|
||||
@completeUsingMatch(index)
|
||||
|
||||
buildWordList: () ->
|
||||
@wordList = _.unique(@currentBuffer.getText().match(@wordRegex))
|
||||
|
||||
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()
|
||||
@@ -56,7 +98,3 @@ class Autocomplete extends View
|
||||
stop()
|
||||
|
||||
{prefix, suffix}
|
||||
|
||||
wordMatches: (prefix, suffix) ->
|
||||
regex = new RegExp("^#{prefix}(.+)#{suffix}$", "i")
|
||||
regex.exec(word) for word in @wordList when regex.test(word)
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
window.keymap.bindKeys '.editor',
|
||||
'escape': 'autocomplete:complete-word'
|
||||
'escape': 'autocomplete:toggle'
|
||||
|
||||
Reference in New Issue
Block a user