AutoCompleteManager.coffee 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. define [
  2. "auto-complete/SuggestionManager"
  3. "auto-complete/Snippets"
  4. "ace/autocomplete/util"
  5. "ace/autocomplete"
  6. "ace/range"
  7. "ace/ext/language_tools"
  8. ], (SuggestionManager, Snippets, Util, AutoComplete) ->
  9. Range = require("ace/range").Range
  10. Autocomplete = AutoComplete.Autocomplete
  11. Util.retrievePrecedingIdentifier = (text, pos, regex) ->
  12. currentLineOffset = 0
  13. for i in [(pos-1)..0]
  14. if text[i] == "\n"
  15. currentLineOffset = i + 1
  16. break
  17. currentLine = text.slice(currentLineOffset, pos)
  18. fragment = getLastCommandFragment(currentLine) or ""
  19. return fragment
  20. getLastCommandFragment = (lineUpToCursor) ->
  21. if m = lineUpToCursor.match(/(\\[^\\ ]+)$/)
  22. return m[1]
  23. else
  24. return null
  25. class AutoCompleteManager
  26. constructor: (@ide) ->
  27. @aceEditor = @ide.editor.aceEditor
  28. @aceEditor.setOptions({
  29. enableBasicAutocompletion: true,
  30. enableSnippets: true
  31. })
  32. SnippetCompleter =
  33. getCompletions: (editor, session, pos, prefix, callback) ->
  34. callback null, Snippets
  35. @suggestionManager = new SuggestionManager()
  36. @aceEditor.completers = [@suggestionManager, SnippetCompleter]
  37. insertMatch = Autocomplete::insertMatch
  38. editor = @aceEditor
  39. Autocomplete::insertMatch = (data) ->
  40. pos = editor.getCursorPosition()
  41. range = new Range(pos.row, pos.column, pos.row, pos.column + 1)
  42. nextChar = editor.session.getTextRange(range)
  43. # If we are in \begin{it|}, then we need to remove the trailing }
  44. # since it will be adding in with the autocomplete of \begin{item}...
  45. if this.completions.filterText.match(/^\\begin\{/) and nextChar == "}"
  46. editor.session.remove(range)
  47. insertMatch.call editor.completer, data
  48. @bindToEditorEvents()
  49. bindToEditorEvents: () ->
  50. @ide.editor.on "change:doc", (@aceSession) =>
  51. @aceSession.on "change", (change) => @onChange(change)
  52. onChange: (change) ->
  53. cursorPosition = @aceEditor.getCursorPosition()
  54. end = change.data.range.end
  55. # Check that this change was made by us, not a collaborator
  56. # (Cursor is still one place behind)
  57. if end.row == cursorPosition.row and end.column == cursorPosition.column + 1
  58. if change.data.action == "insertText"
  59. range = new Range(end.row, 0, end.row, end.column)
  60. lineUpToCursor = @aceSession.getTextRange(range)
  61. commandFragment = getLastCommandFragment(lineUpToCursor)
  62. if commandFragment? and commandFragment.length > 2
  63. setTimeout () =>
  64. @aceEditor.execCommand("startAutocomplete")
  65. , 0