No autocomplete x y, rename Zatanna to Autocomplete

Don’t autocomplete common variables ’x’ or ‘y’:
return if /^x$|^y$/i.test(prefix)
Renaming zatanna to autocomplete

Closes #3865
This commit is contained in:
Matt Lott 2016-08-19 10:46:08 -07:00
parent 47e115a7eb
commit f2597229b5
4 changed files with 43 additions and 40 deletions

View file

@ -103,12 +103,12 @@ module.exports =
'tome:change-config': c.object {title: 'Change Config', description: 'Published when you change your tome settings'}
'tome:update-snippets': c.object {title: 'Update Snippets', description: 'Published when we need to add Zatanna snippets', required: ['propGroups', 'allDocs']},
'tome:update-snippets': c.object {title: 'Update Snippets', description: 'Published when we need to add autocomplete snippets', required: ['propGroups', 'allDocs']},
propGroups: {type: 'object'}
allDocs: {type: 'object'}
language: {type: 'string'}
'tome:insert-snippet': c.object {title: 'Insert Snippet', description: 'Published when we need to insert a Zatanna snippet', required: ['doc', 'language', 'formatted']},
'tome:insert-snippet': c.object {title: 'Insert Snippet', description: 'Published when we need to insert a autocomplete snippet', required: ['doc', 'language', 'formatted']},
doc: {type: 'object'}
language: {type: 'string'}
formatted: {type: 'object'}

View file

@ -12,7 +12,7 @@ LevelComponent = require 'models/LevelComponent'
UserCodeProblem = require 'models/UserCodeProblem'
utils = require 'core/utils'
CodeLog = require 'models/CodeLog'
Zatanna = require './editor/zatanna'
Autocomplete = require './editor/autocomplete'
module.exports = class SpellView extends CocoView
id: 'spell-view'
@ -45,7 +45,7 @@ module.exports = class SpellView extends CocoView
'tome:spell-statement-index-updated': 'onStatementIndexUpdated'
'tome:change-language': 'onChangeLanguage'
'tome:change-config': 'onChangeEditorConfig'
'tome:update-snippets': 'addZatannaSnippets'
'tome:update-snippets': 'addAutocompleteSnippets'
'tome:insert-snippet': 'onInsertSnippet'
'tome:spell-beautify': 'onSpellBeautify'
'tome:maximize-toggled': 'onMaximizeToggled'
@ -459,7 +459,7 @@ module.exports = class SpellView extends CocoView
if (e.command.name is 'insertstring' and intersects()) or
(e.command.name in ['Backspace', 'throttle-backspaces'] and intersectsLeft()) or
(e.command.name is 'del' and intersectsRight())
@zatanna?.off?()
@autocomplete?.off?()
pulseLockedCode()
return false
else if e.command.name in ['enter-skip-delimiters', 'Enter', 'Return']
@ -468,41 +468,41 @@ module.exports = class SpellView extends CocoView
e.editor.navigateLineStart()
return false
else if e.command.name in ['Enter', 'Return'] and not e.editor?.completer?.popup?.isOpen
@zatanna?.on?()
@autocomplete?.on?()
return e.editor.execCommand 'enter-skip-delimiters'
@zatanna?.on?()
@autocomplete?.on?()
e.command.exec e.editor, e.args or {}
initAutocomplete: (@autocomplete) ->
initAutocomplete: (@autocompleteOn) ->
# TODO: Turn on more autocompletion based on level sophistication
# TODO: E.g. using the language default snippets yields a bunch of crazy non-beginner suggestions
# TODO: Options logic shouldn't exist both here and in updateAutocomplete()
return if @spell.language is 'html'
popupFontSizePx = @options.level.get('autocompleteFontSizePx') ? 16
@zatanna = new Zatanna @ace,
@autocomplete = new Autocomplete @ace,
basic: false
liveCompletion: false
snippetsLangDefaults: false
completers:
keywords: false
snippets: @autocomplete
snippets: @autocompleteOn
autoLineEndings:
javascript: ';'
popupFontSizePx: popupFontSizePx
popupLineHeightPx: 1.5 * popupFontSizePx
popupWidthPx: 380
updateAutocomplete: (@autocomplete) ->
@zatanna?.set 'snippets', @autocomplete
updateAutocomplete: (@autocompleteOn) ->
@autocomplete?.set 'snippets', @autocompleteOn
addZatannaSnippets: (e) ->
addAutocompleteSnippets: (e) ->
# Snippet entry format:
# content: code inserted into document
# meta: displayed right-justfied in popup
# name: displayed left-justified in popup, and what's being matched
# tabTrigger: fallback for name field
return unless @zatanna and @autocomplete
@zatanna.addCodeCombatSnippets @options.level, @, e
return unless @autocomplete and @autocompleteOn
@autocomplete.addCodeCombatSnippets @options.level, @, e
translateFindNearest: ->
# If they have advanced glasses but are playing a level which assumes earlier glasses, we'll adjust the sample code to use the more advanced APIs instead.
@ -582,7 +582,7 @@ module.exports = class SpellView extends CocoView
@createTranslationView() unless @translationView
@toolbarView?.toggleFlow false
@updateAether false, false
# @addZatannaSnippets()
# @addAutocompleteSnippets()
@highlightCurrentLine()
cast: (preload=false, realTime=false, justBegin=false) ->
@ -1219,7 +1219,7 @@ module.exports = class SpellView extends CocoView
onChangeLanguage: (e) ->
return unless @spell.canWrite()
@aceSession.setMode utils.aceEditModes[e.language]
@zatanna?.set 'language', utils.aceEditModes[e.language].substr('ace/mode/')
@autocomplete?.set 'language', utils.aceEditModes[e.language].substr('ace/mode/')
wasDefault = @getSource() is @spell.originalSource
@spell.setLanguage e.language
@reloadCode true if wasDefault
@ -1287,7 +1287,7 @@ module.exports = class SpellView extends CocoView
@debugView?.destroy()
@translationView?.destroy()
@toolbarView?.destroy()
@zatanna?.addSnippets [], @editorLang if @editorLang?
@autocomplete?.addSnippets [], @editorLang if @editorLang?
$(window).off 'resize', @onWindowResize
window.clearTimeout @saveSpadeTimeout
@saveSpadeTimeout = null

View file

@ -23,7 +23,7 @@ defaults =
# TODO: Create list of manual test cases
module.exports = class Zatanna
module.exports = class Autocomplete
Tokenizer = ''
BackgroundTokenizer = ''
@ -43,7 +43,7 @@ module.exports = class Zatanna
#TODO: Renable option validation if we care
#validationResult = optionsValidator @options
#unless validationResult.valid
# throw new Error "Invalid Zatanna options: " + JSON.stringify(validationResult.errors, null, 4)
# throw new Error "Invalid Autocomplete options: " + JSON.stringify(validationResult.errors, null, 4)
ace.config.loadModule 'ace/ext/language_tools', () =>
@snippetManager = ace.require('ace/snippets').snippetManager
@ -154,7 +154,7 @@ module.exports = class Zatanna
off: -> @paused = true
doLiveCompletion: (e) =>
# console.log 'Zatanna doLiveCompletion', e
# console.log 'Autocomplete doLiveCompletion', e
return unless @options.basic or @options.liveCompletion or @options.completers.snippets
return if @paused
@ -172,6 +172,9 @@ module.exports = class Zatanna
# Bake a fresh autocomplete every keystroke
editor.completer?.detach() if hasCompleter
# Skip common single letter variable names
return if /^x$|^y$/i.test(prefix)
# Only autocomplete if there's a prefix that can be matched
if (prefix)
unless (editor.completer)
@ -330,7 +333,7 @@ module.exports = class Zatanna
if haveFindNearest and not haveFindNearestEnemy
spellView.translateFindNearest()
# window.zatannaInstance = @zatanna # For debugging. Make sure to not leave active when committing.
# window.AutocompleteInstance = @Autocomplete # For debugging. Make sure to not leave active when committing.
# window.snippetEntries = snippetEntries
lang = utils.aceEditModes[e.language].substr 'ace/mode/'.length
@addSnippets snippetEntries, lang

View file

@ -37,8 +37,8 @@ module.exports = (SnippetManager, autoLineEndings) ->
range = new Range cursor.row, cursor.column - 1 - prevWord.length, cursor.row, cursor.column
editor.session.remove range
else
# console.log "Zatanna cursor.column=#{cursor.column} snippet='#{snippet}' line='#{line}' prevWord='#{prevWord}'"
# console.log "Zatanna prevWordIndex=#{prevWordIndex}"
# console.log "Snippets cursor.column=#{cursor.column} snippet='#{snippet}' line='#{line}' prevWord='#{prevWord}'"
# console.log "Snippets prevWordIndex=#{prevWordIndex}"
# Lookup original completion
# TODO: Can we identify correct completer somehow?
@ -51,10 +51,10 @@ module.exports = (SnippetManager, autoLineEndings) ->
break if originalCompletion
if originalCompletion?
# console.log 'Zatanna original completion', originalCompletion
# console.log 'Snippets original completion', originalCompletion
# Get original snippet prefix (accounting for extra '\n' and possibly autoLineEndings at end)
lang = editor.session.getMode()?.$id?.substr 'ace/mode/'.length
# console.log 'Zatanna lang', lang, autoLineEndings[lang]?.length
# console.log 'Snippets lang', lang, autoLineEndings[lang]?.length
extraEndLength = 1
extraEndLength += autoLineEndings[lang].length if autoLineEndings[lang]?
if snippetIndex = originalCompletion.content.indexOf snippet.substr(0, snippet.length - extraEndLength)
@ -62,21 +62,21 @@ module.exports = (SnippetManager, autoLineEndings) ->
else
originalPrefix = ''
snippetStart = cursor.column - originalPrefix.length
# console.log "Zatanna originalPrefix='#{originalPrefix}' snippetStart=#{snippetStart}"
# console.log "Snippets originalPrefix='#{originalPrefix}' snippetStart=#{snippetStart}"
if snippetStart > 0 and snippetStart <= line.length
extraIndex = snippetStart - 1
# console.log "Zatanna prev char='#{line[extraIndex]}'"
# console.log "Snippets prev char='#{line[extraIndex]}'"
if line[extraIndex] is '.'
# Fuzzy string match previous word before '.', and remove if a match to beginning of snippet
originalObject = originalCompletion.content.substring(0, originalCompletion.content.indexOf('.'))
prevObjectIndex = extraIndex - 1
# console.log "Zatanna prevObjectIndex=#{prevObjectIndex}"
# console.log "Snippets prevObjectIndex=#{prevObjectIndex}"
if prevObjectIndex >= 0 and /\w/.test(line[prevObjectIndex])
prevObjectIndex-- while prevObjectIndex >= 0 and /\w/.test(line[prevObjectIndex])
prevObjectIndex++ if prevObjectIndex < 0 or not /\w/.test(line[prevObjectIndex])
# console.log "Zatanna prevObjectIndex=#{prevObjectIndex} extraIndex=#{extraIndex}"
# console.log "Snippets prevObjectIndex=#{prevObjectIndex} extraIndex=#{extraIndex}"
prevObject = line.substring prevObjectIndex, extraIndex
#TODO: We use to use fuzziac here, but we forgot why. Using
@ -87,7 +87,7 @@ module.exports = (SnippetManager, autoLineEndings) ->
if fuzzer
finalScore = fuzzer.score prevObject
# console.log "Zatanna originalObject='#{originalObject}' prevObject='#{prevObject}'", finalScore
# console.log "Snippets originalObject='#{originalObject}' prevObject='#{prevObject}'", finalScore
if finalScore > 0.5
range = new Range cursor.row, prevObjectIndex, cursor.row, snippetStart
editor.session.remove range
@ -113,7 +113,7 @@ module.exports = (SnippetManager, autoLineEndings) ->
baseInsertSnippet.call @, editor, snippet
getCompletions: (editor, session, pos, prefix, callback) ->
# console.log "Zatanna getCompletions pos.column=#{pos.column} prefix=#{prefix}"
# console.log "Snippets getCompletions pos.column=#{pos.column} prefix=#{prefix}"
# Completion format:
# prefix: text that will be replaced by snippet
# caption: displayed left-justified in popup, and what's being matched
@ -149,7 +149,7 @@ module.exports = (SnippetManager, autoLineEndings) ->
continue unless caption
[snippet, fuzzScore] = scrubSnippet s.content, caption, line, prefix, pos, lang, autoLineEndings, s.captureReturn
completions.push
content: s.content # Used internally by Zatanna, not by ace autocomplete
content: s.content # Used internally by Snippets, not by ace autocomplete
caption: caption
snippet: snippet
score: fuzzScore * s.importance ? 1.0
@ -162,7 +162,7 @@ module.exports = (SnippetManager, autoLineEndings) ->
@completions = _.filter(completions, (x) -> x.caption.indexOf prefix is 0)
return callback null, @completions
# console.log 'Zatanna snippet completions', completions
# console.log 'Snippets snippet completions', completions
@completions = completions
callback null, completions
@ -170,7 +170,7 @@ module.exports = (SnippetManager, autoLineEndings) ->
# TODO: https://github.com/ajaxorg/ace/commit/7b01a4273e91985c9177f53d238d6b83fe99dc56
# TODO: But, if it was we could use this and pass a 'completer: @' property for each completion
# insertMatch: (editor, data) ->
# console.log 'Zatanna snippets insertMatch', editor, data
# console.log 'Snippets snippets insertMatch', editor, data
# if data.snippet
# SnippetManager.insertSnippet editor, data.snippet
# else
@ -193,7 +193,7 @@ getFullIdentifier = (doc, pos) ->
text.substring start, end
scrubSnippet = (snippet, caption, line, input, pos, lang, autoLineEndings, captureReturn) ->
# console.log "Zatanna snippet=#{snippet} caption=#{caption} line=#{line} input=#{input} pos.column=#{pos.column} lang=#{lang}"
# console.log "Snippets snippet=#{snippet} caption=#{caption} line=#{line} input=#{input} pos.column=#{pos.column} lang=#{lang}"
fuzzScore = 0.1
# input will be replaced by snippet
# trim snippet prefix and suffix if already in the document (line)
@ -223,7 +223,7 @@ scrubSnippet = (snippet, caption, line, input, pos, lang, autoLineEndings, captu
# TODO: This is broken for attack(find in Python, but seems ok in JavaScript.
# Don't eat existing matched parentheses
# console.log "Zatanna checking parentheses lineSuffix=#{lineSuffix} pos.column=#{pos.column} input.length=#{input.length}, prevChar=#{line[pos.column - input.length - 1]} line.length=#{line.length} nextChar=#{line[pos.column]}"
# console.log "Snippets checking parentheses lineSuffix=#{lineSuffix} pos.column=#{pos.column} input.length=#{input.length}, prevChar=#{line[pos.column - input.length - 1]} line.length=#{line.length} nextChar=#{line[pos.column]}"
if pos.column - input.length >= 0 and line[pos.column - input.length - 1] is '(' and pos.column < line.length and line[pos.column] is ')' and lineSuffix is ')'
lineSuffix = ''
@ -238,9 +238,9 @@ scrubSnippet = (snippet, caption, line, input, pos, lang, autoLineEndings, captu
# If at end of line
# And, no parentheses are before snippet. E.g. 'if ('
# And, line doesn't start with whitespace followed by 'if ' or 'elif '
# console.log "Zatanna autoLineEndings linePrefixIndex='#{linePrefixIndex}'"
# console.log "Snippets autoLineEndings linePrefixIndex='#{linePrefixIndex}'"
if lineSuffix.length is 0 and /^\s*$/.test line.slice pos.column
# console.log 'Zatanna atLineEnd', pos.column, lineSuffix.length, line.slice(pos.column + lineSuffix.length), line
# console.log 'Snippets atLineEnd', pos.column, lineSuffix.length, line.slice(pos.column + lineSuffix.length), line
toLinePrefix = line.substring 0, linePrefixIndex
if linePrefixIndex < 0 or linePrefixIndex >= 0 and not /[\(\)]/.test(toLinePrefix) and not /^[ \t]*(?:if\b|elif\b)/.test(toLinePrefix)
snippet += autoLineEndings[lang] if snippetLines is 0 and autoLineEndings[lang]
@ -249,7 +249,7 @@ scrubSnippet = (snippet, caption, line, input, pos, lang, autoLineEndings, captu
if captureReturn and /^\s*$/.test(toLinePrefix)
snippet = captureReturn + linePrefix + snippet
# console.log "Zatanna snippetPrefix=#{snippetPrefix} linePrefix=#{linePrefix} snippetSuffix=#{snippetSuffix} lineSuffix=#{lineSuffix} snippet=#{snippet} score=#{fuzzScore}"
# console.log "Snippets snippetPrefix=#{snippetPrefix} linePrefix=#{linePrefix} snippetSuffix=#{snippetSuffix} lineSuffix=#{lineSuffix} snippet=#{snippet} score=#{fuzzScore}"
else
fuzzScore += score snippet, input