Merge pull request #155 from stuartquin/tab-autocomplete

Issue #29 Command and file autocomplete
This commit is contained in:
Jasper v. B 2016-08-14 21:51:43 +02:00 committed by GitHub
commit 25ce6b59fd
4 changed files with 179 additions and 0 deletions

74
lib/autocomplete.coffee Normal file
View file

@ -0,0 +1,74 @@
fs = require 'fs'
path = require 'path'
os = require 'os'
Ex = require './ex'
module.exports =
class AutoComplete
constructor: (commands) ->
@commands = commands
@resetCompletion()
resetCompletion: () ->
@autoCompleteIndex = 0
@autoCompleteText = null
@completions = []
expandTilde: (filePath) ->
if filePath.charAt(0) == '~'
return os.homedir() + filePath.slice(1)
else
return filePath
getAutocomplete: (text) ->
if !@autoCompleteText
@autoCompleteText = text
parts = @autoCompleteText.split(' ')
cmd = parts[0]
if parts.length > 1
filePath = parts.slice(1).join(' ')
return @getCompletion(() => @getFilePathCompletion(cmd, filePath))
else
return @getCompletion(() => @getCommandCompletion(cmd))
filterByPrefix: (commands, prefix) ->
commands.sort().filter((f) => f.startsWith(prefix))
getCompletion: (completeFunc) ->
if @completions.length == 0
@completions = completeFunc()
if @completions.length
complete = @completions[@autoCompleteIndex % @completions.length]
@autoCompleteIndex++
# Only one result so lets return this directory
if complete.endsWith('/') && @completions.length == 1
@resetCompletion()
return complete
getCommandCompletion: (command) ->
return @filterByPrefix(@commands, command)
getFilePathCompletion: (command, filePath) ->
filePath = @expandTilde(filePath)
if filePath.endsWith(path.sep)
basePath = path.dirname(filePath + '.')
baseName = ''
else
basePath = path.dirname(filePath)
baseName = path.basename(filePath)
files = fs.readdirSync(basePath)
return @filterByPrefix(files, baseName).map((f) =>
filePath = path.join(basePath, f)
if fs.lstatSync(filePath).isDirectory()
return command + ' ' + filePath + path.sep
else
return command + ' ' + filePath
)

View file

@ -1,4 +1,6 @@
{ViewModel, Input} = require './view-model'
AutoComplete = require './autocomplete'
Ex = require './ex'
module.exports =
class ExViewModel extends ViewModel
@ -6,15 +8,31 @@ class ExViewModel extends ViewModel
super(@exCommand, class: 'command')
@historyIndex = -1
@view.editorElement.addEventListener('keydown', @tabAutocomplete)
atom.commands.add(@view.editorElement, 'core:move-up', @increaseHistoryEx)
atom.commands.add(@view.editorElement, 'core:move-down', @decreaseHistoryEx)
@autoComplete = new AutoComplete(Ex.getCommands())
restoreHistory: (index) ->
@view.editorElement.getModel().setText(@history(index).value)
history: (index) ->
@exState.getExHistoryItem(index)
tabAutocomplete: (event) =>
if event.keyCode == 9
event.stopPropagation()
event.preventDefault()
completed = @autoComplete.getAutocomplete(@view.editorElement.getModel().getText())
if completed
@view.editorElement.getModel().setText(completed)
return false
else
@autoComplete.resetCompletion()
increaseHistoryEx: =>
if @history(@historyIndex + 1)?
@historyIndex += 1

View file

@ -118,6 +118,11 @@ class Ex
@registerAlias: (alias, name) =>
@singleton()[alias] = (args) => @singleton()[name](args)
@getCommands: () =>
Object.keys(Ex.singleton()).concat(Object.keys(Ex.prototype)).filter((cmd, index, list) ->
list.indexOf(cmd) == index
)
quit: ->
atom.workspace.getActivePane().destroyActiveItem()